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:
Robbie Harwood
2020-01-09 16:11:28 -05:00
committed by Florence Blanc-Renaud
parent ab4e910c52
commit df6a89be51

View File

@@ -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,