diff options
Diffstat (limited to 'src/pluto/ac.c')
-rw-r--r-- | src/pluto/ac.c | 871 |
1 files changed, 119 insertions, 752 deletions
diff --git a/src/pluto/ac.c b/src/pluto/ac.c index 96cc9b274..e35245845 100644 --- a/src/pluto/ac.c +++ b/src/pluto/ac.c @@ -1,6 +1,7 @@ /* Support of X.509 attribute certificates * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler * Copyright (C) 2003 Martin Berner, Lukas Suter + * Copyright (C) 2009 Andreas Steffen * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -18,16 +19,12 @@ #include <string.h> #include <unistd.h> #include <dirent.h> -#include <time.h> #include <sys/types.h> #include <freeswan.h> #include <utils.h> -#include <asn1/asn1.h> -#include <asn1/asn1_parser.h> -#include <asn1/oid.h> -#include <credentials/certificates/certificate.h> +#include <credentials/certificates/ac.h> #include "ac.h" #include "x509.h" @@ -45,597 +42,13 @@ static x509acert_t *x509acerts = NULL; /** - * Chained list of ietfAttributes - */ -static ietfAttrList_t *ietfAttributes = NULL; - -/** - * ASN.1 definition of ietfAttrSyntax - */ -static const asn1Object_t ietfAttrSyntaxObjects[] = -{ - { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_BODY }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ - { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | - ASN1_BODY }, /* 4 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ - { 2, "oid", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 6 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ - { 2, "string", ASN1_UTF8STRING, ASN1_OPT | - ASN1_BODY }, /* 8 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ - { 0, "exit", ASN1_EOC, ASN1_EXIT } -}; - -#define IETF_ATTR_OCTETS 4 -#define IETF_ATTR_OID 6 -#define IETF_ATTR_STRING 8 - -/** - * ASN.1 definition of roleSyntax - */ -static const asn1Object_t roleSyntaxObjects[] = -{ - { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_OBJ }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ }, /* 3 */ - { 0, "exit", ASN1_EOC, ASN1_EXIT } -}; - -/** - * ASN.1 definition of an X509 attribute certificate - */ -static const asn1Object_t acObjects[] = -{ - { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "version", ASN1_INTEGER, ASN1_DEF | - ASN1_BODY }, /* 2 */ - { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ - { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | - ASN1_BODY }, /* 7 */ - { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ - { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_OBJ }, /* 10 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ - { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */ - { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 14 */ - { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ - { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ - { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ - { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | - ASN1_OBJ }, /* 19 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ - { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ - { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ - { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ - { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | - ASN1_BODY }, /* 25 */ - { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ - { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ - { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ - { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 31 */ - { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ - { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ - { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ - { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ - { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ - { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ - { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ - { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ - { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ - { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */ - { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ - { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ - { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ - { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */ - { 4, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 50 */ - { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 54 */ - { 0, "exit", ASN1_EOC, ASN1_EXIT } -}; - -#define AC_OBJ_CERTIFICATE 0 -#define AC_OBJ_CERTIFICATE_INFO 1 -#define AC_OBJ_VERSION 2 -#define AC_OBJ_HOLDER_ISSUER 5 -#define AC_OBJ_HOLDER_SERIAL 6 -#define AC_OBJ_ENTITY_NAME 10 -#define AC_OBJ_ISSUER_NAME 19 -#define AC_OBJ_ISSUER 23 -#define AC_OBJ_SIG_ALG 35 -#define AC_OBJ_SERIAL_NUMBER 36 -#define AC_OBJ_NOT_BEFORE 38 -#define AC_OBJ_NOT_AFTER 39 -#define AC_OBJ_ATTRIBUTE_TYPE 42 -#define AC_OBJ_ATTRIBUTE_VALUE 44 -#define AC_OBJ_EXTN_ID 49 -#define AC_OBJ_CRITICAL 50 -#define AC_OBJ_EXTN_VALUE 51 -#define AC_OBJ_ALGORITHM 53 -#define AC_OBJ_SIGNATURE 54 - -const x509acert_t empty_ac = { - NULL , /* *next */ - 0 , /* installed */ - { NULL, 0 }, /* certificate */ - { NULL, 0 }, /* certificateInfo */ - 1 , /* version */ - /* holder */ - /* baseCertificateID */ - { NULL, 0 }, /* holderIssuer */ - { NULL, 0 }, /* holderSerial */ - /* entityName */ - { NULL, 0 }, /* generalNames */ - /* v2Form */ - { NULL, 0 }, /* issuerName */ - /* signature */ - OID_UNKNOWN, /* sigAlg */ - { NULL, 0 }, /* serialNumber */ - /* attrCertValidityPeriod */ - 0 , /* notBefore */ - 0 , /* notAfter */ - /* attributes */ - NULL , /* charging */ - NULL , /* groups */ - /* extensions */ - { NULL, 0 }, /* authKeyID */ - { NULL, 0 }, /* authKeySerialNumber */ - FALSE , /* noRevAvail */ - /* signatureAlgorithm */ - OID_UNKNOWN, /* algorithm */ - { NULL, 0 }, /* signature */ -}; - - -/** - * compare two ietfAttributes, returns zero if a equals b - * negative/positive if a is earlier/later in the alphabet than b - */ -static int cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b) -{ - int cmp_len, len, cmp_value; - - /* cannot compare OID with STRING or OCTETS attributes */ - if (a->kind == IETF_ATTRIBUTE_OID && b->kind != IETF_ATTRIBUTE_OID) - return 1; - - cmp_len = a->value.len - b->value.len; - len = (cmp_len < 0)? a->value.len : b->value.len; - cmp_value = memcmp(a->value.ptr, b->value.ptr, len); - - return (cmp_value == 0)? cmp_len : cmp_value; -} - -/** - * add an ietfAttribute to the chained list - */ -static ietfAttr_t* add_ietfAttr(ietfAttr_t *attr) -{ - ietfAttrList_t **listp = &ietfAttributes; - ietfAttrList_t *list = *listp; - int cmp = -1; - - while (list != NULL) - { - cmp = cmp_ietfAttr(attr, list->attr); - if (cmp <= 0) - break; - listp = &list->next; - list = *listp; - } - - if (cmp == 0) - { - /* attribute already exists, increase count */ - free(attr); - list->attr->count++; - return list->attr; - } - else - { - ietfAttrList_t *el = malloc_thing(ietfAttrList_t); - - /* new attribute, unshare value */ - attr->value = chunk_clone(attr->value); - attr->count = 1; - time(&attr->installed); - - el->attr = attr; - el->next = list; - *listp = el; - - return attr; - } -} - -/** - * decodes a comma separated list of group attributes - */ -void decode_groups(char *groups, ietfAttrList_t **listp) -{ - if (groups == NULL) - return; - - while (strlen(groups) > 0) - { - char *end; - char *next = strchr(groups, ','); - - if (next == NULL) - end = next = groups + strlen(groups); - else - end = next++; - - /* eat preceeding whitespace */ - while (groups < end && *groups == ' ') - groups++; - - /* eat trailing whitespace */ - while (end > groups && *(end-1) == ' ') - end--; - - if (groups < end) - { - ietfAttr_t *attr = malloc_thing(ietfAttr_t); - ietfAttrList_t *el = malloc_thing(ietfAttrList_t); - - attr->kind = IETF_ATTRIBUTE_STRING; - attr->value.ptr = groups; - attr->value.len = end - groups; - attr->count = 0; - - el->attr = add_ietfAttr(attr); - el->next = *listp; - *listp = el; - } - - groups = next; - } -} - -static bool same_attribute(const ietfAttr_t *a, const ietfAttr_t *b) -{ - return (a->kind == b->kind && a->value.len == b->value.len - && memeq(a->value.ptr, b->value.ptr, b->value.len)); -} - -bool group_membership(const ietfAttrList_t *peer_list - , const char *conn - , const ietfAttrList_t *conn_list) -{ - if (conn_list == NULL) - return TRUE; - - while (peer_list != NULL) - { - const ietfAttr_t *peer_attr = peer_list->attr; - const ietfAttrList_t *list = conn_list; - - while (list != NULL) - { - ietfAttr_t *conn_attr = list->attr; - - if (same_attribute(conn_attr, peer_attr)) - { - DBG(DBG_CONTROL, - DBG_log("%s: peer matches group '%.*s'" - , conn - , (int)peer_attr->value.len, peer_attr->value.ptr) - ) - return TRUE; - } - list = list->next; - } - peer_list = peer_list->next; - } - DBG(DBG_CONTROL, - DBG_log("%s: peer doesn't match any group", conn) - ) - return FALSE; -} - -void unshare_ietfAttrList(ietfAttrList_t **listp) -{ - ietfAttrList_t *list = *listp; - - while (list != NULL) - { - ietfAttrList_t *el = malloc_thing(ietfAttrList_t); - - el->attr = list->attr; - el->attr->count++; - el->next = NULL; - *listp = el; - listp = &el->next; - list = list->next; - } -} - -/** - * Parses ietfAttrSyntax - */ -static ietfAttrList_t* parse_ietfAttrSyntax(chunk_t blob, int level0) -{ - asn1_parser_t *parser; - chunk_t object; - int objectID; - - ietfAttrList_t *list = NULL; - - parser = asn1_parser_create(ietfAttrSyntaxObjects, blob); - parser->set_top_level(parser, level0); - - while (parser->iterate(parser, &objectID, &object)) - { - switch (objectID) - { - case IETF_ATTR_OCTETS: - case IETF_ATTR_OID: - case IETF_ATTR_STRING: - { - ietfAttr_t *attr = malloc_thing(ietfAttr_t); - ietfAttrList_t *el = malloc_thing(ietfAttrList_t); - - attr->kind = (objectID - IETF_ATTR_OCTETS) / 2; - attr->value = object; - attr->count = 0; - - el->attr = add_ietfAttr(attr); - el->next = list; - list = el; - } - break; - default: - break; - } - } - parser->destroy(parser); - return list; -} - -/** - * Parses roleSyntax - */ -static void parse_roleSyntax(chunk_t blob, int level0) -{ - asn1_parser_t *parser; - chunk_t object; - int objectID; - - parser = asn1_parser_create(roleSyntaxObjects, blob); - parser->set_top_level(parser, level0); - - while (parser->iterate(parser, &objectID, &object)) - { - switch (objectID) - { - default: - break; - } - } - parser->destroy(parser); -} - -/** - * Parses an X.509 attribute certificate - */ -bool parse_ac(chunk_t blob, x509acert_t *ac) -{ - asn1_parser_t *parser; - chunk_t object; - int objectID; - int type = OID_UNKNOWN; - int extn_oid = OID_UNKNOWN; - bool success = FALSE; - bool critical; - - parser = asn1_parser_create(acObjects, blob); - - while (parser->iterate(parser, &objectID, &object)) - { - u_int level = parser->get_level(parser)+1; - - switch (objectID) - { - case AC_OBJ_CERTIFICATE: - ac->certificate = object; - break; - case AC_OBJ_CERTIFICATE_INFO: - ac->certificateInfo = object; - break; - case AC_OBJ_VERSION: - ac->version = (object.len) ? (1 + (u_int)*object.ptr) : 1; - DBG(DBG_PARSING, - DBG_log(" v%d", ac->version); - ) - if (ac->version != 2) - { - plog("v%d attribute certificates are not supported" - , ac->version); - goto end; - } - break; - case AC_OBJ_HOLDER_ISSUER: - ac->holderIssuer = get_directoryName(object, level, FALSE); - break; - case AC_OBJ_HOLDER_SERIAL: - ac->holderSerial = object; - break; - case AC_OBJ_ENTITY_NAME: - ac->entityName = get_directoryName(object, level, TRUE); - break; - case AC_OBJ_ISSUER_NAME: - ac->issuerName = get_directoryName(object, level, FALSE); - break; - case AC_OBJ_SIG_ALG: - ac->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL); - break; - case AC_OBJ_SERIAL_NUMBER: - ac->serialNumber = object; - break; - case AC_OBJ_NOT_BEFORE: - ac->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME); - break; - case AC_OBJ_NOT_AFTER: - ac->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME); - break; - case AC_OBJ_ATTRIBUTE_TYPE: - type = asn1_known_oid(object); - break; - case AC_OBJ_ATTRIBUTE_VALUE: - { - switch (type) { - case OID_AUTHENTICATION_INFO: - DBG(DBG_PARSING, - DBG_log(" need to parse authenticationInfo") - ) - break; - case OID_ACCESS_IDENTITY: - DBG(DBG_PARSING, - DBG_log(" need to parse accessIdentity") - ) - break; - case OID_CHARGING_IDENTITY: - ac->charging = parse_ietfAttrSyntax(object, level); - break; - case OID_GROUP: - ac->groups = parse_ietfAttrSyntax(object, level); - break; - case OID_ROLE: - parse_roleSyntax(object, level); - break; - default: - break; - } - } - break; - case AC_OBJ_EXTN_ID: - extn_oid = asn1_known_oid(object); - break; - case AC_OBJ_CRITICAL: - critical = object.len && *object.ptr; - DBG(DBG_PARSING, - DBG_log(" %s",(critical)?"TRUE":"FALSE"); - ) - break; - case AC_OBJ_EXTN_VALUE: - { - switch (extn_oid) { - case OID_CRL_DISTRIBUTION_POINTS: - DBG(DBG_PARSING, - DBG_log(" need to parse crlDistributionPoints") - ) - break; - case OID_AUTHORITY_KEY_ID: - parse_authorityKeyIdentifier(object, level - , &ac->authKeyID, &ac->authKeySerialNumber); - break; - case OID_TARGET_INFORMATION: - DBG(DBG_PARSING, - DBG_log(" need to parse targetInformation") - ) - break; - case OID_NO_REV_AVAIL: - ac->noRevAvail = TRUE; - break; - default: - break; - } - } - break; - case AC_OBJ_ALGORITHM: - ac->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL); - break; - case AC_OBJ_SIGNATURE: - ac->signature = object; - break; - - default: - break; - } - } - success = parser->success(parser); - time(&ac->installed); - -end: - parser->destroy(parser); - return success; -} - -/** - * Release an ietfAttribute, free it if count reaches zero - */ -static void release_ietfAttr(ietfAttr_t* attr) -{ - if (--attr->count == 0) - { - ietfAttrList_t **plist = &ietfAttributes; - ietfAttrList_t *list = *plist; - - while (list->attr != attr) - { - plist = &list->next; - list = *plist; - } - *plist = list->next; - - free(attr->value.ptr); - free(attr); - free(list); - } -} - -/** - * Free an ietfAttrList - */ -void free_ietfAttrList(ietfAttrList_t* list) -{ - while (list != NULL) - { - ietfAttrList_t *el = list; - - release_ietfAttr(el->attr); - list = list->next; - free(el); - } -} - -/** * Free a X.509 attribute certificate */ void free_acert(x509acert_t *ac) { - if (ac != NULL) + if (ac) { - free_ietfAttrList(ac->charging); - free_ietfAttrList(ac->groups); - free(ac->certificate.ptr); + DESTROY_IF(ac->ac); free(ac); } } @@ -656,7 +69,9 @@ static void free_first_acert(void) void free_acerts(void) { while (x509acerts != NULL) + { free_first_acert(); + } } /** @@ -664,25 +79,30 @@ void free_acerts(void) */ x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial) { - x509acert_t *ac = x509acerts; + x509acert_t *x509ac = x509acerts; x509acert_t *prev_ac = NULL; - while (ac != NULL) + while (x509ac != NULL) { - if (same_dn(issuer, ac->holderIssuer) && - chunk_equals(serial, ac->holderSerial)) + ac_t *ac = (ac_t*)x509ac->ac; + identification_t *holderIssuer = ac->get_holderIssuer(ac); + chunk_t holderIssuer_dn = holderIssuer->get_encoding(holderIssuer); + chunk_t holderSerial = ac->get_holderSerial(ac); + + if (same_dn(issuer, holderIssuer_dn) && + chunk_equals(serial, holderSerial)) { - if (ac!= x509acerts) + if (x509ac!= x509acerts) { /* bring the certificate up front */ - prev_ac->next = ac->next; - ac->next = x509acerts; - x509acerts = ac; + prev_ac->next = x509ac->next; + x509ac->next = x509acerts; + x509acerts = x509ac; } - return ac; + return x509ac; } - prev_ac = ac; - ac = ac->next; + prev_ac = x509ac; + x509ac = x509ac->next; } return NULL; } @@ -690,13 +110,19 @@ x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial) /** * Add a X.509 attribute certificate to the chained list */ -static void add_acert(x509acert_t *ac) +static void add_acert(x509acert_t *x509ac) { - x509acert_t *old_ac = get_x509acert(ac->holderIssuer, ac->holderSerial); - + certificate_t *cert_ac = x509ac->ac; + ac_t *ac = (ac_t*)cert_ac; + identification_t *holderIssuer = ac->get_holderIssuer(ac); + chunk_t holderIssuer_dn = holderIssuer->get_encoding(holderIssuer); + chunk_t holderSerial = ac->get_serial(ac); + x509acert_t *old_ac; + + old_ac = get_x509acert(holderIssuer_dn, holderSerial); if (old_ac != NULL) { - if (ac->notBefore >old_ac->notBefore) + if (cert_ac->is_newer(cert_ac, old_ac->ac)) { /* delete the old attribute cert */ free_first_acert(); @@ -709,70 +135,46 @@ static void add_acert(x509acert_t *ac) DBG(DBG_CONTROL, DBG_log("attribute cert is not newer - existing cert kept"); ) - free_acert(ac); + free_acert(x509ac); return; } } plog("attribute cert added"); /* insert new attribute cert at the root of the chain */ - ac->next = x509acerts; - x509acerts = ac; -} - -/** - * Verify the validity of an attribute certificate by - * checking the notBefore and notAfter dates - */ -static err_t check_ac_validity(const x509acert_t *ac) -{ - time_t current_time; - - time(¤t_time); - DBG(DBG_CONTROL | DBG_PARSING, - DBG_log(" not before : %T", &ac->notBefore, TRUE); - DBG_log(" current time: %T", ¤t_time, TRUE); - DBG_log(" not after : %T", &ac->notAfter, TRUE); - ) - - if (current_time < ac->notBefore) - return "attribute certificate is not valid yet"; - if (current_time > ac->notAfter) - return "attribute certificate has expired"; - else - return NULL; + x509ac->next = x509acerts; + x509acerts = x509ac; } /** * verifies a X.509 attribute certificate */ -bool verify_x509acert(x509acert_t *ac, bool strict) +bool verify_x509acert(x509acert_t *x509ac, bool strict) { - u_char buf[BUF_LEN]; + certificate_t *cert_ac = x509ac->ac; + ac_t *ac = (ac_t*)cert_ac; + identification_t *subject = cert_ac->get_subject(cert_ac); + identification_t *issuer = cert_ac->get_issuer(cert_ac); + chunk_t issuer_dn = issuer->get_encoding(issuer); + chunk_t authKeyID = ac->get_authKeyIdentifier(ac); x509cert_t *aacert; - err_t ugh = NULL; - time_t valid_until = ac->notAfter; + time_t valid_until; DBG(DBG_CONTROL, - dntoa(buf, BUF_LEN, ac->entityName); - DBG_log("holder: '%s'",buf); - dntoa(buf, BUF_LEN, ac->issuerName); - DBG_log("issuer: '%s'",buf); + DBG_log("holder: '%Y'", subject); + DBG_log("issuer: '%Y'", issuer); ) - ugh = check_ac_validity(ac); - - if (ugh != NULL) + if (!cert_ac->get_validity(cert_ac, NULL, NULL, &valid_until)) { - plog("%s", ugh); return FALSE; } DBG(DBG_CONTROL, - DBG_log("attribute certificate is valid") + DBG_log("attribute certificate is valid until %T", &valid_until, TRUE) ) lock_authcert_list("verify_x509acert"); - aacert = get_authcert(ac->issuerName, ac->authKeyID, AUTH_AA); + aacert = get_authcert(issuer_dn, authKeyID, X509_AA); unlock_authcert_list("verify_x509acert"); if (aacert == NULL) @@ -784,8 +186,7 @@ bool verify_x509acert(x509acert_t *ac, bool strict) DBG_log("issuer aacert found") ) - if (!x509_check_signature(ac->certificateInfo, ac->signature, ac->algorithm, - aacert->cert)) + if (!cert_ac->issued_by(cert_ac, aacert->cert)) { plog("attribute certificate signature is invalid"); return FALSE; @@ -798,6 +199,31 @@ bool verify_x509acert(x509acert_t *ac, bool strict) } /** + * Check if at least one peer attribute matches a connection attribute + */ +bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn, + ietf_attributes_t *conn_attributes) +{ + bool match; + + if (conn_attributes == NULL) + { + return TRUE; + } + + match = conn_attributes->matches(conn_attributes, peer_attributes); + DBG(DBG_CONTROL, + DBG_log("%s: peer with attributes '%s' is %sa member of the groups '%s'", + conn, + peer_attributes->get_string(peer_attributes), + match ? "" : "not ", + conn_attributes->get_string(conn_attributes)) + ) + return match; + +} + +/** * Loads X.509 attribute certificates */ void load_acerts(void) @@ -840,141 +266,82 @@ void load_acerts(void) } /** - * lists group attributes separated by commas on a single line - */ -void format_groups(const ietfAttrList_t *list, char *buf, int len) -{ - bool first_group = TRUE; - - while (list != NULL && len > 0) - { - ietfAttr_t *attr = list->attr; - - if (attr->kind == IETF_ATTRIBUTE_OCTETS - || attr->kind == IETF_ATTRIBUTE_STRING) - { - int written = snprintf(buf, len, "%s%.*s" - , (first_group)? "" : ", " - , (int)attr->value.len, attr->value.ptr); - - first_group = FALSE; - - /* return value of snprintf() up to glibc 2.0.6 */ - if (written < 0) - break; - - buf += written; - len -= written; - } - list = list->next; - } -} - -/** * list all X.509 attribute certificates in the chained list */ void list_acerts(bool utc) { - x509acert_t *ac = x509acerts; + x509acert_t *x509ac = x509acerts; time_t now; /* determine the current time */ time(&now); - if (ac != NULL) + if (x509ac) { whack_log(RC_COMMENT, " "); whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:"); whack_log(RC_COMMENT, " "); } - while (ac != NULL) + while (x509ac) { - u_char buf[BUF_LEN]; + certificate_t *cert_ac = x509ac->ac; + ac_t *ac = (ac_t*)cert_ac; + identification_t *entityName, *holderIssuer, *issuer; + chunk_t holderSerial, serial, authKeyID; + time_t notBefore, notAfter; + ietf_attributes_t *groups; - whack_log(RC_COMMENT, "%T", &ac->installed, utc); - if (ac->entityName.ptr != NULL) - { - dntoa(buf, BUF_LEN, ac->entityName); - whack_log(RC_COMMENT, " holder: '%s'", buf); - } - if (ac->holderIssuer.ptr != NULL) - { - dntoa(buf, BUF_LEN, ac->holderIssuer); - whack_log(RC_COMMENT, " hissuer: '%s'", buf); - } - if (ac->holderSerial.ptr != NULL) + + whack_log(RC_COMMENT, "%T", &x509ac->installed, utc); + + entityName = cert_ac->get_subject(cert_ac); + if (entityName) { - datatot(ac->holderSerial.ptr, ac->holderSerial.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " hserial: %s", buf); + whack_log(RC_COMMENT, " holder: '%Y'", entityName); } - if (ac->groups != NULL) + + holderIssuer = ac->get_holderIssuer(ac); + if (holderIssuer) { - format_groups(ac->groups, buf, BUF_LEN); - whack_log(RC_COMMENT, " groups: %s", buf); + whack_log(RC_COMMENT, " hissuer: '%Y'", holderIssuer); } - dntoa(buf, BUF_LEN, ac->issuerName); - whack_log(RC_COMMENT, " issuer: '%s'", buf); - datatot(ac->serialNumber.ptr, ac->serialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " serial: %s", buf); - whack_log(RC_COMMENT, " validity: not before %T %s", - &ac->notBefore, utc, - (ac->notBefore < now)?"ok":"fatal (not valid yet)"); - whack_log(RC_COMMENT, " not after %T %s", - &ac->notAfter, utc, - check_expiry(ac->notAfter, ACERT_WARNING_INTERVAL, TRUE)); - if (ac->authKeyID.ptr != NULL) + + holderSerial = ac->get_holderSerial(ac); + if (holderSerial.ptr) { - datatot(ac->authKeyID.ptr, ac->authKeyID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authkey: %s", buf); + whack_log(RC_COMMENT, " hserial: %#B", &holderSerial); } - if (ac->authKeySerialNumber.ptr != NULL) + + groups = ac->get_groups(ac); + if (groups) { - datatot(ac->authKeySerialNumber.ptr, ac->authKeySerialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); + whack_log(RC_COMMENT, " groups: %s", + groups->get_string(groups)); + groups->destroy(groups); } - ac = ac->next; - } -} + issuer = cert_ac->get_issuer(cert_ac); + whack_log(RC_COMMENT, " issuer: '%Y'", issuer); -/** - * list all group attributes in alphabetical order - */ -void list_groups(bool utc) -{ - ietfAttrList_t *list = ietfAttributes; + serial = ac->get_serial(ac); + whack_log(RC_COMMENT, " serial: %#B", &serial); - if (list != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of Group Attributes:"); - whack_log(RC_COMMENT, " "); - } - - while (list != NULL) - { - ietfAttr_t *attr = list->attr; - - whack_log(RC_COMMENT, "%T, count: %d", &attr->installed, utc, attr->count); + cert_ac->get_validity(cert_ac, &now, ¬Before, ¬After); + whack_log(RC_COMMENT, " validity: not before %T %s", + ¬Before, utc, + (notBefore < now)?"ok":"fatal (not valid yet)"); + whack_log(RC_COMMENT, " not after %T %s", + ¬After, utc, + check_expiry(notAfter, ACERT_WARNING_INTERVAL, TRUE)); - switch (attr->kind) + authKeyID = ac->get_authKeyIdentifier(ac); + if (authKeyID.ptr) { - case IETF_ATTRIBUTE_OCTETS: - case IETF_ATTRIBUTE_STRING: - whack_log(RC_COMMENT, " %.*s", (int)attr->value.len, attr->value.ptr); - break; - case IETF_ATTRIBUTE_OID: - whack_log(RC_COMMENT, " OID"); - break; - default: - break; + whack_log(RC_COMMENT, " authkey: %#B", &authKeyID); } - list = list->next; + x509ac = x509ac->next; } } + |