krb5_error_code pkinit_libdefault_string(krb5_context context, const krb5_data *realm, const char *option, char **ret_value) { krb5_error_code retval; char **values = NULL; retval = pkinit_libdefault_strings(context, realm, option, &values); if (retval) return retval; if (values[0] == NULL) { retval = ENOENT; } else { *ret_value = strdup(values[0]); if (*ret_value == NULL) retval = ENOMEM; } profile_free_list(values); return retval; }
krb5_error_code pkinit_cert_matching(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, pkinit_req_crypto_context req_cryptoctx, pkinit_identity_crypto_context id_cryptoctx, krb5_principal princ) { krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; int x; char **rules = NULL; rule_set *rs = NULL; int match_found = 0; pkinit_cert_matching_data **matchdata = NULL; pkinit_cert_matching_data *the_matching_cert = NULL; /* If no matching rules, select the default cert and we're done */ pkinit_libdefault_strings(context, krb5_princ_realm(context, princ), KRB5_CONF_PKINIT_CERT_MATCH, &rules); if (rules == NULL) { pkiDebug("%s: no matching rules found in config file\n", __FUNCTION__); retval = crypto_cert_select_default(context, plg_cryptoctx, req_cryptoctx, id_cryptoctx); goto cleanup; } /* parse each rule line one at a time and check all the certs against it */ for (x = 0; rules[x] != NULL; x++) { pkiDebug("%s: Processing rule '%s'\n", __FUNCTION__, rules[x]); /* Free rules from previous time through... */ if (rs != NULL) { free_rule_set(context, rs); rs = NULL; } retval = parse_rule_set(context, rules[x], &rs); if (retval) { if (retval == EINVAL) { pkiDebug("%s: Ignoring invalid rule pkinit_cert_match = '%s'\n", __FUNCTION__, rules[x]); continue; } goto cleanup; } /* * Optimize so that we do not get cert info unless we have * valid rules to check. Once obtained, keep it around * until we are done. */ if (matchdata == NULL) { retval = obtain_all_cert_matching_data(context, plg_cryptoctx, req_cryptoctx, id_cryptoctx, &matchdata); if (retval || matchdata == NULL) { pkiDebug("%s: Error %d obtaining certificate information\n", __FUNCTION__, retval); retval = ENOENT; goto cleanup; } } retval = check_all_certs(context, plg_cryptoctx, req_cryptoctx, id_cryptoctx, princ, rs, matchdata, &match_found, &the_matching_cert); if (retval) { pkiDebug("%s: Error %d, checking certs against rule '%s'\n", __FUNCTION__, retval, rules[x]); goto cleanup; } if (match_found) { pkiDebug("%s: We have an exact match with rule '%s'\n", __FUNCTION__, rules[x]); break; } } if (match_found && the_matching_cert != NULL) { pkiDebug("%s: Selecting the matching cert!\n", __FUNCTION__); retval = crypto_cert_select(context, the_matching_cert); if (retval) { pkiDebug("%s: crypto_cert_select error %d, %s\n", __FUNCTION__, retval, error_message(retval)); goto cleanup; } } else { retval = ENOENT; /* XXX */ goto cleanup; } retval = 0; cleanup: if (rules != NULL) profile_free_list(rules); if (rs != NULL) free_rule_set(context, rs); if (matchdata != NULL) free_all_cert_matching_data(context, matchdata); return retval; }