Prevent integer overflow when setting krbPasswordExpiration

Since in Kerberos V5 are used 32-bit unix timestamps, setting
maxlife in pwpolicy to values such as 9999 days would cause
integer overflow in krbPasswordExpiration attribute.

This would result into unpredictable behaviour such as users
not being able to log in after password expiration if password
policy was changed (#3114) or new users not being able to log
in at all (#3312).

The timestamp value is truncated to Jan 1, 2038 in ipa-kdc driver.

https://fedorahosted.org/freeipa/ticket/3312
https://fedorahosted.org/freeipa/ticket/3114
This commit is contained in:
Tomas Babej
2013-01-14 10:19:44 -05:00
committed by Martin Kosek
parent 1d35043e46
commit 0e8a329048
5 changed files with 50 additions and 13 deletions

View File

@@ -140,6 +140,8 @@ int ipadb_ldap_attr_to_bool(LDAP *lcontext, LDAPMessage *le,
char *attrname, bool *result);
int ipadb_ldap_attr_to_time_t(LDAP *lcontext, LDAPMessage *le,
char *attrname, time_t *result);
int ipadb_ldap_attr_to_krb5_timestamp(LDAP *lcontext, LDAPMessage *le,
char *attrname, krb5_timestamp *result);
int ipadb_ldap_attr_has_value(LDAP *lcontext, LDAPMessage *le,
char *attrname, char *value);

View File

@@ -480,6 +480,33 @@ int ipadb_ldap_attr_to_time_t(LDAP *lcontext, LDAPMessage *le,
return ret;
}
int ipadb_ldap_attr_to_krb5_timestamp(LDAP *lcontext, LDAPMessage *le,
char *attrname, krb5_timestamp *result)
{
time_t res_time;
long long res_long;
int ret = ipadb_ldap_attr_to_time_t(lcontext, le,
attrname, &res_time);
if (ret) return ret;
/* this will cast correctly maintaing sign to a 64bit variable */
res_long = res_time;
/* For dates beyond IPAPWD_END_OF_TIME, rest_time might oveflow
* on 32-bit platforms. This does not apply for 64-bit platforms.
* However, since krb5 uses 32-bit time representation, we need
* to limit the result.*/
if (res_long < 0 || res_long > IPAPWD_END_OF_TIME) {
*result = IPAPWD_END_OF_TIME; // 1 Jan 2038, 00:00 GMT
} else {
*result = (krb5_timestamp)res_long;
}
return 0;
}
int ipadb_ldap_attr_has_value(LDAP *lcontext, LDAPMessage *le,
char *attrname, char *value)
{

View File

@@ -246,6 +246,11 @@ krb5_error_code ipadb_get_pwd_expiration(krb5_context context,
*expire_time = mod_time;
}
/* in the case of integer owerflow, set expiration to IPAPWD_END_OF_TIME */
if ((*expire_time) < 0 || (*expire_time) > IPAPWD_END_OF_TIME) {
*expire_time = IPAPWD_END_OF_TIME; // 1 Jan 2038, 00:00 GMT
}
kerr = 0;
done:

View File

@@ -237,7 +237,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
krb5_kvno mkvno = 0;
char **restrlist;
char *restring;
time_t restime;
krb5_timestamp restime;
bool resbool;
int result;
int ret;
@@ -286,7 +286,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
*polmask |= MAXRENEWABLEAGE_BIT;
}
ret = ipadb_ldap_attr_to_time_t(lcontext, lentry,
ret = ipadb_ldap_attr_to_krb5_timestamp(lcontext, lentry,
"krbPrincipalexpiration", &restime);
switch (ret) {
case 0:
@@ -298,7 +298,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
goto done;
}
ret = ipadb_ldap_attr_to_time_t(lcontext, lentry,
ret = ipadb_ldap_attr_to_krb5_timestamp(lcontext, lentry,
"krbPasswordExpiration", &restime);
switch (ret) {
case 0:
@@ -310,7 +310,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
goto done;
}
ret = ipadb_ldap_attr_to_time_t(lcontext, lentry,
ret = ipadb_ldap_attr_to_krb5_timestamp(lcontext, lentry,
"krbLastSuccessfulAuth", &restime);
switch (ret) {
case 0:
@@ -322,7 +322,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
goto done;
}
ret = ipadb_ldap_attr_to_time_t(lcontext, lentry,
ret = ipadb_ldap_attr_to_krb5_timestamp(lcontext, lentry,
"krbLastFailedAuth", &restime);
switch (ret) {
case 0:
@@ -471,7 +471,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
ied->pw_history = restrlist;
}
ret = ipadb_ldap_attr_to_time_t(lcontext, lentry,
ret = ipadb_ldap_attr_to_krb5_timestamp(lcontext, lentry,
"krbLastPwdChange", &restime);
if (ret == 0) {
krb5_int32 time32le = htole32((krb5_int32)restime);
@@ -487,7 +487,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
ied->last_pwd_change = restime;
}
ret = ipadb_ldap_attr_to_time_t(lcontext, lentry,
ret = ipadb_ldap_attr_to_krb5_timestamp(lcontext, lentry,
"krbLastAdminUnlock", &restime);
if (ret == 0) {
krb5_int32 time32le = htole32((krb5_int32)restime);

View File

@@ -27,6 +27,9 @@
#define IPAPWD_DEFAULT_PWDLIFE (90 * 24 *3600)
#define IPAPWD_DEFAULT_MINLEN 0
/* 1 Jan 2038, 00:00 GMT */
#define IPAPWD_END_OF_TIME 2145916800
/*
* IMPORTANT: please update error string table in ipa_pwd.c if you change this
* error code table.