/*
* COPYRIGHT (C) 2007
* THE REGENTS OF THE UNIVERSITY OF MICHIGAN
* ALL RIGHTS RESERVED
*
* Permission is granted to use, copy, create derivative works
* and redistribute this software and such derivative works
* for any purpose, so long as the name of The University of
* Michigan is not used in any advertising or publicity
* pertaining to the use of distribution of this software
* without specific, written prior authorization. If the
* above copyright notice or any other identification of the
* University of Michigan is included in any copy of any
* portion of this software, then the disclaimer below must
* also be included.
*
* THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
* FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
* PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
* MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
* WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
* REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
* FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
* OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
* IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGES.
*/
/*
*/
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <regex.h>
#include <krb5.h>
#include "pkinit.h"
typedef enum {
kw_undefined = 0,
} keyword_type;
static char *
{
/* Solaris Kerberos: removed "break"s (lint) */
switch(kw) {
case kw_undefined: return "NONE";
case kw_subject: return "SUBJECT";
case kw_issuer: return "ISSUER";
case kw_san: return "SAN";
case kw_eku: return "EKU";
case kw_ku: return "KU";
default: return "INVALID";
}
}
typedef enum {
relation_none = 0,
static char *
{
/* Solaris Kerberos: removed "break"s (lint) */
switch(rel) {
case relation_none: return "NONE";
case relation_and: return "AND";
case relation_or: return "OR";
default: return "INVALID";
}
}
typedef enum {
kwvaltype_undefined = 0,
static char *
{
/* Solaris Kerberos: removed "break"s (lint) */
switch(kwval) {
case kwvaltype_undefined: return "NONE";
case kwvaltype_regexp: return "REGEXP";
case kwvaltype_list: return "LIST";
default: return "INVALID";
}
}
struct keyword_desc {
const char *value;
} matching_keywords[] = {
};
struct ku_desc {
const char *value;
unsigned int bitval;
};
{ NULL, 0, 0 },
};
{ NULL, 0, 0 },
};
/* Rule component */
typedef struct _rule_component {
unsigned int ku_bits;
unsigned int eku_bits;
/* Set rule components */
typedef struct _rule_set {
int num_crs;
} rule_set;
/* ARGSUSED */
static krb5_error_code
{
return 0;
}
return 0;
}
static krb5_error_code
{
return 0;
/* Solaris Kerberos */
}
return 0;
}
/* ARGSUSED */
static krb5_error_code
char *value,
{
char *comma;
int found;
unsigned int *bitptr;
pkiDebug("%s: Missing or empty value for list keyword type %d\n",
__FUNCTION__, type);
goto out;
}
} else {
goto out;
}
do {
found = 0;
else
ku = eku_keywords;
ku = ku_keywords;
}
found = 1;
pkiDebug("%s: Found value '%s', bitfield is now 0x%x\n",
break;
}
}
if (found) {
if (*value == ',')
value += 1;
} else {
goto out;
}
retval = 0;
out:
return retval;
}
static krb5_error_code
const char **rule,
int *remaining,
{
int ret;
char *nk;
int found_next_kw = 0;
break;
}
}
pkiDebug("%s: Missing or invalid keyword in rule '%s'\n",
__FUNCTION__, *rule);
goto out;
}
goto out;
}
/*
* Before procesing the value for this keyword,
* (compiling the regular expression or processing the list)
* we need to find the end of it. That means parsing for the
* beginning of the next keyword (or the end of the rule).
*/
/* Possibly another keyword, check it out */
/* Found a keyword, nk points to the beginning */
found_next_kw = 1;
break; /* Need to break out of the while! */
}
}
if (!found_next_kw)
else
break;
}
else
if (len == 0) {
pkiDebug("%s: Missing value for keyword '%s'\n",
goto out;
}
goto out;
}
if (ret) {
pkiDebug("%s: Error compiling reg-exp '%s': %s\n",
goto out;
}
goto out;
}
if (retval) {
pkiDebug("%s: Error %d, parsing list values for keyword %s\n",
goto out;
}
}
retval = 0;
out:
return retval;
}
/* ARGSUSED */
static krb5_error_code
const char *rule_in,
{
const char *rule;
/* Solaris Kerberos */
int remaining;
return EINVAL;
/* Solaris Kerberos */
goto cleanup;
}
if (remaining > 1) {
rule += 2;
remaining -= 2;
rule +=2;
remaining -= 2;
}
}
while (remaining > 0) {
pkiDebug("%s: Assuming AND relation for multiple components in rule '%s'\n",
}
if (ret) {
goto cleanup;
}
pkiDebug("%s: After parse_rule_component, remaining %d, rule '%s'\n",
/*
* Chain the new component on the end (order matters since
* we can short-circuit an OR or an AND relation if an
* earlier check passes
*/
else {
}
}
retval = 0;
}
return retval;
}
/* ARGSUSED */
static int
{
int code;
pkiDebug("%s: checking %s rule '%s' with value '%s'\n",
return (code == 0 ? 1: 0);
}
static int
{
int match = 0;
int i;
char *princ_string;
switch (rc->kwval_type) {
case kwvaltype_regexp:
case kw_subject:
break;
case kw_issuer:
break;
case kw_san:
break;
if (match)
break;
}
break;
default:
pkiDebug("%s: keyword %s, keyword value %s mismatch\n",
break;
}
break;
case kwvaltype_list:
case kw_eku:
pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n",
match = 1;
break;
case kw_ku:
pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n",
match = 1;
break;
default:
pkiDebug("%s: keyword %s, keyword value %s mismatch\n",
break;
}
break;
default:
pkiDebug("%s: unknown keyword value type %d\n",
break;
}
return match;
}
/*
* Returns match_found == 1 only if exactly one certificate matches
* the given rule
*/
/* ARGSUSED */
static krb5_error_code
int *match_found,
{
int i;
int comp_match = 0;
int total_cert_matches = 0;
int certs_checked = 0;
return EINVAL;
*matching_cert = NULL;
*match_found = 0;
pkiDebug("%s: matching rule relation is %s with %d components\n",
/*
* Loop through all the certs available and count
* how many match the rule
*/
#if 0
char *san_string;
}
#endif
if (comp_match) {
pkiDebug("%s: match for keyword type %s\n",
}
pkiDebug("%s: cert matches rule (OR relation)\n",
save_match = md;
goto nextcert;
}
pkiDebug("%s: cert does not match rule (AND relation)\n",
goto nextcert;
}
}
save_match = md;
}
continue;
}
pkiDebug("%s: After checking %d certs, we found %d matches\n",
if (total_cert_matches == 1) {
*match_found = 1;
}
retval = 0;
pkiDebug("%s: returning %d, match_found %d\n",
return retval;
}
static krb5_error_code
{
int i;
return EINVAL;
if (retval) {
pkiDebug("%s: crypto_cert_free_matching_data error %d, %s\n",
goto cleanup;
}
if (retval) {
pkiDebug("%s: crypto_cert_release error %d, %s\n",
goto cleanup;
}
}
retval = 0;
return retval;
}
static krb5_error_code
{
int i, cert_count;
if (retval) {
pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
goto cleanup;
}
pkiDebug("%s: crypto_cert_get_count says there are %d certs\n",
return ENOMEM;
id_cryptoctx, &ih);
if (retval) {
pkiDebug("%s: crypto_cert_iteration_begin returned %d, %s\n",
goto cleanup;
}
for (i = 0; i < cert_count; i++) {
if (retval) {
if (retval == PKINIT_ITER_NO_MORE)
pkiDebug("%s: We thought there were %d certs, but "
"crypto_cert_iteration_next stopped after %d?\n",
__FUNCTION__, cert_count, i);
else
pkiDebug("%s: crypto_cert_iteration_next error %d, %s\n",
goto cleanup;
}
if (retval) {
pkiDebug("%s: crypto_cert_get_matching_data error %d, %s\n",
goto cleanup;
}
}
retval = 0;
/* Solaris Kerberos */
if (retval) {
}
pkiDebug("%s: returning %d, certinfo %p\n",
return retval;
}
{
int x;
int match_found = 0;
/* If no matching rules, select the default cert and we're done */
"pkinit_cert_match", &rules);
} else
retval = 0;
goto cleanup;
}
/* parse each rule line one at a time and check all the certs against it */
/* Free rules from previous time through... */
}
if (retval) {
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.
*/
&matchdata);
pkiDebug("%s: Error %d obtaining certificate information\n",
goto cleanup;
}
}
if (retval) {
pkiDebug("%s: Error %d, checking certs against rule '%s'\n",
goto cleanup;
}
if (match_found) {
pkiDebug("%s: We have an exact match with rule '%s'\n",
__FUNCTION__, rules[x]);
break;
}
}
if (retval) {
pkiDebug("%s: crypto_cert_select error %d, %s\n",
goto cleanup;
}
}
} else {
goto cleanup;
}
retval = 0;
/* Solaris Kerberos */
return retval;
}