mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Fix several leaks in ipadb_find_principal
`vals` is often leaked during early exit. Refactor function to use a single exit path to prevent this. Signed-off-by: Robbie Harwood <rharwood@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
committed by
Florence Blanc-Renaud
parent
ab4e910c52
commit
df6a89be51
@@ -1035,100 +1035,96 @@ krb5_error_code ipadb_find_principal(krb5_context kcontext,
|
||||
struct ipadb_context *ipactx;
|
||||
bool found = false;
|
||||
LDAPMessage *le = NULL;
|
||||
struct berval **vals;
|
||||
int i, result;
|
||||
struct berval **vals = NULL;
|
||||
int result;
|
||||
krb5_error_code ret;
|
||||
|
||||
ipactx = ipadb_get_context(kcontext);
|
||||
if (!ipactx) {
|
||||
return KRB5_KDB_DBNOTINITED;
|
||||
ret = KRB5_KDB_DBNOTINITED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
while (!found) {
|
||||
for (le = ldap_first_entry(ipactx->lcontext, res); le != NULL;
|
||||
le = ldap_next_entry(ipactx->lcontext, le)) {
|
||||
vals = ldap_get_values_len(ipactx->lcontext, le, "krbprincipalname");
|
||||
if (vals == NULL)
|
||||
continue;
|
||||
|
||||
if (!le) {
|
||||
le = ldap_first_entry(ipactx->lcontext, res);
|
||||
} else {
|
||||
le = ldap_next_entry(ipactx->lcontext, le);
|
||||
}
|
||||
if (!le) {
|
||||
/* We need to check for a strict match as a '*' in the name may have
|
||||
* caused the ldap server to return multiple entries. */
|
||||
for (int i = 0; vals[i]; i++) {
|
||||
if ((flags & KRB5_KDB_FLAG_ALIAS_OK) == 0) {
|
||||
found = strcmp(vals[i]->bv_val, *principal) == 0;
|
||||
if (found)
|
||||
break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The KDC will accept aliases when doing TGT lookup
|
||||
* (ref_tgt_again in do_tgs_req.c), so use case-insensitive
|
||||
* comparison. */
|
||||
if (ulc_casecmp(vals[i]->bv_val, vals[i]->bv_len, *principal,
|
||||
strlen(*principal), NULL, NULL, &result) != 0) {
|
||||
ret = KRB5_KDB_INTERNAL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (result != 0)
|
||||
continue;
|
||||
|
||||
/* Fix case on the incoming principal to ensure that a valid
|
||||
* name/alias is returned even if krbCanonicalName is not
|
||||
* present. */
|
||||
free(*principal);
|
||||
*principal = strdup(vals[i]->bv_val);
|
||||
if (!*principal) {
|
||||
ret = KRB5_KDB_INTERNAL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
vals = ldap_get_values_len(ipactx->lcontext, le, "krbprincipalname");
|
||||
if (vals == NULL) {
|
||||
if (!found)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we need to check for a strict match as a '*' in the name may have
|
||||
* caused the ldap server to return multiple entries */
|
||||
for (i = 0; vals[i]; i++) {
|
||||
/* KDC will accept aliases when doing TGT lookup (ref_tgt_again in do_tgs_req.c */
|
||||
/* Use case-insensitive comparison in such cases */
|
||||
if ((flags & KRB5_KDB_FLAG_ALIAS_OK) != 0) {
|
||||
if (ulc_casecmp(vals[i]->bv_val, vals[i]->bv_len,
|
||||
(*principal), strlen(*principal),
|
||||
NULL, NULL, &result) != 0)
|
||||
return KRB5_KDB_INTERNAL_ERROR;
|
||||
found = (result == 0);
|
||||
if (found) {
|
||||
/* replace the incoming principal with the value having
|
||||
* the correct case. This ensures that valid name/alias
|
||||
* is returned even if krbCanonicalName is not present
|
||||
*/
|
||||
free(*principal);
|
||||
*principal = strdup(vals[i]->bv_val);
|
||||
if (!(*principal)) {
|
||||
return KRB5_KDB_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
found = (strcmp(vals[i]->bv_val, (*principal)) == 0);
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We need to check if this is the canonical name. */
|
||||
ldap_value_free_len(vals);
|
||||
|
||||
if (!found) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we need to check if this is the canonical name */
|
||||
vals = ldap_get_values_len(ipactx->lcontext, le, "krbcanonicalname");
|
||||
if (vals == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (vals == NULL)
|
||||
break;
|
||||
|
||||
/* Again, if aliases are accepted by KDC, use case-insensitive comparison */
|
||||
if ((flags & KRB5_KDB_FLAG_ALIAS_OK) != 0) {
|
||||
found = true;
|
||||
} else {
|
||||
found = (strcmp(vals[0]->bv_val, (*principal)) == 0);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
/* search does not allow aliases */
|
||||
ldap_value_free_len(vals);
|
||||
continue;
|
||||
/* If aliases aren't accepted by the KDC, use case-sensitive
|
||||
* comparison. */
|
||||
if ((flags & KRB5_KDB_FLAG_ALIAS_OK) == 0) {
|
||||
found = strcmp(vals[0]->bv_val, *principal) == 0;
|
||||
if (!found) {
|
||||
ldap_value_free_len(vals);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
free(*principal);
|
||||
*principal = strdup(vals[0]->bv_val);
|
||||
if (!(*principal)) {
|
||||
return KRB5_KDB_INTERNAL_ERROR;
|
||||
if (!*principal) {
|
||||
ret = KRB5_KDB_INTERNAL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ldap_value_free_len(vals);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found || !le) {
|
||||
return KRB5_KDB_NOENTRY;
|
||||
ret = KRB5_KDB_NOENTRY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
*entry = le;
|
||||
return 0;
|
||||
done:
|
||||
if (vals)
|
||||
ldap_value_free_len(vals);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static krb5_flags maybe_require_preauth(struct ipadb_context *ipactx,
|
||||
|
||||
Reference in New Issue
Block a user