static int regexp_match(krb5_context context, rule_component *rc, char *value) { int code; pkiDebug("%s: checking %s rule '%s' with value '%s'\n", __FUNCTION__, keyword2string(rc->kw_type), rc->regsrc, value); code = regexec(&rc->regexp, value, 0, NULL, 0); pkiDebug("%s: the result is%s a match\n", __FUNCTION__, code == REG_NOMATCH ? " NOT" : ""); return (code == 0 ? 1: 0); }
/* * Returns match_found == 1 only if exactly one certificate matches * the given rule */ static krb5_error_code check_all_certs(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, pkinit_req_crypto_context req_cryptoctx, pkinit_identity_crypto_context id_cryptoctx, krb5_principal princ, rule_set *rs, /* rule to check */ pkinit_cert_matching_data **matchdata, int *match_found, pkinit_cert_matching_data **matching_cert) { krb5_error_code retval; pkinit_cert_matching_data *md; int i; int comp_match = 0; int total_cert_matches = 0; rule_component *rc; int certs_checked = 0; pkinit_cert_matching_data *save_match = NULL; char *princ_string = NULL; char *princ_realm = NULL; if (match_found == NULL || matching_cert == NULL) return EINVAL; *matching_cert = NULL; *match_found = 0; pkiDebug("%s: matching rule relation is %s with %d components\n", __FUNCTION__, relation2string(rs->relation), rs->num_crs); if (princ) { retval = krb5_unparse_name(context, princ, &princ_string); if (retval || princ_string == NULL) { return EINVAL; } princ_realm = strchr(princ_string, '@'); if (princ_realm == NULL) { krb5_free_unparsed_name(context, princ_string); return EINVAL; } *princ_realm++ = '\0'; } /* * Loop through all the certs available and count * how many match the rule */ for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) { pkiDebug("%s: subject: '%s'\n", __FUNCTION__, md->subject_dn); pkiDebug("%s: issuer: '%s'\n", __FUNCTION__, md->issuer_dn); certs_checked++; for (rc = rs->crs; rc != NULL; rc = rc->next) { comp_match = component_match(context, rc, md, princ); if (comp_match) { pkiDebug("%s: match for keyword type %s\n", __FUNCTION__, keyword2string(rc->kw_type)); } if (comp_match && rs->relation == relation_or) { pkiDebug("%s: cert matches rule (OR relation)\n", __FUNCTION__); total_cert_matches++; save_match = md; goto nextcert; } if (!comp_match && rs->relation == relation_and) { pkiDebug("%s: cert does not match rule (AND relation)\n", __FUNCTION__); goto nextcert; } } if (rc == NULL && comp_match) { pkiDebug("%s: cert matches rule (AND relation)\n", __FUNCTION__); total_cert_matches++; save_match = md; } nextcert: continue; } if (princ_string) { krb5_free_unparsed_name(context, princ_string); } pkiDebug("%s: After checking %d certs, we found %d matches\n", __FUNCTION__, certs_checked, total_cert_matches); if (total_cert_matches == 1) { *match_found = 1; *matching_cert = save_match; } retval = 0; pkiDebug("%s: returning %d, match_found %d\n", __FUNCTION__, retval, *match_found); return retval; }
static int component_match(krb5_context context, rule_component *rc, pkinit_cert_matching_data *md, krb5_principal princ) { int match = 0; int i; krb5_principal p; char *princ_string; switch (rc->kwval_type) { case kwvaltype_regexp: switch (rc->kw_type) { case kw_subject: match = regexp_match(context, rc, md->subject_dn); break; case kw_issuer: match = regexp_match(context, rc, md->issuer_dn); break; case kw_san: if (md->sans == NULL) break; for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) { krb5_unparse_name(context, p, &princ_string); match = regexp_match(context, rc, princ_string); krb5_free_unparsed_name(context, princ_string); if (match) break; } break; default: pkiDebug("%s: keyword %s, keyword value %s mismatch\n", __FUNCTION__, keyword2string(rc->kw_type), kwval2string(kwvaltype_regexp)); break; } break; case kwvaltype_list: switch(rc->kw_type) { case kw_eku: pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n", __FUNCTION__, keyword2string(rc->kw_type), rc->eku_bits, md->eku_bits); if ((rc->eku_bits & md->eku_bits) == rc->eku_bits) match = 1; break; case kw_ku: pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n", __FUNCTION__, keyword2string(rc->kw_type), rc->ku_bits, md->ku_bits); if ((rc->ku_bits & md->ku_bits) == rc->ku_bits) match = 1; break; default: pkiDebug("%s: keyword %s, keyword value %s mismatch\n", __FUNCTION__, keyword2string(rc->kw_type), kwval2string(kwvaltype_regexp)); break; } break; case kwvaltype_principal: if (md->sans == NULL) break; #ifdef DEBUG krb5_unparse_name(context, princ, &princ_string); #endif for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) { #ifdef DEBUG char *san_string; krb5_unparse_name(context, p, &san_string); pkiDebug("%s: comparing principal '%s' with cert SAN '%s'\n", __FUNCTION__, princ_string, san_string); #endif if (krb5_principal_compare_flags(context, p, princ, KRB5_PRINCIPAL_COMPARE_CASEFOLD)) { match = 1; break; } if (match) break; } break; default: pkiDebug("%s: unknown keyword value type %d\n", __FUNCTION__, rc->kwval_type); break; } pkiDebug("%s: returning match = %d\n", __FUNCTION__, match); return match; }
static int component_match(krb5_context context, rule_component *rc, pkinit_cert_matching_data *md) { int match = 0; int i; krb5_principal p; char *princ_string; switch (rc->kwval_type) { case kwvaltype_regexp: switch (rc->kw_type) { case kw_subject: match = regexp_match(context, rc, md->subject_dn); break; case kw_issuer: match = regexp_match(context, rc, md->issuer_dn); break; case kw_san: if (md->sans == NULL) break; for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) { krb5_unparse_name(context, p, &princ_string); match = regexp_match(context, rc, princ_string); krb5_free_unparsed_name(context, princ_string); if (match) break; } break; default: pkiDebug("%s: keyword %s, keyword value %s mismatch\n", __FUNCTION__, keyword2string(rc->kw_type), kwval2string(kwvaltype_regexp)); break; } break; case kwvaltype_list: switch(rc->kw_type) { case kw_eku: pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n", __FUNCTION__, keyword2string(rc->kw_type), rc->eku_bits, md->eku_bits); if ((rc->eku_bits & md->eku_bits) == rc->eku_bits) match = 1; break; case kw_ku: pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n", __FUNCTION__, keyword2string(rc->kw_type), rc->ku_bits, md->ku_bits); if ((rc->ku_bits & md->ku_bits) == rc->ku_bits) match = 1; break; default: pkiDebug("%s: keyword %s, keyword value %s mismatch\n", __FUNCTION__, keyword2string(rc->kw_type), kwval2string(kwvaltype_regexp)); break; } break; default: pkiDebug("%s: unknown keyword value type %d\n", __FUNCTION__, rc->kwval_type); break; } pkiDebug("%s: returning match = %d\n", __FUNCTION__, match); return match; }