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;
}
示例#4
0
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;
}