mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2026-08-13 06:25:00 -05:00
CVE-2020-1722: prevent use of too long passwords
NIST SP 800-63-3B sets a recommendation to have password length upper bound limited in A.2: https://pages.nist.gov/800-63-3/sp800-63b.html#appA Users should be encouraged to make their passwords as lengthy as they want, within reason. Since the size of a hashed password is independent of its length, there is no reason not to permit the use of lengthy passwords (or pass phrases) if the user wishes. Extremely long passwords (perhaps megabytes in length) could conceivably require excessive processing time to hash, so it is reasonable to have some limit. FreeIPA already applied 256 characters limit for non-random passwords set through ipa-getkeytab tool. The limit was not, however, enforced in other places. MIT Kerberos limits the length of the password to 1024 characters in its tools. However, these tools (kpasswd and 'cpw' command of kadmin) do not differentiate between a password larger than 1024 and a password of 1024 characters. As a result, longer passwords are silently cut off. To prevent silent cut off for user passwords, use limit of 1000 characters. Thus, this patch enforces common limit of 1000 characters everywhere: - LDAP-based password changes - LDAP password change control - LDAP ADD and MOD operations on clear-text userPassword - Keytab setting with ipa-getkeytab - Kerberos password setting and changing Fixes: https://pagure.io/freeipa/issue/8268 Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com> Signed-off-by: Rob Crittenden <rcritten@redhat.com> Reviewed-by: Simo Sorce <ssorce@redhat.com> Reviewed-By: Simo Sorce <ssorce@redhat.com>
This commit is contained in:
@@ -1087,3 +1087,12 @@ void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg)
|
||||
*cfg = NULL;
|
||||
};
|
||||
|
||||
int ipapwd_check_max_pwd_len(size_t len, char **errMesg) {
|
||||
if (len > IPAPWD_PASSWORD_MAX_LEN) {
|
||||
LOG("%s\n", ipapwd_password_max_len_errmsg);
|
||||
*errMesg = ipapwd_password_max_len_errmsg;
|
||||
return LDAP_CONSTRAINT_VIOLATION;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -334,6 +334,11 @@ parse_req_done:
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
rc = ipapwd_check_max_pwd_len(strlen(newPasswd), &errMesg);
|
||||
if (rc) {
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
if (oldPasswd == NULL || *oldPasswd == '\0') {
|
||||
/* If user is authenticated, they already gave their password during
|
||||
the bind operation (or used sasl or client cert auth or OS creds) */
|
||||
@@ -1684,6 +1689,14 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
|
||||
} else {
|
||||
|
||||
if (password != NULL) {
|
||||
/* if password was passed-in, check its length */
|
||||
rc = ipapwd_check_max_pwd_len(strlen(password), &err_msg);
|
||||
if (rc) {
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if we are allowed to *write* keys */
|
||||
acl_ok = is_allowed_to_access_attr(pb, bind_dn, target_entry,
|
||||
WRITEKEYS_OP_CHECK, NULL,
|
||||
|
||||
@@ -133,6 +133,7 @@ int ipapwd_set_extradata(const char *dn,
|
||||
time_t unixtime);
|
||||
void ipapwd_free_slapi_value_array(Slapi_Value ***svals);
|
||||
void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg);
|
||||
int ipapwd_check_max_pwd_len(size_t len, char **errMesg);
|
||||
|
||||
/* from encoding.c */
|
||||
struct ipapwd_keyset {
|
||||
|
||||
@@ -278,6 +278,10 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
rc = LDAP_CONSTRAINT_VIOLATION;
|
||||
slapi_ch_free_string(&userpw);
|
||||
} else {
|
||||
rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
userpw = slapi_ch_strdup(userpw_clear);
|
||||
}
|
||||
|
||||
@@ -561,6 +565,11 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
goto done;
|
||||
}
|
||||
bv = lmod->mod_bvalues[0];
|
||||
|
||||
rc = ipapwd_check_max_pwd_len(bv->bv_len, &errMesg);
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
slapi_ch_free_string(&unhashedpw);
|
||||
unhashedpw = slapi_ch_malloc(bv->bv_len+1);
|
||||
if (!unhashedpw) {
|
||||
@@ -783,7 +792,12 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
if (! unhashedpw && (gen_krb_keys || is_smb || is_ipant)) {
|
||||
if ((userpw != NULL) && ('{' == userpw[0])) {
|
||||
if (0 == strncasecmp(userpw, "{CLEAR}", strlen("{CLEAR}"))) {
|
||||
unhashedpw = slapi_ch_strdup(&userpw[strlen("{CLEAR}")]);
|
||||
const char *userpw_clear = &userpw[strlen("{CLEAR}")];
|
||||
rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
unhashedpw = slapi_ch_strdup(userpw_clear);
|
||||
if (NULL == unhashedpw) {
|
||||
LOG_OOM();
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
@@ -1419,6 +1433,8 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
time_t expire_time;
|
||||
char *principal_expire = NULL;
|
||||
struct tm expire_tm;
|
||||
int rc = LDAP_INVALID_CREDENTIALS;
|
||||
char *errMesg = NULL;
|
||||
|
||||
/* get BIND parameters */
|
||||
ret |= slapi_pblock_get(pb, SLAPI_BIND_TARGET_SDN, &target_sdn);
|
||||
@@ -1480,8 +1496,14 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
goto invalid_creds;
|
||||
|
||||
/* Ensure that there is a password. */
|
||||
if (credentials->bv_len == 0)
|
||||
if (credentials->bv_len == 0) {
|
||||
goto invalid_creds;
|
||||
} else {
|
||||
rc = ipapwd_check_max_pwd_len(credentials->bv_len, &errMesg);
|
||||
if (rc) {
|
||||
goto invalid_creds;
|
||||
}
|
||||
}
|
||||
|
||||
/* Authenticate the user. */
|
||||
ret = ipapwd_authenticate(dn, entry, credentials);
|
||||
@@ -1505,8 +1527,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
invalid_creds:
|
||||
slapi_entry_free(entry);
|
||||
slapi_sdn_free(&sdn);
|
||||
slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS,
|
||||
NULL, NULL, 0, NULL);
|
||||
slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user