Add language to support querying certificates to find a match. Support constructs like "1.3.6.1.5.2.3.5" IN %{certificate.eku} AND %{certificate.subject} TAILMATCH "C=SE"".

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@22677 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2008-03-13 17:35:49 +00:00
parent 08cb59513f
commit 7776ed30a9
16 changed files with 1006 additions and 71 deletions

View File

@@ -1,5 +1,7 @@
2008-02-26 Love H<>rnquist <20>strand <lha@it.su.se>
* version-script.map: add hx509_pem_read
* hxtool-commands.in: Add --pem to cms-verify-sd.
* test_cms.in: Test verifying PEM signature files.

View File

@@ -6,6 +6,7 @@ lib_LTLIBRARIES = libhx509.la
libhx509_la_LDFLAGS = -version-info 3:0:0
BUILT_SOURCES = \
sel-gram.h \
$(gen_files_ocsp:.x=.c) \
$(gen_files_pkcs10:.x=.c) \
hx509_err.c \
@@ -50,6 +51,8 @@ gen_files_crmf = \
asn1_ProofOfPossession.x \
asn1_SubsequentMessage.x
AM_YFLAGS = -d
dist_libhx509_la_SOURCES = \
ca.c \
cert.c \
@@ -64,6 +67,10 @@ dist_libhx509_la_SOURCES = \
hx509-protos.h \
hx509.h \
hx_locl.h \
sel.c \
sel.h \
sel-gram.y \
sel-lex.l \
keyset.c \
ks_dir.c \
ks_file.c \
@@ -81,6 +88,8 @@ dist_libhx509_la_SOURCES = \
req.c \
revoke.c
sel-lex.c: sel-gram.h
libhx509_la_LIBADD = \
$(LIB_com_err) \
$(LIB_hcrypto) \
@@ -184,7 +193,8 @@ test_soft_pkcs11_CPPFLAGS = -I$(srcdir)/ref
TESTS = $(SCRIPT_TESTS) $(PROGRAM_TESTS)
PROGRAM_TESTS = \
test_name
test_name \
test_expr
SCRIPT_TESTS = \
test_ca \

View File

@@ -2355,7 +2355,7 @@ hx509_verify_hostname(hx509_context context,
} while (1);
{
Name *name = &cert->data->tbsCertificate.subject;
const Name *name = &cert->data->tbsCertificate.subject;
/* match if first component is a CN= */
if (name->u.rdnSequence.len > 0
@@ -2548,6 +2548,7 @@ hx509_query_alloc(hx509_context context, hx509_query **q)
return 0;
}
/**
* Set match options for the hx509 query controller.
*
@@ -2697,6 +2698,25 @@ hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
return 0;
}
int
hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
{
if (q->expr) {
_hx509_expr_free(q->expr);
q->expr = NULL;
}
if (expr == NULL) {
q->match &= ~HX509_QUERY_MATCH_EXPR;
} else {
q->expr = _hx509_expr_parse(expr);
if (q->expr)
q->match |= HX509_QUERY_MATCH_EXPR;
}
return 0;
}
/**
* Set the query controller to match using a specific match function.
*
@@ -2753,6 +2773,9 @@ hx509_query_free(hx509_context context, hx509_query *q)
}
if (q->friendlyname)
free(q->friendlyname);
if (q->expr)
_hx509_expr_free(q->expr);
memset(q, 0, sizeof(*q));
free(q);
}
@@ -2890,6 +2913,19 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert
hx509_cert_check_eku(context, cert, q->eku, 0))
return 0;
if ((q->match & HX509_QUERY_MATCH_EXPR)) {
hx509_env env = NULL;
ret = _hx509_cert_to_env(context, cert, &env);
if (ret)
return 0;
ret = _hx509_eval_expr(context, env, q->expr);
hx509_env_free(&env);
if (ret == 0)
return 0;
}
if (q->match & ~HX509_QUERY_MASK)
return 0;
@@ -3206,3 +3242,103 @@ hx509_xfree(void *ptr)
{
free(ptr);
}
/**
*
*/
int
_hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
{
ExtKeyUsage eku;
hx509_name name;
char *buf;
int ret;
hx509_env envcert = NULL;
*env = NULL;
/* version */
asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
ret = hx509_env_add(context, &envcert, "version", buf);
free(buf);
if (ret)
goto out;
/* subject */
ret = hx509_cert_get_subject(cert, &name);
if (ret)
goto out;
ret = hx509_name_to_string(name, &buf);
if (ret) {
hx509_name_free(&name);
goto out;
}
ret = hx509_env_add(context, &envcert, "subject", buf);
hx509_name_free(&name);
if (ret)
goto out;
/* issuer */
ret = hx509_cert_get_issuer(cert, &name);
if (ret)
goto out;
ret = hx509_name_to_string(name, &buf);
hx509_name_free(&name);
if (ret)
goto out;
ret = hx509_env_add(context, &envcert, "issuer", buf);
hx509_xfree(buf);
if (ret)
goto out;
/* eku */
ret = _hx509_cert_get_eku(context, cert, &eku);
if (ret == HX509_EXTENSION_NOT_FOUND)
;
else if (ret != 0)
goto out;
else {
int i;
hx509_env enveku = NULL;
for (i = 0; i < eku.len; i++) {
ret = der_print_heim_oid(&eku.val[i], '.', &buf);
if (ret) {
free_ExtKeyUsage(&eku);
hx509_env_free(&enveku);
goto out;
}
ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
free(buf);
if (ret) {
free_ExtKeyUsage(&eku);
hx509_env_free(&enveku);
goto out;
}
}
free_ExtKeyUsage(&eku);
ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
if (ret) {
hx509_env_free(&enveku);
goto out;
}
}
ret = hx509_env_add_binding(context, env, "certificate", envcert);
if (ret)
goto out;
return 0;
out:
hx509_env_free(&envcert);
return ret;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007 Kungliga Tekniska H<>gskolan
* Copyright (c) 2007 - 2008 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -40,36 +40,6 @@ RCSID("$Id$");
* See the library functions here: @ref hx509_env
*/
struct hx509_env {
struct {
char *key;
char *value;
} *val;
size_t len;
};
/**
* Allocate a new hx509_env container object.
*
* @param context A hx509 context.
* @param env return a hx509_env structure, free with hx509_env_free().
*
* @return An hx509 error code, see hx509_get_error_string().
*
* @ingroup hx509_env
*/
int
hx509_env_init(hx509_context context, hx509_env *env)
{
*env = calloc(1, sizeof(**env));
if (*env == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
return ENOMEM;
}
return 0;
}
/**
* Add a new key/value pair to the hx509_env.
*
@@ -84,34 +54,92 @@ hx509_env_init(hx509_context context, hx509_env *env)
*/
int
hx509_env_add(hx509_context context, hx509_env env,
hx509_env_add(hx509_context context, hx509_env *env,
const char *key, const char *value)
{
void *ptr;
hx509_env n;
ptr = realloc(env->val, sizeof(env->val[0]) * (env->len + 1));
if (ptr == NULL) {
n = malloc(sizeof(*n));
if (n == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
return ENOMEM;
}
env->val = ptr;
env->val[env->len].key = strdup(key);
if (env->val[env->len].key == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
n->type = env_string;
n->next = NULL;
n->name = strdup(key);
if (n->name == NULL) {
free(n);
return ENOMEM;
}
env->val[env->len].value = strdup(value);
if (env->val[env->len].value == NULL) {
free(env->val[env->len].key);
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
n->u.string = strdup(value);
if (n->u.string == NULL) {
free(n->name);
free(n);
return ENOMEM;
}
env->len++;
/* add to tail */
if (*env) {
hx509_env e = *env;
while (e->next)
e = e->next;
e->next = n;
} else
*env = n;
return 0;
}
/**
* Search the hx509_env for a key.
* Add a new key/binding pair to the hx509_env.
*
* @param context A hx509 context.
* @param env enviroment to add the enviroment variable too.
* @param key key to add
* @param list binding list to add
*
* @return An hx509 error code, see hx509_get_error_string().
*
* @ingroup hx509_env
*/
int
hx509_env_add_binding(hx509_context context, hx509_env *env,
const char *key, hx509_env list)
{
hx509_env n;
n = malloc(sizeof(*n));
if (n == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
return ENOMEM;
}
n->type = env_list;
n->next = NULL;
n->name = strdup(key);
if (n->name == NULL) {
free(n);
return ENOMEM;
}
n->u.list = list;
/* add to tail */
if (*env) {
hx509_env e = *env;
while (e->next)
e = e->next;
e->next = n;
} else
*env = n;
return 0;
}
/**
* Search the hx509_env for a length based key.
*
* @param context A hx509 context.
* @param env enviroment to add the enviroment variable too.
@@ -127,16 +155,80 @@ const char *
hx509_env_lfind(hx509_context context, hx509_env env,
const char *key, size_t len)
{
size_t i;
for (i = 0; i < env->len; i++) {
char *s = env->val[i].key;
if (strncmp(key, s, len) == 0 && s[len] == '\0')
return env->val[i].value;
while(env) {
if (strncmp(key, env->name ,len) == 0
&& env->name[len] == '\0' && env->type == env_string)
return env->u.string;
env = env->next;
}
return NULL;
}
/**
* Search the hx509_env for a key.
*
* @param context A hx509 context.
* @param env enviroment to add the enviroment variable too.
* @param key key to search for.
*
* @return the value if the key is found, NULL otherwise.
*
* @ingroup hx509_env
*/
const char *
hx509_env_find(hx509_context context, hx509_env env, const char *key)
{
while(env) {
if (strcmp(key, env->name) == 0 && env->type == env_string)
return env->u.string;
env = env->next;
}
return NULL;
}
/**
* Search the hx509_env for a binding.
*
* @param context A hx509 context.
* @param env enviroment to add the enviroment variable too.
* @param key key to search for.
*
* @return the binding if the key is found, NULL if not found.
*
* @ingroup hx509_env
*/
hx509_env
hx509_env_find_binding(hx509_context context,
hx509_env env,
const char *key)
{
while(env) {
if (strcmp(key, env->name) == 0 && env->type == env_list)
return env->u.list;
env = env->next;
}
return NULL;
}
static void
env_free(hx509_env b)
{
while(b) {
hx509_env next = b->next;
if (b->type == env_string)
free(b->u.string);
else if (b->type == env_list)
env_free(b->u.list);
free(b->name);
free(b);
b = next;
}
}
/**
* Free an hx509_env enviroment context.
*
@@ -148,14 +240,7 @@ hx509_env_lfind(hx509_context context, hx509_env env,
void
hx509_env_free(hx509_env *env)
{
size_t i;
for (i = 0; i < (*env)->len; i++) {
free((*env)->val[i].key);
free((*env)->val[i].value);
}
free((*env)->val);
free(*env);
if (*env)
env_free(*env);
*env = NULL;
}

View File

@@ -50,7 +50,7 @@ typedef struct hx509_request_data *hx509_request;
typedef struct hx509_error_data *hx509_error;
typedef struct hx509_peer_info *hx509_peer_info;
typedef struct hx509_ca_tbs *hx509_ca_tbs;
typedef struct hx509_env *hx509_env;
typedef struct hx509_env_data *hx509_env;
typedef struct hx509_crl *hx509_crl;
typedef void (*hx509_vprint_func)(void *, const char *, va_list);

View File

@@ -80,6 +80,8 @@ typedef void (*_hx509_cert_release_func)(struct hx509_cert_data *, void *);
typedef struct hx509_private_key_ops hx509_private_key_ops;
#include "sel.h"
#include <hx509-private.h>
#include <hx509_err.h>
@@ -129,7 +131,8 @@ struct hx509_query_data {
#define HX509_QUERY_MATCH_KEY_HASH_SHA1 0x100000
#define HX509_QUERY_MATCH_TIME 0x200000
#define HX509_QUERY_MATCH_EKU 0x400000
#define HX509_QUERY_MASK 0x7fffff
#define HX509_QUERY_MATCH_EXPR 0x800000
#define HX509_QUERY_MASK 0xffffff
Certificate *subject;
Certificate *certificate;
heim_integer *serial;
@@ -144,6 +147,7 @@ struct hx509_query_data {
heim_octet_string *keyhash_sha1;
time_t timenow;
heim_oid *eku;
struct hx_expr *expr;
};
struct hx509_keyset_ops {
@@ -188,6 +192,18 @@ struct hx509_context_data {
/* _hx509_calculate_path flag field */
#define HX509_CALCULATE_PATH_NO_ANCHOR 1
/* environment */
struct hx509_env_data {
enum { env_string, env_list } type;
char *name;
struct hx509_env_data *next;
union {
char *string;
struct hx509_env_data *list;
} u;
};
extern const AlgorithmIdentifier * _hx509_crypto_default_sig_alg;
extern const AlgorithmIdentifier * _hx509_crypto_default_digest_alg;
extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg;

View File

@@ -448,6 +448,12 @@ command = {
argument = "oid-string"
help = "match on EKU"
}
option = {
long = "expr"
type = "string"
argument = "expression"
help = "match on expression"
}
option = {
long = "keyEncipherment"
type = "flag"

View File

@@ -942,6 +942,9 @@ query(struct query_options *opt, int argc, char **argv)
if (opt->digitalSignature_flag)
hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
if (opt->expr_string)
hx509_query_match_expr(context, q, opt->expr_string);
ret = hx509_certs_find(context, certs, q, &c);
hx509_query_free(context, q);
if (ret)

View File

@@ -897,7 +897,7 @@ hx509_name_is_null_p(const hx509_name name)
* @param name the name to print
* @param str an allocated string returns the name in string form
*
* @return An hx509 error code, see krb5_get_error_string().
* @return An hx509 error code, see hx509_get_error_string().
*
* @ingroup hx509_name
*/

115
lib/hx509/sel-gram.y Normal file
View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2008 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
%{
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <hx_locl.h>
RCSID("$Id$");
%}
%union {
char *string;
struct hx_expr *expr;
}
%token kw_TRUE
%token kw_FALSE
%token kw_AND
%token kw_OR
%token kw_IN
%token kw_TAILMATCH
%type <expr> expr
%type <expr> comp
%type <expr> word words
%type <expr> number
%type <expr> string
%type <expr> function
%type <expr> variable variables
%token <string> NUMBER
%token <string> STRING
%token <string> IDENTIFIER
%start start
%%
start: expr { _hx509_expr_input.expr = $1; }
expr : kw_TRUE { $$ = _hx509_make_expr(op_TRUE, NULL, NULL); }
| kw_FALSE { $$ = _hx509_make_expr(op_FALSE, NULL, NULL); }
| '!' expr { $$ = _hx509_make_expr(op_NOT, $2, NULL); }
| expr kw_AND expr { $$ = _hx509_make_expr(op_AND, $1, $3); }
| expr kw_OR expr { $$ = _hx509_make_expr(op_OR, $1, $3); }
| '(' expr ')' { $$ = $2; }
| comp { $$ = _hx509_make_expr(op_COMP, $1, NULL); }
;
words : word { $$ = _hx509_make_expr(expr_WORDS, $1, NULL); }
| word ',' words { $$ = _hx509_make_expr(expr_WORDS, $1, $3); }
;
comp : word '=' '=' word { $$ = _hx509_make_expr(comp_EQ, $1, $4); }
| word '!' '=' word { $$ = _hx509_make_expr(comp_NE, $1, $4); }
| word kw_TAILMATCH word { $$ = _hx509_make_expr(comp_TAILEQ, $1, $3); }
| word kw_IN '(' words ')' { $$ = _hx509_make_expr(comp_IN, $1, $4); }
| word kw_IN variable { $$ = _hx509_make_expr(comp_IN, $1, $3); }
;
word : number { $$ = $1; }
| string { $$ = $1; }
| function { $$ = $1; }
| variable { $$ = $1; }
;
number : NUMBER { $$ = _hx509_make_expr(expr_NUMBER, $1, NULL); };
string : STRING { $$ = _hx509_make_expr(expr_STRING, $1, NULL); };
function: IDENTIFIER '(' words ')' {
$$ = _hx509_make_expr(expr_FUNCTION, $1, $3); }
;
variable: '%' '{' variables '}' { $$ = $3; }
;
variables: IDENTIFIER '.' variables {
$$ = _hx509_make_expr(expr_VAR, $1, $3); }
| IDENTIFIER {
$$ = _hx509_make_expr(expr_VAR, $1, NULL); }
;

152
lib/hx509/sel-lex.l Normal file
View File

@@ -0,0 +1,152 @@
%{
/*
* Copyright (c) 2004, 2008 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $Id$ */
#undef ECHO
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "sel.h"
#include "sel-gram.h"
unsigned lineno = 1;
static char * handle_string(void);
static int lex_input(char *, int);
static void error_message (const char *format, ...);
void yyerror (char *);
struct hx_expr_input _hx509_expr_input;
#define YY_NO_UNPUT 1
#undef YY_INPUT
#define YY_INPUT(buf,res,maxsize) (res = lex_input(buf, maxsize))
#undef ECHO
%}
%%
TRUE { return kw_TRUE; }
FALSE { return kw_FALSE; }
AND { return kw_AND; }
OR { return kw_OR; }
IN { return kw_IN; }
TAILMATCH { return kw_TAILMATCH; }
[A-Za-z][-A-Za-z0-9_]* {
yylval.string = strdup ((const char *)yytext);
return IDENTIFIER;
}
"\"" { yylval.string = handle_string(); return STRING; }
\n { ++lineno; }
[,.!={}()%] { return *yytext; }
[ \t] ;
%%
void
error_message (const char *format, ...)
{
va_list args;
if (_hx509_expr_input.error)
free(_hx509_expr_input.error);
va_start (args, format);
vasprintf(&_hx509_expr_input.error, format, args);
va_end (args);
}
void
yyerror (char *s)
{
error_message("%s", s);
}
static char *
handle_string(void)
{
char x[1024];
int i = 0;
int c;
int quote = 0;
while((c = input()) != EOF){
if(quote) {
x[i++] = '\\';
x[i++] = c;
quote = 0;
continue;
}
if(c == '\n'){
error_message("unterminated string");
lineno++;
break;
}
if(c == '\\'){
quote++;
continue;
}
if(c == '\"')
break;
x[i++] = c;
}
x[i] = '\0';
return strdup(x);
}
int
yywrap ()
{
return 1;
}
static int
lex_input(char *buf, int max_size)
{
int n;
n = _hx509_expr_input.length - _hx509_expr_input.offset;
if (max_size < n)
n = max_size;
if (n <= 0)
return YY_NULL;
memcpy(buf, _hx509_expr_input.buf + _hx509_expr_input.offset, n);
_hx509_expr_input.offset += n;
return n;
}

222
lib/hx509/sel.c Normal file
View File

@@ -0,0 +1,222 @@
/*
* Copyright (c) 2008 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "hx_locl.h"
struct hx_expr *
_hx509_make_expr(enum hx_expr_op op, void *arg1, void *arg2)
{
struct hx_expr *expr;
expr = malloc(sizeof(*expr));
if (expr == NULL)
return NULL;
expr->op = op;
expr->arg1 = arg1;
expr->arg2 = arg2;
return expr;
}
static const char *
eval_word(hx509_context context, hx509_env env, struct hx_expr *word)
{
switch (word->op) {
case expr_STRING:
return word->arg1;
case expr_VAR:
if (word->arg2 == NULL)
return hx509_env_find(context, env, word->arg1);
env = hx509_env_find_binding(context, env, word->arg1);
if (env == NULL)
return NULL;
return eval_word(context, env, word->arg2);
default:
return NULL;
}
}
static hx509_env
find_variable(hx509_context context, hx509_env env, struct hx_expr *word)
{
assert(word->op == expr_VAR);
if (word->arg2 == NULL)
return hx509_env_find_binding(context, env, word->arg1);
env = hx509_env_find_binding(context, env, word->arg1);
if (env == NULL)
return NULL;
return find_variable(context, env, word->arg2);
}
static int
eval_comp(hx509_context context, hx509_env env, struct hx_expr *expr)
{
switch (expr->op) {
case comp_NE:
case comp_EQ:
case comp_TAILEQ: {
const char *s1, *s2;
int ret;
s1 = eval_word(context, env, expr->arg1);
s2 = eval_word(context, env, expr->arg2);
if (s1 == NULL || s2 == NULL)
return FALSE;
if (expr->op == comp_TAILEQ) {
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
if (len1 < len2)
return 0;
ret = strcmp(s1 + (len1 - len2), s2) == 0;
} else {
ret = strcmp(s1, s2) == 0;
if (expr->op == comp_NE)
ret = !ret;
}
return ret;
}
case comp_IN: {
struct hx_expr *subexpr;
const char *w, *s1;
w = eval_word(context, env, expr->arg1);
subexpr = expr->arg2;
if (subexpr->op == expr_WORDS) {
while (subexpr) {
s1 = eval_word(context, env, subexpr->arg1);
if (strcmp(w, s1) == 0)
return TRUE;
subexpr = subexpr->arg2;
}
} else if (subexpr->op == expr_VAR) {
hx509_env subenv;
subenv = find_variable(context, env, subexpr);
if (subenv == NULL)
return FALSE;
while (subenv) {
if (subenv->type != env_string)
continue;
if (strcmp(w, subenv->name) == 0)
return TRUE;
if (strcmp(w, subenv->u.string) == 0)
return TRUE;
subenv = subenv->next;
}
} else
_hx509_abort("hx509 eval IN unknown op: %d", (int)subexpr->op);
return FALSE;
}
default:
_hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op);
}
return FALSE;
}
int
_hx509_eval_expr(hx509_context context, hx509_env env, struct hx_expr *expr)
{
switch (expr->op) {
case op_TRUE:
return 1;
case op_FALSE:
return 0;
case op_NOT:
return ! _hx509_eval_expr(context, env, expr->arg1);
case op_AND:
return _hx509_eval_expr(context, env, expr->arg1) &&
_hx509_eval_expr(context, env, expr->arg2);
case op_OR:
return _hx509_eval_expr(context, env, expr->arg1) ||
_hx509_eval_expr(context, env, expr->arg2);
case op_COMP:
return eval_comp(context, env, expr->arg1);
default:
_hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op);
}
}
void
_hx509_expr_free(struct hx_expr *expr)
{
switch (expr->op) {
case expr_STRING:
case expr_NUMBER:
free(expr->arg1);
break;
case expr_WORDS:
case expr_FUNCTION:
case expr_VAR:
free(expr->arg1);
if (expr->arg2)
_hx509_expr_free(expr->arg2);
break;
default:
if (expr->arg1)
_hx509_expr_free(expr->arg1);
if (expr->arg2)
_hx509_expr_free(expr->arg2);
break;
}
free(expr);
}
struct hx_expr *
_hx509_expr_parse(const char *buf)
{
_hx509_expr_input.buf = buf;
_hx509_expr_input.length = strlen(buf);
_hx509_expr_input.offset = 0;
_hx509_expr_input.expr = NULL;
if (_hx509_expr_input.error) {
free(_hx509_expr_input.error);
_hx509_expr_input.error = NULL;
}
yyparse();
return _hx509_expr_input.expr;
}

70
lib/hx509/sel.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2008 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
enum hx_expr_op {
op_TRUE,
op_FALSE,
op_NOT,
op_AND,
op_OR,
op_COMP,
comp_EQ,
comp_NE,
comp_IN,
comp_TAILEQ,
expr_NUMBER,
expr_STRING,
expr_FUNCTION,
expr_VAR,
expr_WORDS
};
struct hx_expr {
enum hx_expr_op op;
void *arg1;
void *arg2;
};
struct hx_expr_input {
const char *buf;
size_t length;
size_t offset;
struct hx_expr *expr;
char *error;
};
extern struct hx_expr_input _hx509_expr_input;
int yyparse(void);

85
lib/hx509/test_expr.c Normal file
View File

@@ -0,0 +1,85 @@
#include "hx_locl.h"
#include <err.h>
struct foo {
int val;
char *str;
} foo[] = {
{ 0, "FALSE" },
{ 1, "TRUE" },
{ 0, "!TRUE" },
{ 0, "! TRUE" },
{ 0, "!\tTRUE" },
{ 0, "( FALSE AND FALSE )" },
{ 0, "( TRUE AND FALSE )" },
{ 1, "( TRUE AND TRUE )" },
{ 1, "( TRUE OR TRUE )" },
{ 1, "( TRUE OR FALSE )" },
{ 0, "( FALSE OR FALSE )" },
{ 1, "! ( FALSE OR FALSE )" },
{ 1, "\"foo\" TAILMATCH \"foo\"" },
{ 1, "\"foobar\" TAILMATCH \"bar\"" },
{ 0, "\"foobar\" TAILMATCH \"foo\"" },
{ 1, "\"foo\" == \"foo\"" },
{ 0, "\"foo\" == \"bar\"" },
{ 0, "\"foo\" != \"foo\"" },
{ 1, "\"foo\" != \"bar\"" },
{ 1, "%{variable} == \"foo\"" },
{ 0, "%{variable} == \"bar\"" },
{ 1, "%{context.variable} == \"foo\"" },
{ 0, "%{context.variable} == \"bar\"" },
{ 1, "\"foo\" IN ( \"bar\", \"foo\")" },
{ 0, "\"foo\" IN ( \"bar\", \"baz\")" },
{ 0, "\"bar\" IN %{context}" },
{ 1, "\"foo\" IN %{context}" },
{ 1, "\"variable\" IN %{context}" },
{ 1, "\"foo\" IN %{context} AND %{context.variable} == \"foo\"" }
};
int
main(int argc, char **argv)
{
struct hx_expr *expr;
hx509_context context;
hx509_env env = NULL, env2 = NULL;
int val, i, ret;
#if 0
extern int yydebug;
yydebug = 1;
#endif
ret = hx509_context_init(&context);
if (ret)
errx(1, "hx509_context_init failed with %d", ret);
hx509_env_add(context, &env, "variable", "foo");
hx509_env_add(context, &env2, "variable", "foo");
hx509_env_add_binding(context, &env, "context", env2);
for (i = 0; i < sizeof(foo)/sizeof(foo[0]); i++) {
expr = _hx509_expr_parse(foo[i].str);
if (expr == NULL)
errx(1, "_hx509_expr_parse failed for %d: %s", i, foo[i].str);
val = _hx509_eval_expr(context, env, expr);
if (foo[i].val) {
if (val == 0)
errx(1, "_hx509_eval_expr not true when it should: %d: %s",
i, foo[i].str);
} else {
if (val)
errx(1, "_hx509_eval_expr true when it should not: %d: %s",
i, foo[i].str);
}
}
hx509_env_free(&env);
return 0;
}

View File

@@ -72,13 +72,12 @@ test_name_fail(hx509_context context, const char *name)
static int
test_expand(hx509_context context, const char *name, const char *expected)
{
hx509_env env;
hx509_env env = NULL;
hx509_name n;
char *s;
int ret;
hx509_env_init(context, &env);
hx509_env_add(context, env, "uid", "lha");
hx509_env_add(context, &env, "uid", "lha");
ret = hx509_parse_name(context, name, &n);
if (ret)

View File

@@ -1,6 +1,6 @@
#!/bin/sh
#
# Copyright (c) 2005 - 2007 Kungliga Tekniska H<>gskolan
# Copyright (c) 2005 - 2008 Kungliga Tekniska H<>gskolan
# (Royal Institute of Technology, Stockholm, Sweden).
# All rights reserved.
#
@@ -51,7 +51,7 @@ echo "try printing"
${hxtool} print \
--pass=PASS:foobar \
--info --content \
FILE:$srcdir/data/kdc.crt || exit 1
FILE:$srcdir/data/kdc.crt >/dev/null 2>/dev/null || exit 1
${hxtool} print \
--pass=PASS:foobar \
@@ -159,5 +159,39 @@ ${hxtool} query \
--keyEncipherment \
FILE:$srcdir/data/test-ke-only.crt >/dev/null 2>/dev/null && exit 1
exit 0
echo "make sure entry is found (eku) in query language"
${hxtool} query \
--expr='"1.3.6.1.5.2.3.5" IN %{certificate.eku}' \
FILE:$srcdir/data/kdc.crt > /dev/null || exit 1
echo "make sure entry is not found (eku) in query language"
${hxtool} query \
--expr='"1.3.6.1.5.2.3.6" IN %{certificate.eku}' \
FILE:$srcdir/data/kdc.crt > /dev/null && exit 1
echo "make sure entry is found (subject) in query language"
${hxtool} query \
--expr='%{certificate.subject} == "CN=kdc,C=SE"' \
FILE:$srcdir/data/kdc.crt > /dev/null || exit 1
echo "make sure entry is found using TAILMATCH (subject) in query language"
${hxtool} query \
--expr='%{certificate.subject} TAILMATCH "C=SE"' \
FILE:$srcdir/data/kdc.crt > /dev/null || exit 1
echo "make sure entry is not found using TAILMATCH (subject) in query language"
${hxtool} query \
--expr='%{certificate.subject} TAILMATCH "C=FI"' \
FILE:$srcdir/data/kdc.crt > /dev/null && exit 1
echo "make sure entry is found (issuer) in query language"
${hxtool} query \
--expr='%{certificate.issuer} == "C=SE,CN=hx509 Test Root CA"' \
FILE:$srcdir/data/kdc.crt > /dev/null || exit 1
echo "make sure entry match with EKU and TAILMATCH in query language"
${hxtool} query \
--expr='"1.3.6.1.5.2.3.5" IN %{certificate.eku} AND %{certificate.subject} TAILMATCH "C=SE"' \
FILE:$srcdir/data/kdc.crt > /dev/null || exit 1
exit 0