|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* COPYRIGHT (C) 2007
|
|
Packit |
fd8b60 |
* THE REGENTS OF THE UNIVERSITY OF MICHIGAN
|
|
Packit |
fd8b60 |
* ALL RIGHTS RESERVED
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Permission is granted to use, copy, create derivative works
|
|
Packit |
fd8b60 |
* and redistribute this software and such derivative works
|
|
Packit |
fd8b60 |
* for any purpose, so long as the name of The University of
|
|
Packit |
fd8b60 |
* Michigan is not used in any advertising or publicity
|
|
Packit |
fd8b60 |
* pertaining to the use of distribution of this software
|
|
Packit |
fd8b60 |
* without specific, written prior authorization. If the
|
|
Packit |
fd8b60 |
* above copyright notice or any other identification of the
|
|
Packit |
fd8b60 |
* University of Michigan is included in any copy of any
|
|
Packit |
fd8b60 |
* portion of this software, then the disclaimer below must
|
|
Packit |
fd8b60 |
* also be included.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
|
|
Packit |
fd8b60 |
* FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
|
|
Packit |
fd8b60 |
* PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
|
|
Packit |
fd8b60 |
* MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
Packit |
fd8b60 |
* WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
|
|
Packit |
fd8b60 |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
|
Packit |
fd8b60 |
* REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
|
|
Packit |
fd8b60 |
* FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
|
|
Packit |
fd8b60 |
* CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
|
|
Packit |
fd8b60 |
* OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
|
|
Packit |
fd8b60 |
* IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
|
|
Packit |
fd8b60 |
* SUCH DAMAGES.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include <errno.h>
|
|
Packit |
fd8b60 |
#include <string.h>
|
|
Packit |
fd8b60 |
#include <stdio.h>
|
|
Packit |
fd8b60 |
#include <stdlib.h>
|
|
Packit |
fd8b60 |
#include <unistd.h>
|
|
Packit |
fd8b60 |
#include <regex.h>
|
|
Packit |
fd8b60 |
#include "pkinit.h"
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
typedef struct _pkinit_cert_info pkinit_cert_info;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
typedef enum {
|
|
Packit |
fd8b60 |
kw_undefined = 0,
|
|
Packit |
fd8b60 |
kw_subject = 1,
|
|
Packit |
fd8b60 |
kw_issuer = 2,
|
|
Packit |
fd8b60 |
kw_san = 3,
|
|
Packit |
fd8b60 |
kw_eku = 4,
|
|
Packit |
fd8b60 |
kw_ku = 5
|
|
Packit |
fd8b60 |
} keyword_type;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static char *
|
|
Packit |
fd8b60 |
keyword2string(unsigned int kw)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
switch(kw) {
|
|
Packit |
fd8b60 |
case kw_undefined: return "NONE"; break;
|
|
Packit |
fd8b60 |
case kw_subject: return "SUBJECT"; break;
|
|
Packit |
fd8b60 |
case kw_issuer: return "ISSUER"; break;
|
|
Packit |
fd8b60 |
case kw_san: return "SAN"; break;
|
|
Packit |
fd8b60 |
case kw_eku: return "EKU"; break;
|
|
Packit |
fd8b60 |
case kw_ku: return "KU"; break;
|
|
Packit |
fd8b60 |
default: return "INVALID"; break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
typedef enum {
|
|
Packit |
fd8b60 |
relation_none = 0,
|
|
Packit |
fd8b60 |
relation_and = 1,
|
|
Packit |
fd8b60 |
relation_or = 2
|
|
Packit |
fd8b60 |
} relation_type;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static char *
|
|
Packit |
fd8b60 |
relation2string(unsigned int rel)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
switch(rel) {
|
|
Packit |
fd8b60 |
case relation_none: return "NONE"; break;
|
|
Packit |
fd8b60 |
case relation_and: return "AND"; break;
|
|
Packit |
fd8b60 |
case relation_or: return "OR"; break;
|
|
Packit |
fd8b60 |
default: return "INVALID"; break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
typedef enum {
|
|
Packit |
fd8b60 |
kwvaltype_undefined = 0,
|
|
Packit |
fd8b60 |
kwvaltype_regexp = 1,
|
|
Packit |
fd8b60 |
kwvaltype_list = 2
|
|
Packit |
fd8b60 |
} kw_value_type;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static char *
|
|
Packit |
fd8b60 |
kwval2string(unsigned int kwval)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
switch(kwval) {
|
|
Packit |
fd8b60 |
case kwvaltype_undefined: return "NONE"; break;
|
|
Packit |
fd8b60 |
case kwvaltype_regexp: return "REGEXP"; break;
|
|
Packit |
fd8b60 |
case kwvaltype_list: return "LIST"; break;
|
|
Packit |
fd8b60 |
default: return "INVALID"; break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
struct keyword_desc {
|
|
Packit |
fd8b60 |
const char *value;
|
|
Packit |
fd8b60 |
size_t length;
|
|
Packit |
fd8b60 |
keyword_type kwtype;
|
|
Packit |
fd8b60 |
kw_value_type kwvaltype;
|
|
Packit |
fd8b60 |
} matching_keywords[] = {
|
|
Packit |
fd8b60 |
{ "<KU>", 4, kw_ku, kwvaltype_list },
|
|
Packit |
fd8b60 |
{ "<EKU>", 5, kw_eku, kwvaltype_list },
|
|
Packit |
fd8b60 |
{ "<SAN>", 5, kw_san, kwvaltype_regexp },
|
|
Packit |
fd8b60 |
{ "<ISSUER>", 8, kw_issuer, kwvaltype_regexp },
|
|
Packit |
fd8b60 |
{ "<SUBJECT>", 9, kw_subject, kwvaltype_regexp },
|
|
Packit |
fd8b60 |
{ NULL, 0, kw_undefined, kwvaltype_undefined},
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
struct ku_desc {
|
|
Packit |
fd8b60 |
const char *value;
|
|
Packit |
fd8b60 |
size_t length;
|
|
Packit |
fd8b60 |
unsigned int bitval;
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
struct ku_desc ku_keywords[] = {
|
|
Packit |
fd8b60 |
{ "digitalSignature", 16, PKINIT_KU_DIGITALSIGNATURE },
|
|
Packit |
fd8b60 |
{ "keyEncipherment", 15, PKINIT_KU_KEYENCIPHERMENT },
|
|
Packit |
fd8b60 |
{ NULL, 0, 0 },
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
struct ku_desc eku_keywords[] = {
|
|
Packit |
fd8b60 |
{ "pkinit", 6, PKINIT_EKU_PKINIT },
|
|
Packit |
fd8b60 |
{ "msScLogin", 9, PKINIT_EKU_MSSCLOGIN },
|
|
Packit |
fd8b60 |
{ "clientAuth", 10, PKINIT_EKU_CLIENTAUTH },
|
|
Packit |
fd8b60 |
{ "emailProtection", 15, PKINIT_EKU_EMAILPROTECTION },
|
|
Packit |
fd8b60 |
{ NULL, 0, 0 },
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Rule component */
|
|
Packit |
fd8b60 |
typedef struct _rule_component {
|
|
Packit |
fd8b60 |
struct _rule_component *next;
|
|
Packit |
fd8b60 |
keyword_type kw_type;
|
|
Packit |
fd8b60 |
kw_value_type kwval_type;
|
|
Packit |
fd8b60 |
regex_t regexp; /* Compiled regular expression */
|
|
Packit |
fd8b60 |
char *regsrc; /* The regular expression source (for debugging) */
|
|
Packit |
fd8b60 |
unsigned int ku_bits;
|
|
Packit |
fd8b60 |
unsigned int eku_bits;
|
|
Packit |
fd8b60 |
} rule_component;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Set rule components */
|
|
Packit |
fd8b60 |
typedef struct _rule_set {
|
|
Packit |
fd8b60 |
relation_type relation;
|
|
Packit |
fd8b60 |
int num_crs;
|
|
Packit |
fd8b60 |
rule_component *crs;
|
|
Packit |
fd8b60 |
} rule_set;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
free_rule_component(krb5_context context,
|
|
Packit |
fd8b60 |
rule_component *rc)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
if (rc == NULL)
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (rc->kwval_type == kwvaltype_regexp) {
|
|
Packit |
fd8b60 |
free(rc->regsrc);
|
|
Packit |
fd8b60 |
regfree(&rc->regexp);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
free(rc);
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
free_rule_set(krb5_context context,
|
|
Packit |
fd8b60 |
rule_set *rs)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
rule_component *rc, *trc;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (rs == NULL)
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
for (rc = rs->crs; rc != NULL;) {
|
|
Packit |
fd8b60 |
trc = rc->next;
|
|
Packit |
fd8b60 |
free_rule_component(context, rc);
|
|
Packit |
fd8b60 |
rc = trc;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
free(rs);
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
parse_list_value(krb5_context context,
|
|
Packit |
fd8b60 |
keyword_type type,
|
|
Packit |
fd8b60 |
char *value,
|
|
Packit |
fd8b60 |
rule_component *rc)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code retval;
|
|
Packit |
fd8b60 |
char *comma;
|
|
Packit |
fd8b60 |
struct ku_desc *ku = NULL;
|
|
Packit |
fd8b60 |
int found;
|
|
Packit |
fd8b60 |
size_t len;
|
|
Packit |
fd8b60 |
unsigned int *bitptr;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (value == NULL || value[0] == '\0') {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Missing or empty value for list keyword type %d\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, type);
|
|
Packit |
fd8b60 |
retval = EINVAL;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (type == kw_eku) {
|
|
Packit |
fd8b60 |
bitptr = &rc->eku_bits;
|
|
Packit |
fd8b60 |
} else if (type == kw_ku) {
|
|
Packit |
fd8b60 |
bitptr = &rc->ku_bits;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Unknown list keyword type %d\n", __FUNCTION__, type);
|
|
Packit |
fd8b60 |
retval = EINVAL;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
do {
|
|
Packit |
fd8b60 |
found = 0;
|
|
Packit |
fd8b60 |
comma = strchr(value, ',');
|
|
Packit |
fd8b60 |
if (comma != NULL)
|
|
Packit |
fd8b60 |
len = comma - value;
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
len = strlen(value);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (type == kw_eku) {
|
|
Packit |
fd8b60 |
ku = eku_keywords;
|
|
Packit |
fd8b60 |
} else if (type == kw_ku) {
|
|
Packit |
fd8b60 |
ku = ku_keywords;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (; ku->value != NULL; ku++) {
|
|
Packit |
fd8b60 |
if (strncasecmp(value, ku->value, len) == 0) {
|
|
Packit |
fd8b60 |
*bitptr |= ku->bitval;
|
|
Packit |
fd8b60 |
found = 1;
|
|
Packit |
fd8b60 |
pkiDebug("%s: Found value '%s', bitfield is now 0x%x\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, ku->value, *bitptr);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (found) {
|
|
Packit |
fd8b60 |
value += ku->length;
|
|
Packit |
fd8b60 |
if (*value == ',')
|
|
Packit |
fd8b60 |
value += 1;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Urecognized value '%s'\n", __FUNCTION__, value);
|
|
Packit |
fd8b60 |
retval = EINVAL;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} while (found && *value != '\0');
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
out:
|
|
Packit |
fd8b60 |
pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
parse_rule_component(krb5_context context,
|
|
Packit |
fd8b60 |
const char **rule,
|
|
Packit |
fd8b60 |
int *remaining,
|
|
Packit |
fd8b60 |
rule_component **ret_rule)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code retval;
|
|
Packit |
fd8b60 |
rule_component *rc = NULL;
|
|
Packit |
fd8b60 |
keyword_type kw_type;
|
|
Packit |
fd8b60 |
kw_value_type kwval_type;
|
|
Packit |
fd8b60 |
char err_buf[128];
|
|
Packit |
fd8b60 |
int ret;
|
|
Packit |
fd8b60 |
struct keyword_desc *kw, *nextkw;
|
|
Packit |
fd8b60 |
char *nk;
|
|
Packit |
fd8b60 |
int found_next_kw = 0;
|
|
Packit |
fd8b60 |
char *value = NULL;
|
|
Packit |
fd8b60 |
size_t len;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (kw = matching_keywords; kw->value != NULL; kw++) {
|
|
Packit |
fd8b60 |
if (strncmp(*rule, kw->value, kw->length) == 0) {
|
|
Packit |
fd8b60 |
kw_type = kw->kwtype;
|
|
Packit |
fd8b60 |
kwval_type = kw->kwvaltype;
|
|
Packit |
fd8b60 |
*rule += kw->length;
|
|
Packit |
fd8b60 |
*remaining -= kw->length;
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (kw->value == NULL) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Missing or invalid keyword in rule '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, *rule);
|
|
Packit |
fd8b60 |
retval = ENOENT;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: found keyword '%s'\n", __FUNCTION__, kw->value);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
rc = calloc(1, sizeof(*rc));
|
|
Packit |
fd8b60 |
if (rc == NULL) {
|
|
Packit |
fd8b60 |
retval = ENOMEM;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
rc->next = NULL;
|
|
Packit |
fd8b60 |
rc->kw_type = kw_type;
|
|
Packit |
fd8b60 |
rc->kwval_type = kwval_type;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Before procesing the value for this keyword,
|
|
Packit |
fd8b60 |
* (compiling the regular expression or processing the list)
|
|
Packit |
fd8b60 |
* we need to find the end of it. That means parsing for the
|
|
Packit |
fd8b60 |
* beginning of the next keyword (or the end of the rule).
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
nk = strchr(*rule, '<');
|
|
Packit |
fd8b60 |
while (nk != NULL) {
|
|
Packit |
fd8b60 |
/* Possibly another keyword, check it out */
|
|
Packit |
fd8b60 |
for (nextkw = matching_keywords; nextkw->value != NULL; nextkw++) {
|
|
Packit |
fd8b60 |
if (strncmp(nk, nextkw->value, nextkw->length) == 0) {
|
|
Packit |
fd8b60 |
/* Found a keyword, nk points to the beginning */
|
|
Packit |
fd8b60 |
found_next_kw = 1;
|
|
Packit |
fd8b60 |
break; /* Need to break out of the while! */
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (!found_next_kw)
|
|
Packit |
fd8b60 |
nk = strchr(nk+1, '<'); /* keep looking */
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (nk != NULL && found_next_kw)
|
|
Packit |
fd8b60 |
len = (nk - *rule);
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
len = (*remaining);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (len == 0) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Missing value for keyword '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, kw->value);
|
|
Packit |
fd8b60 |
retval = EINVAL;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
value = calloc(1, len+1);
|
|
Packit |
fd8b60 |
if (value == NULL) {
|
|
Packit |
fd8b60 |
retval = ENOMEM;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
memcpy(value, *rule, len);
|
|
Packit |
fd8b60 |
*remaining -= len;
|
|
Packit |
fd8b60 |
*rule += len;
|
|
Packit |
fd8b60 |
pkiDebug("%s: found value '%s'\n", __FUNCTION__, value);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (kw->kwvaltype == kwvaltype_regexp) {
|
|
Packit |
fd8b60 |
ret = regcomp(&rc->regexp, value, REG_EXTENDED);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
regerror(ret, &rc->regexp, err_buf, sizeof(err_buf));
|
|
Packit |
fd8b60 |
pkiDebug("%s: Error compiling reg-exp '%s': %s\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, value, err_buf);
|
|
Packit |
fd8b60 |
retval = ret;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
rc->regsrc = strdup(value);
|
|
Packit |
fd8b60 |
if (rc->regsrc == NULL) {
|
|
Packit |
fd8b60 |
retval = ENOMEM;
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else if (kw->kwvaltype == kwvaltype_list) {
|
|
Packit |
fd8b60 |
retval = parse_list_value(context, rc->kw_type, value, rc);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Error %d, parsing list values for keyword %s\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, retval, kw->value);
|
|
Packit |
fd8b60 |
goto out;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*ret_rule = rc;
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
out:
|
|
Packit |
fd8b60 |
free(value);
|
|
Packit |
fd8b60 |
if (retval && rc != NULL)
|
|
Packit |
fd8b60 |
free_rule_component(context, rc);
|
|
Packit |
fd8b60 |
pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
parse_rule_set(krb5_context context,
|
|
Packit |
fd8b60 |
const char *rule_in,
|
|
Packit |
fd8b60 |
rule_set **out_rs)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const char *rule;
|
|
Packit |
fd8b60 |
int remaining;
|
|
Packit |
fd8b60 |
krb5_error_code ret, retval;
|
|
Packit |
fd8b60 |
rule_component *rc = NULL, *trc;
|
|
Packit |
fd8b60 |
rule_set *rs;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (rule_in == NULL)
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
rule = rule_in;
|
|
Packit |
fd8b60 |
remaining = strlen(rule);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
rs = calloc(1, sizeof(*rs));
|
|
Packit |
fd8b60 |
if (rs == NULL) {
|
|
Packit |
fd8b60 |
retval = ENOMEM;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
rs->relation = relation_none;
|
|
Packit |
fd8b60 |
if (remaining > 1) {
|
|
Packit |
fd8b60 |
if (rule[0] == '&' && rule[1] == '&') {
|
|
Packit |
fd8b60 |
rs->relation = relation_and;
|
|
Packit |
fd8b60 |
rule += 2;
|
|
Packit |
fd8b60 |
remaining -= 2;
|
|
Packit |
fd8b60 |
} else if (rule_in[0] == '|' && rule_in[1] == '|') {
|
|
Packit |
fd8b60 |
rs->relation = relation_or;
|
|
Packit |
fd8b60 |
rule +=2;
|
|
Packit |
fd8b60 |
remaining -= 2;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
rs->num_crs = 0;
|
|
Packit |
fd8b60 |
while (remaining > 0) {
|
|
Packit |
fd8b60 |
if (rs->relation == relation_none && rs->num_crs > 0) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Assuming AND relation for multiple components in rule '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, rule_in);
|
|
Packit |
fd8b60 |
rs->relation = relation_and;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
ret = parse_rule_component(context, &rule, &remaining, &rc);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
retval = ret;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
pkiDebug("%s: After parse_rule_component, remaining %d, rule '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, remaining, rule);
|
|
Packit |
fd8b60 |
rs->num_crs++;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Chain the new component on the end (order matters since
|
|
Packit |
fd8b60 |
* we can short-circuit an OR or an AND relation if an
|
|
Packit |
fd8b60 |
* earlier check passes
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
for (trc = rs->crs; trc != NULL && trc->next != NULL; trc = trc->next);
|
|
Packit |
fd8b60 |
if (trc == NULL)
|
|
Packit |
fd8b60 |
rs->crs = rc;
|
|
Packit |
fd8b60 |
else {
|
|
Packit |
fd8b60 |
trc->next = rc;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*out_rs = rs;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
if (retval && rs != NULL) {
|
|
Packit |
fd8b60 |
free_rule_set(context, rs);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
regexp_match(krb5_context context, rule_component *rc, char *value)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int code;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: checking %s rule '%s' with value '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, keyword2string(rc->kw_type), rc->regsrc, value);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
code = regexec(&rc->regexp, value, 0, NULL, 0);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: the result is%s a match\n", __FUNCTION__,
|
|
Packit |
fd8b60 |
code == REG_NOMATCH ? " NOT" : "");
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return (code == 0 ? 1: 0);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static int
|
|
Packit |
fd8b60 |
component_match(krb5_context context,
|
|
Packit |
fd8b60 |
rule_component *rc,
|
|
Packit |
fd8b60 |
pkinit_cert_matching_data *md)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int match = 0;
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
char *princ_string;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
switch (rc->kwval_type) {
|
|
Packit |
fd8b60 |
case kwvaltype_regexp:
|
|
Packit |
fd8b60 |
switch (rc->kw_type) {
|
|
Packit |
fd8b60 |
case kw_subject:
|
|
Packit |
fd8b60 |
match = regexp_match(context, rc, md->subject_dn);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
case kw_issuer:
|
|
Packit |
fd8b60 |
match = regexp_match(context, rc, md->issuer_dn);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
case kw_san:
|
|
Packit |
fd8b60 |
for (i = 0; md->sans != NULL && md->sans[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
krb5_unparse_name(context, md->sans[i], &princ_string);
|
|
Packit |
fd8b60 |
match = regexp_match(context, rc, princ_string);
|
|
Packit |
fd8b60 |
krb5_free_unparsed_name(context, princ_string);
|
|
Packit |
fd8b60 |
if (match)
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
for (i = 0; md->upns != NULL && md->upns[i] != NULL; i++) {
|
|
Packit |
fd8b60 |
match = regexp_match(context, rc, md->upns[i]);
|
|
Packit |
fd8b60 |
if (match)
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
default:
|
|
Packit |
fd8b60 |
pkiDebug("%s: keyword %s, keyword value %s mismatch\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, keyword2string(rc->kw_type),
|
|
Packit |
fd8b60 |
kwval2string(kwvaltype_regexp));
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
case kwvaltype_list:
|
|
Packit |
fd8b60 |
switch(rc->kw_type) {
|
|
Packit |
fd8b60 |
case kw_eku:
|
|
Packit |
fd8b60 |
pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, keyword2string(rc->kw_type),
|
|
Packit |
fd8b60 |
rc->eku_bits, md->eku_bits);
|
|
Packit |
fd8b60 |
if ((rc->eku_bits & md->eku_bits) == rc->eku_bits)
|
|
Packit |
fd8b60 |
match = 1;
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
case kw_ku:
|
|
Packit |
fd8b60 |
pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, keyword2string(rc->kw_type),
|
|
Packit |
fd8b60 |
rc->ku_bits, md->ku_bits);
|
|
Packit |
fd8b60 |
if ((rc->ku_bits & md->ku_bits) == rc->ku_bits)
|
|
Packit |
fd8b60 |
match = 1;
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
default:
|
|
Packit |
fd8b60 |
pkiDebug("%s: keyword %s, keyword value %s mismatch\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, keyword2string(rc->kw_type),
|
|
Packit |
fd8b60 |
kwval2string(kwvaltype_regexp));
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
default:
|
|
Packit |
fd8b60 |
pkiDebug("%s: unknown keyword value type %d\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, rc->kwval_type);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
pkiDebug("%s: returning match = %d\n", __FUNCTION__, match);
|
|
Packit |
fd8b60 |
return match;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Returns match_found == 1 only if exactly one certificate matches
|
|
Packit |
fd8b60 |
* the given rule
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
check_all_certs(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_plg_crypto_context plg_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_req_crypto_context req_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_identity_crypto_context id_cryptoctx,
|
|
Packit |
fd8b60 |
krb5_principal princ,
|
|
Packit |
fd8b60 |
rule_set *rs, /* rule to check */
|
|
Packit |
fd8b60 |
pkinit_cert_matching_data **matchdata,
|
|
Packit |
fd8b60 |
int *match_found,
|
|
Packit |
fd8b60 |
size_t *match_index)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code retval;
|
|
Packit |
fd8b60 |
pkinit_cert_matching_data *md;
|
|
Packit |
fd8b60 |
int i;
|
|
Packit |
fd8b60 |
int comp_match = 0;
|
|
Packit |
fd8b60 |
int total_cert_matches = 0;
|
|
Packit |
fd8b60 |
rule_component *rc;
|
|
Packit |
fd8b60 |
int certs_checked = 0;
|
|
Packit |
fd8b60 |
size_t save_index = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (match_found == NULL || match_index == NULL)
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*match_index = 0;
|
|
Packit |
fd8b60 |
*match_found = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: matching rule relation is %s with %d components\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, relation2string(rs->relation), rs->num_crs);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Loop through all the certs available and count
|
|
Packit |
fd8b60 |
* how many match the rule
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: subject: '%s'\n", __FUNCTION__, md->subject_dn);
|
|
Packit |
fd8b60 |
certs_checked++;
|
|
Packit |
fd8b60 |
for (rc = rs->crs; rc != NULL; rc = rc->next) {
|
|
Packit |
fd8b60 |
comp_match = component_match(context, rc, md);
|
|
Packit |
fd8b60 |
if (comp_match) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: match for keyword type %s\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, keyword2string(rc->kw_type));
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (comp_match && rs->relation == relation_or) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: cert matches rule (OR relation)\n",
|
|
Packit |
fd8b60 |
__FUNCTION__);
|
|
Packit |
fd8b60 |
total_cert_matches++;
|
|
Packit |
fd8b60 |
save_index = i;
|
|
Packit |
fd8b60 |
goto nextcert;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (!comp_match && rs->relation == relation_and) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: cert does not match rule (AND relation)\n",
|
|
Packit |
fd8b60 |
__FUNCTION__);
|
|
Packit |
fd8b60 |
goto nextcert;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (rc == NULL && comp_match) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: cert matches rule (AND relation)\n", __FUNCTION__);
|
|
Packit |
fd8b60 |
total_cert_matches++;
|
|
Packit |
fd8b60 |
save_index = i;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
nextcert:
|
|
Packit |
fd8b60 |
continue;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
pkiDebug("%s: After checking %d certs, we found %d matches\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, certs_checked, total_cert_matches);
|
|
Packit |
fd8b60 |
if (total_cert_matches == 1) {
|
|
Packit |
fd8b60 |
*match_found = 1;
|
|
Packit |
fd8b60 |
*match_index = save_index;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pkiDebug("%s: returning %d, match_found %d\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, retval, *match_found);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
pkinit_cert_matching(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_plg_crypto_context plg_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_req_crypto_context req_cryptoctx,
|
|
Packit |
fd8b60 |
pkinit_identity_crypto_context id_cryptoctx,
|
|
Packit |
fd8b60 |
krb5_principal princ)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
|
|
Packit |
fd8b60 |
int x;
|
|
Packit |
fd8b60 |
char **rules = NULL;
|
|
Packit |
fd8b60 |
rule_set *rs = NULL;
|
|
Packit |
fd8b60 |
int match_found = 0;
|
|
Packit |
fd8b60 |
pkinit_cert_matching_data **matchdata = NULL;
|
|
Packit |
fd8b60 |
size_t match_index = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* If no matching rules, select the default cert and we're done */
|
|
Packit |
fd8b60 |
pkinit_libdefault_strings(context, krb5_princ_realm(context, princ),
|
|
Packit |
fd8b60 |
KRB5_CONF_PKINIT_CERT_MATCH, &rules);
|
|
Packit |
fd8b60 |
if (rules == NULL) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: no matching rules found in config file\n", __FUNCTION__);
|
|
Packit |
fd8b60 |
retval = crypto_cert_select_default(context, plg_cryptoctx,
|
|
Packit |
fd8b60 |
req_cryptoctx, id_cryptoctx);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* parse each rule line one at a time and check all the certs against it */
|
|
Packit |
fd8b60 |
for (x = 0; rules[x] != NULL; x++) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Processing rule '%s'\n", __FUNCTION__, rules[x]);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Free rules from previous time through... */
|
|
Packit |
fd8b60 |
if (rs != NULL) {
|
|
Packit |
fd8b60 |
free_rule_set(context, rs);
|
|
Packit |
fd8b60 |
rs = NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
retval = parse_rule_set(context, rules[x], &rs);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
if (retval == EINVAL) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Ignoring invalid rule pkinit_cert_match = '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, rules[x]);
|
|
Packit |
fd8b60 |
continue;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Optimize so that we do not get cert info unless we have
|
|
Packit |
fd8b60 |
* valid rules to check. Once obtained, keep it around
|
|
Packit |
fd8b60 |
* until we are done.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
if (matchdata == NULL) {
|
|
Packit |
fd8b60 |
retval = crypto_cert_get_matching_data(context, plg_cryptoctx,
|
|
Packit |
fd8b60 |
req_cryptoctx, id_cryptoctx,
|
|
Packit |
fd8b60 |
&matchdata);
|
|
Packit |
fd8b60 |
if (retval || matchdata == NULL) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Error %d obtaining certificate information\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, retval);
|
|
Packit |
fd8b60 |
retval = ENOENT;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = check_all_certs(context, plg_cryptoctx, req_cryptoctx,
|
|
Packit |
fd8b60 |
id_cryptoctx, princ, rs, matchdata,
|
|
Packit |
fd8b60 |
&match_found, &match_index);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Error %d, checking certs against rule '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, retval, rules[x]);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (match_found) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: We have an exact match with rule '%s'\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, rules[x]);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (match_found) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: Selecting the matching cert!\n", __FUNCTION__);
|
|
Packit |
fd8b60 |
retval = crypto_cert_select(context, id_cryptoctx, match_index);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
pkiDebug("%s: crypto_cert_select error %d, %s\n",
|
|
Packit |
fd8b60 |
__FUNCTION__, retval, error_message(retval));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
TRACE_PKINIT_NO_MATCHING_CERT(context);
|
|
Packit |
fd8b60 |
retval = ENOENT; /* XXX */
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
retval = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
profile_free_list(rules);
|
|
Packit |
fd8b60 |
free_rule_set(context, rs);
|
|
Packit |
fd8b60 |
crypto_cert_free_matching_data_list(context, matchdata);
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
pkinit_client_cert_match(krb5_context context,
|
|
Packit |
fd8b60 |
pkinit_plg_crypto_context plgctx,
|
|
Packit |
fd8b60 |
pkinit_req_crypto_context reqctx,
|
|
Packit |
fd8b60 |
const char *match_rule,
|
|
Packit |
fd8b60 |
krb5_boolean *matched)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
pkinit_cert_matching_data *md = NULL;
|
|
Packit |
fd8b60 |
rule_component *rc = NULL;
|
|
Packit |
fd8b60 |
int comp_match = 0;
|
|
Packit |
fd8b60 |
rule_set *rs = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*matched = FALSE;
|
|
Packit |
fd8b60 |
ret = parse_rule_set(context, match_rule, &rs);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = crypto_req_cert_matching_data(context, plgctx, reqctx, &md);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (rc = rs->crs; rc != NULL; rc = rc->next) {
|
|
Packit |
fd8b60 |
comp_match = component_match(context, rc, md);
|
|
Packit |
fd8b60 |
if ((comp_match && rs->relation == relation_or) ||
|
|
Packit |
fd8b60 |
(!comp_match && rs->relation == relation_and)) {
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
*matched = comp_match;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
free_rule_set(context, rs);
|
|
Packit |
fd8b60 |
crypto_cert_free_matching_data(context, md);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|