diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2009-10-05 07:24:28 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2009-10-05 07:24:28 +0200 |
commit | fc12e3cd2eccee07fa3b15d519a24673f15f277d (patch) | |
tree | 0068a60daf9c8303768b495feacda98c4cee7272 /src/pluto | |
parent | 0ea9cbc6e9d0743e863de6d3d141761d5c5036c6 (diff) | |
download | strongswan-fc12e3cd2eccee07fa3b15d519a24673f15f277d.tar.bz2 strongswan-fc12e3cd2eccee07fa3b15d519a24673f15f277d.tar.xz |
pluto now uses x509 plugin for attribute certificate handling
Diffstat (limited to 'src/pluto')
-rw-r--r-- | src/pluto/ac.c | 871 | ||||
-rw-r--r-- | src/pluto/ac.h | 74 | ||||
-rw-r--r-- | src/pluto/builder.c | 14 | ||||
-rw-r--r-- | src/pluto/ca.c | 28 | ||||
-rw-r--r-- | src/pluto/ca.h | 25 | ||||
-rw-r--r-- | src/pluto/certs.c | 10 | ||||
-rw-r--r-- | src/pluto/certs.h | 3 | ||||
-rw-r--r-- | src/pluto/connections.c | 134 | ||||
-rw-r--r-- | src/pluto/connections.h | 6 | ||||
-rw-r--r-- | src/pluto/crl.c | 4 | ||||
-rw-r--r-- | src/pluto/ipsec_doi.c | 32 | ||||
-rw-r--r-- | src/pluto/ocsp.c | 8 | ||||
-rw-r--r-- | src/pluto/plutomain.c | 6 | ||||
-rw-r--r-- | src/pluto/rcv_whack.c | 17 | ||||
-rw-r--r-- | src/pluto/x509.c | 18 | ||||
-rw-r--r-- | src/pluto/x509.h | 3 |
16 files changed, 312 insertions, 941 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; } } + diff --git a/src/pluto/ac.h b/src/pluto/ac.h index bee016143..d1feb5570 100644 --- a/src/pluto/ac.h +++ b/src/pluto/ac.h @@ -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 @@ -17,85 +18,28 @@ #ifndef _AC_H #define _AC_H -/* definition of ietfAttribute kinds */ - -typedef enum { - IETF_ATTRIBUTE_OCTETS = 0, - IETF_ATTRIBUTE_OID = 1, - IETF_ATTRIBUTE_STRING = 2 -} ietfAttribute_t; - -/* access structure for an ietfAttribute */ - -typedef struct ietfAttr ietfAttr_t; - -struct ietfAttr { - time_t installed; - int count; - ietfAttribute_t kind; - chunk_t value; -}; - -typedef struct ietfAttrList ietfAttrList_t; - -struct ietfAttrList { - ietfAttrList_t *next; - ietfAttr_t *attr; -}; +#include <time.h> +#include <credentials/certificates/certificate.h> +#include <credentials/ietf_attributes/ietf_attributes.h> /* access structure for an X.509 attribute certificate */ typedef struct x509acert x509acert_t; struct x509acert { - x509acert_t *next; - time_t installed; - chunk_t certificate; - chunk_t certificateInfo; - u_int version; - /* holder */ - /* baseCertificateID */ - chunk_t holderIssuer; - chunk_t holderSerial; - chunk_t entityName; - /* v2Form */ - chunk_t issuerName; - /* signature */ - int sigAlg; - chunk_t serialNumber; - /* attrCertValidityPeriod */ - time_t notBefore; - time_t notAfter; - /* attributes */ - ietfAttrList_t *charging; - ietfAttrList_t *groups; - /* extensions */ - chunk_t authKeyID; - chunk_t authKeySerialNumber; - bool noRevAvail; - /* signatureAlgorithm */ - int algorithm; - chunk_t signature; + certificate_t *ac; + x509acert_t *next; + time_t installed; }; -/* used for initialization */ -extern const x509acert_t empty_ac; - -extern void unshare_ietfAttrList(ietfAttrList_t **listp); -extern void free_ietfAttrList(ietfAttrList_t *list); -extern void decode_groups(char *groups, ietfAttrList_t **listp); -extern bool group_membership(const ietfAttrList_t *my_list - , const char *conn, const ietfAttrList_t *conn_list); -extern bool parse_ac(chunk_t blob, x509acert_t *ac); extern bool verify_x509acert(x509acert_t *ac, bool strict); +extern bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn, + ietf_attributes_t *conn_attributes); extern x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial); extern void load_acerts(void); extern void free_acert(x509acert_t *ac); extern void free_acerts(void); extern void list_acerts(bool utc); -extern void list_groups(bool utc); -extern void format_groups(const ietfAttrList_t *list, char *buf, int len); - #endif /* _AH_H */ diff --git a/src/pluto/builder.c b/src/pluto/builder.c index 8a90e05af..b8b9aac35 100644 --- a/src/pluto/builder.c +++ b/src/pluto/builder.c @@ -40,6 +40,7 @@ */ static cert_t *builder_load_cert(certificate_type_t type, va_list args) { + x509_flag_t flags = 0; chunk_t blob = chunk_empty; bool pgp = FALSE; @@ -53,6 +54,9 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args) case BUILD_BLOB_ASN1_DER: blob = va_arg(args, chunk_t); continue; + case BUILD_X509_FLAG: + flags |= va_arg(args, x509_flag_t); + continue; case BUILD_END: break; default: @@ -85,6 +89,7 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args) x509cert->cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_BLOB_ASN1_DER, blob, + BUILD_X509_FLAG, flags, BUILD_END); if (x509cert->cert) { @@ -128,9 +133,12 @@ static x509acert_t *builder_load_ac(certificate_type_t type, va_list args) if (blob.ptr) { ac = malloc_thing(x509acert_t); - *ac = empty_ac; - if (parse_ac(chunk_clone(blob), ac) && - verify_x509acert(ac, FALSE)) + ac->next = NULL; + ac->installed = UNDEFINED_TIME; + ac->ac = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_AC, + BUILD_BLOB_ASN1_DER, blob, BUILD_END); + if (ac->ac && verify_x509acert(ac, FALSE)) { return ac; } diff --git a/src/pluto/ca.c b/src/pluto/ca.c index bc6bfe9ad..816e71087 100644 --- a/src/pluto/ca.c +++ b/src/pluto/ca.c @@ -81,7 +81,7 @@ bool trusted_ca(chunk_t a, chunk_t b, int *pathlen) chunk_t issuer_dn; x509cert_t *cacert; - cacert = get_authcert(a, chunk_empty, AUTH_CA); + cacert = get_authcert(a, chunk_empty, X509_CA); if (cacert == NULL) { break; @@ -180,7 +180,7 @@ void free_authcerts(void) /* * get a X.509 authority certificate with a given subject or keyid */ -x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags) +x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, x509_flag_t auth_flags) { x509cert_t *cert, *prev_cert = NULL; @@ -193,11 +193,12 @@ x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags) for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next) { certificate_t *certificate = cert->cert; + x509_t *x509 = (x509_t*)certificate; identification_t *cert_subject; chunk_t cert_subject_dn; /* skip non-matching types of authority certificates */ - if (!(cert->authority_flags & auth_flags)) + if (!(x509->get_flags(x509) & auth_flags)) { continue; } @@ -205,7 +206,6 @@ x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags) /* compare the keyid with the certificate's subjectKeyIdentifier */ if (keyid.ptr) { - x509_t *x509 = (x509_t*)certificate; chunk_t subjectKeyId; subjectKeyId = x509->get_subjectKeyIdentifier(x509); @@ -239,7 +239,7 @@ x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags) /* * add an authority certificate to the chained list */ -x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags) +x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags) { certificate_t *certificate = cert->cert; x509_t *x509 = (x509_t*)certificate; @@ -247,9 +247,6 @@ x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags) chunk_t cert_subject_dn = cert_subject->get_encoding(cert_subject); x509cert_t *old_cert; - /* set authority flags */ - cert->authority_flags |= auth_flags; - lock_authcert_list("add_authcert"); old_cert = get_authcert(cert_subject_dn, @@ -259,8 +256,6 @@ x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags) { if (certificate->equals(certificate, old_cert->cert)) { - /* cert is already present, just add additional authority flags */ - old_cert->authority_flags |= cert->authority_flags; DBG(DBG_CONTROL | DBG_PARSING , DBG_log(" authcert is already present and identical") ) @@ -293,7 +288,7 @@ x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags) /* * Loads authority certificates */ -void load_authcerts(const char *type, const char *path, u_char auth_flags) +void load_authcerts(const char *type, const char *path, x509_flag_t auth_flags) { struct dirent **filelist; u_char buf[BUF_LEN]; @@ -320,9 +315,10 @@ void load_authcerts(const char *type, const char *path, u_char auth_flags) { cert_t cert; - if (load_cert(filelist[n]->d_name, type, &cert)) + if (load_cert(filelist[n]->d_name, type, auth_flags, &cert)) + { add_authcert(cert.u.x509, auth_flags); - + } free(filelist[n]); } free(filelist); @@ -335,7 +331,7 @@ void load_authcerts(const char *type, const char *path, u_char auth_flags) /* * list all X.509 authcerts with given auth flags in a chained list */ -void list_authcerts(const char *caption, u_char auth_flags, bool utc) +void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc) { lock_authcert_list("list_authcerts"); list_x509cert_chain(caption, x509authcerts, auth_flags, utc); @@ -426,7 +422,7 @@ bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chai else { /* search in trusted chain */ - authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA); + authcert = get_authcert(issuer_dn, authKeyID, X509_CA); if (authcert != NULL) { @@ -670,7 +666,7 @@ void add_ca_info(const whack_message_t *msg) unlock_ca_info_list("add_ca_info"); /* add cacert to list of authcerts */ - cacert = add_authcert(cacert, AUTH_CA); + cacert = add_authcert(cacert, X509_CA); if (!cached_cert && sc != NULL) { if (sc->last_cert.type == CERT_X509_SIGNATURE) diff --git a/src/pluto/ca.h b/src/pluto/ca.h index eadb96dba..8c7627d2b 100644 --- a/src/pluto/ca.h +++ b/src/pluto/ca.h @@ -22,13 +22,6 @@ #define MAX_CA_PATH_LEN 7 -/* authority flags */ - -#define AUTH_NONE 0x00 /* no authorities */ -#define AUTH_CA 0x01 /* certification authority */ -#define AUTH_AA 0x02 /* authorization authority */ -#define AUTH_OCSP 0x04 /* ocsp signing authority */ - /* CA info structures */ typedef struct ca_info ca_info_t; @@ -47,17 +40,17 @@ struct ca_info { }; extern bool trusted_ca(chunk_t a, chunk_t b, int *pathlen); -extern bool match_requested_ca(generalName_t *requested_ca - , chunk_t our_ca, int *our_pathlen); +extern bool match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, + int *our_pathlen); extern x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, - u_char auth_flags); -extern void load_authcerts(const char *type, const char *path - , u_char auth_flags); -extern x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags); + x509_flag_t auth_flags); +extern void load_authcerts(const char *type, const char *path, + x509_flag_t auth_flags); +extern x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags); extern void free_authcerts(void); -extern void list_authcerts(const char *caption, u_char auth_flags, bool utc); -extern bool trust_authcert_candidate(const x509cert_t *cert - , const x509cert_t *alt_chain); +extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc); +extern bool trust_authcert_candidate(const x509cert_t *cert, + const x509cert_t *alt_chain); extern ca_info_t* get_ca_info(chunk_t name, chunk_t keyid); extern bool find_ca_info_by_name(const char *name, bool delete); extern void add_ca_info(const whack_message_t *msg); diff --git a/src/pluto/certs.c b/src/pluto/certs.c index cdf567e90..456a45fca 100644 --- a/src/pluto/certs.c +++ b/src/pluto/certs.c @@ -162,12 +162,14 @@ private_key_t* load_private_key(char* filename, prompt_pass_t *pass, /** * Loads a X.509 or OpenPGP certificate */ -bool load_cert(char *filename, const char *label, cert_t *out) +bool load_cert(char *filename, const char *label, x509_flag_t flags, cert_t *out) { cert_t *cert; cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT, - BUILD_FROM_FILE, filename, BUILD_END); + BUILD_FROM_FILE, filename, + BUILD_X509_FLAG, flags, + BUILD_END); if (cert) { /* the API passes an empty cert_t, we move over and free the built one */ @@ -186,7 +188,7 @@ bool load_host_cert(char *filename, cert_t *cert) { char *path = concatenate_paths(HOST_CERT_PATH, filename); - return load_cert(path, "host", cert); + return load_cert(path, "host", X509_NONE, cert); } /** @@ -196,7 +198,7 @@ bool load_ca_cert(char *filename, cert_t *cert) { char *path = concatenate_paths(CA_CERT_PATH, filename); - return load_cert(path, "CA", cert); + return load_cert(path, "CA", X509_NONE, cert); } /** diff --git a/src/pluto/certs.h b/src/pluto/certs.h index 1bd03edcd..faf820dae 100644 --- a/src/pluto/certs.h +++ b/src/pluto/certs.h @@ -66,7 +66,8 @@ extern public_key_t* cert_get_public_key(const cert_t cert); extern chunk_t cert_get_encoding(cert_t cert); extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass, key_type_t type); -extern bool load_cert(char *filename, const char *label, cert_t *cert); +extern bool load_cert(char *filename, const char *label, x509_flag_t flags, + cert_t *cert); extern bool load_host_cert(char *filename, cert_t *cert); extern bool load_ca_cert(char *filename, cert_t *cert); extern bool same_cert(const cert_t *a, const cert_t *b); diff --git a/src/pluto/connections.c b/src/pluto/connections.c index d375e49a0..e1a28cade 100644 --- a/src/pluto/connections.c +++ b/src/pluto/connections.c @@ -30,6 +30,7 @@ #include <freeswan.h> #include "kameipsec.h" +#include <credentials/certificates/ac.h> #include <credentials/keys/private_key.h> #include "constants.h" @@ -336,11 +337,11 @@ void delete_connection(connection_t *c, bool relations) free_id_content(&c->spd.this.id); free(c->spd.this.updown); free(c->spd.this.ca.ptr); - free_ietfAttrList(c->spd.this.groups); + DESTROY_IF(c->spd.this.groups); free_id_content(&c->spd.that.id); free(c->spd.that.updown); free(c->spd.that.ca.ptr); - free_ietfAttrList(c->spd.that.groups); + DESTROY_IF(c->spd.that.groups); free_generalNames(c->requested_ca, TRUE); gw_delref(&c->gw_info); @@ -812,7 +813,7 @@ static bool extract_end(struct end *dst, const whack_end_t *src, dst->ca = chunk_empty; /* decode CA distinguished name, if any */ - if (src->ca != NULL) + if (src->ca) { if streq(src->ca, "%same") same_ca = TRUE; @@ -837,7 +838,10 @@ static bool extract_end(struct end *dst, const whack_end_t *src, dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0; /* decode group attributes, if any */ - decode_groups(src->groups, &dst->groups); + if (src->groups) + { + dst->groups = ietf_attributes_create_from_string(src->groups); + } /* the rest is simple copying of corresponding fields */ dst->host_addr = src->host_addr; @@ -1261,8 +1265,14 @@ static connection_t *instantiate(connection_t *c, d->spd.that.has_id_wildcards = FALSE; } unshare_connection_strings(d); - unshare_ietfAttrList(&d->spd.this.groups); - unshare_ietfAttrList(&d->spd.that.groups); + if (d->spd.this.groups) + { + d->spd.this.groups = d->spd.this.groups->get_ref(d->spd.this.groups); + } + if (d->spd.that.groups) + { + d->spd.that.groups = d->spd.that.groups->get_ref(d->spd.that.groups); + } d->kind = CK_INSTANCE; passert(oriented(*d)); @@ -1519,7 +1529,9 @@ connection_t *find_connection_for_clients(struct spd_route **srp, for (c = connections; c != NULL; c = c->ac_next) { if (c->kind == CK_GROUP) + { continue; + } for (sr = &c->spd; best!=c && sr; sr = sr->next) { @@ -1727,7 +1739,9 @@ bool orient(connection_t *c) for (p = interfaces; p != NULL; p = p->next) { if (p->ike_float) + { continue; + } for (;;) { @@ -3036,11 +3050,17 @@ connection_t *route_owner(connection_t *c, struct spd_route **srp, for (src = &c->spd; src; src=src->next) { if (!samesubnet(&src->that.client, &srd->that.client)) + { continue; + } if (src->that.protocol != srd->that.protocol) + { continue; + } if (src->that.port != srd->that.port) + { continue; + } passert(oriented(*d)); if (srd->routing > best_routing) { @@ -3050,11 +3070,17 @@ connection_t *route_owner(connection_t *c, struct spd_route **srp, } if (!samesubnet(&src->this.client, &srd->this.client)) + { continue; + } if (src->this.protocol != srd->this.protocol) + { continue; + } if (src->this.port != srd->this.port) + { continue; + } if (srd->routing > best_erouting) { best_ero = d; @@ -3332,11 +3358,15 @@ connection_t *refine_host_connection(const struct state *st, /* do we have a match? */ if (!match) + { continue; + } /* ignore group connections */ if (d->policy & POLICY_GROUP) + { continue; + } if (c->spd.that.host_port != d->spd.that.host_port && d->kind == CK_INSTANCE) @@ -3354,12 +3384,17 @@ connection_t *refine_host_connection(const struct state *st, const chunk_t *dpsk = get_preshared_secret(d); if (dpsk == NULL) + { continue; /* no secret */ - + } if (psk != dpsk) + { if (psk->len != dpsk->len || memcmp(psk->ptr, dpsk->ptr, psk->len) != 0) + { continue; /* different secret */ + } + } } break; @@ -3374,7 +3409,9 @@ connection_t *refine_host_connection(const struct state *st, .*/ if (d->spd.this.sc == NULL /* no smartcard */ && get_private_key(d) == NULL) /* no private key */ + { continue; + } break; default: @@ -3488,7 +3525,7 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp, const u_int8_t peer_protocol, const u_int16_t peer_port, chunk_t peer_ca, - const ietfAttrList_t *peer_list) + ietf_attributes_t *peer_attributes) { connection_t *d; connection_t *best = NULL; @@ -3502,20 +3539,26 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp, struct spd_route *sr; if (d->policy & POLICY_GROUP) + { continue; + } if (!(same_id(&c->spd.this.id, &d->spd.this.id) && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards) && trusted_ca(peer_ca, d->spd.that.ca, &pathlen) - && group_membership(peer_list, d->name, d->spd.that.groups))) + && match_group_membership(peer_attributes, d->name, d->spd.that.groups))) + { continue; + } /* compare protocol and ports */ if (d->spd.this.protocol != our_protocol || d->spd.this.port != our_port || d->spd.that.protocol != peer_protocol || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard)) + { continue; + } /* non-Opportunistic case: * our_client must match. @@ -3552,29 +3595,38 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp, #endif /* DEBUG */ if (!samesubnet(&sr->this.client, our_net)) + { continue; - + } if (sr->that.has_client) { if (sr->that.has_client_wildcard) { if (!subnetinsubnet(peer_net, &sr->that.client)) + { continue; + } } else { if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d)) + { continue; + } if (is_virtual_connection(d) && (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr) || is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id))) - continue; + { + continue; + } } } else { if (!peer_net_is_host) + { continue; + } } /* We've run the gauntlet -- success: @@ -3616,7 +3668,7 @@ static connection_t *fc_try_oppo(const connection_t *c, const u_int8_t peer_protocol, const u_int16_t peer_port, chunk_t peer_ca, - const ietfAttrList_t *peer_list) + ietf_attributes_t *peer_attributes) { connection_t *d; connection_t *best = NULL; @@ -3629,20 +3681,25 @@ static connection_t *fc_try_oppo(const connection_t *c, policy_prio_t prio; if (d->policy & POLICY_GROUP) + { continue; - + } if (!(same_id(&c->spd.this.id, &d->spd.this.id) && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards) && trusted_ca(peer_ca, d->spd.that.ca, &pathlen) - && group_membership(peer_list, d->name, d->spd.that.groups))) + && match_group_membership(peer_attributes, d->name, d->spd.that.groups))) + { continue; + } /* compare protocol and ports */ if (d->spd.this.protocol != our_protocol || d->spd.this.port != our_port || d->spd.that.protocol != peer_protocol || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard)) + { continue; + } /* Opportunistic case: * our_net must be inside d->spd.this.client @@ -3670,7 +3727,9 @@ static connection_t *fc_try_oppo(const connection_t *c, if (!subnetinsubnet(our_net, &sr->this.client) || !subnetinsubnet(peer_net, &sr->that.client)) + { continue; + } /* The connection is feasible, but we continue looking for the best. * The highest priority wins, implementing eroute-like rule. @@ -3710,21 +3769,25 @@ static connection_t *fc_try_oppo(const connection_t *c, /* * get the peer's CA and group attributes */ -chunk_t get_peer_ca_and_groups(connection_t *c, const ietfAttrList_t **peer_list) +chunk_t get_peer_ca_and_groups(connection_t *c, ietf_attributes_t **peer_attributes) { struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); - *peer_list = NULL; + *peer_attributes = NULL; if (p1st != NULL && p1st->st_peer_pubkey != NULL && p1st->st_peer_pubkey->issuer.ptr != NULL) { - x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer - , p1st->st_peer_pubkey->serial);; + x509acert_t *x509ac = get_x509acert(p1st->st_peer_pubkey->issuer, + p1st->st_peer_pubkey->serial); - if (ac != NULL && verify_x509acert(ac, strict_crl_policy)) - *peer_list = ac->groups; + if (x509ac && verify_x509acert(x509ac, strict_crl_policy)) + { + ac_t * ac = (ac_t*)x509ac->ac; + + *peer_attributes = ac->get_groups(ac); + } else { DBG(DBG_CONTROL, @@ -3746,9 +3809,8 @@ connection_t *find_client_connection(connection_t *c, { connection_t *d; struct spd_route *sr; - - const ietfAttrList_t *peer_list = NULL; - chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list); + ietf_attributes_t *peer_attributes = NULL; + chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_attributes); #ifdef DEBUG if (DBGP(DBG_CONTROLMORE)) @@ -3795,12 +3857,14 @@ connection_t *find_client_connection(connection_t *c, && sr->this.port == our_port && sr->that.protocol == peer_protocol && sr->that.port == peer_port - && group_membership(peer_list, c->name, sr->that.groups)) + && match_group_membership(peer_attributes, c->name, sr->that.groups)) { passert(oriented(*c)); if (routed(sr->routing)) + { + DESTROY_IF(peer_attributes); return c; - + } unrouted = c; } } @@ -3808,7 +3872,7 @@ connection_t *find_client_connection(connection_t *c, /* exact match? */ d = fc_try(c, c->host_pair, NULL, our_net, peer_net , our_protocol, our_port, peer_protocol, peer_port - , peer_ca, peer_list); + , peer_ca, peer_attributes); DBG(DBG_CONTROLMORE, DBG_log(" fc_try %s gives %s" @@ -3817,7 +3881,9 @@ connection_t *find_client_connection(connection_t *c, ) if (d == NULL) + { d = unrouted; + } } if (d == NULL) @@ -3852,7 +3918,7 @@ connection_t *find_client_connection(connection_t *c, /* RW match with actual peer_id or abstract peer_id? */ d = fc_try(c, hp, NULL, our_net, peer_net , our_protocol, our_port, peer_protocol, peer_port - , peer_ca, peer_list); + , peer_ca, peer_attributes); if (d == NULL && subnetishost(our_net) @@ -3864,7 +3930,7 @@ connection_t *find_client_connection(connection_t *c, */ d = fc_try_oppo(c, hp, our_net, peer_net , our_protocol, our_port, peer_protocol, peer_port - , peer_ca, peer_list); + , peer_ca, peer_attributes); } } } @@ -3873,6 +3939,7 @@ connection_t *find_client_connection(connection_t *c, DBG_log(" concluding with d = %s" , (d ? d->name : "none")) ) + DESTROY_IF(peer_attributes); return d; } @@ -3978,8 +4045,7 @@ void show_connections_status(bool all, const char *name) dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any"); dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any"); - whack_log(RC_COMMENT - , "\"%s\"%s: CAs: '%s'...'%s'" + whack_log(RC_COMMENT, "\"%s\"%s: CAs: '%s'...'%s'" , c->name , instance , this_ca @@ -3989,14 +4055,10 @@ void show_connections_status(bool all, const char *name) /* show group attributes if defined */ if (c->spd.that.groups != NULL) { - char buf[BUF_LEN]; - - format_groups(c->spd.that.groups, buf, BUF_LEN); - whack_log(RC_COMMENT - , "\"%s\"%s: groups: %s" + whack_log(RC_COMMENT, "\"%s\"%s: groups: %s" , c->name , instance - , buf); + , c->spd.that.groups->get_string(c->spd.that.groups)); } whack_log(RC_COMMENT diff --git a/src/pluto/connections.h b/src/pluto/connections.h index d6881499b..5bef59b66 100644 --- a/src/pluto/connections.h +++ b/src/pluto/connections.h @@ -146,7 +146,7 @@ struct end { u_int8_t protocol; cert_t cert; /* end certificate */ chunk_t ca; /* CA distinguished name */ - struct ietfAttrList *groups;/* access control groups */ + ietf_attributes_t *groups; /* access control groups */ smartcard_t *sc; /* smartcard reader and key info */ struct virtual_t *virt; bool modecfg; /* this end: request local address from server */ @@ -288,8 +288,8 @@ find_connection_for_clients(struct spd_route **srp , const ip_address *peer_client , int transport_proto); -extern chunk_t get_peer_ca_and_groups(connection_t *c - , const ietfAttrList_t **peer_list); +extern chunk_t get_peer_ca_and_groups(connection_t *c, + ietf_attributes_t **peer_attributes); /* instantiating routines * Note: connection_discard() is in state.h because all its work diff --git a/src/pluto/crl.c b/src/pluto/crl.c index 38e8027d7..01d4839fc 100644 --- a/src/pluto/crl.c +++ b/src/pluto/crl.c @@ -133,7 +133,7 @@ bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl) lock_authcert_list("insert_crl"); /* get the issuer cacert */ - issuer_cert = get_authcert(issuer_dn, authKeyID, AUTH_CA); + issuer_cert = get_authcert(issuer_dn, authKeyID, X509_CA); if (issuer_cert == NULL) { plog("crl issuer cacert not found"); @@ -434,7 +434,7 @@ cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until, lock_authcert_list("verify_by_crl"); - issuer_cert = get_authcert(issuer_dn, authKeyID, AUTH_CA); + issuer_cert = get_authcert(issuer_dn, authKeyID, X509_CA); valid = cert_crl->issued_by(cert_crl, issuer_cert->cert); unlock_authcert_list("verify_by_crl"); diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index 9e941192c..eaa4a7a8c 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -5182,29 +5182,33 @@ stf_status quick_inR1_outI2(struct msg_digest *md) } /* check the peer's group attributes */ - { - const ietfAttrList_t *peer_list = NULL; + ietf_attributes_t *peer_attributes = NULL; + bool match; - get_peer_ca_and_groups(st->st_connection, &peer_list); + get_peer_ca_and_groups(st->st_connection, &peer_attributes); + match = match_group_membership(peer_attributes, + st->st_connection->name, + st->st_connection->spd.that.groups); + DESTROY_IF(peer_attributes); - if (!group_membership(peer_list, st->st_connection->name - , st->st_connection->spd.that.groups)) + if (!match) { - char buf[BUF_LEN]; + ietf_attributes_t *groups = st->st_connection->spd.that.groups; - format_groups(st->st_connection->spd.that.groups, buf, BUF_LEN); - loglog(RC_LOG_SERIOUS, "peer is not member of one of the groups: %s" - , buf); + loglog(RC_LOG_SERIOUS, + "peer with attributes '%s' is not a member of the groups '%s'", + peer_attributes->get_string(peer_attributes), + groups->get_string(groups)); return STF_FAIL + INVALID_ID_INFORMATION; } } - if ((st->nat_traversal & NAT_T_DETECTED) - && (st->nat_traversal & NAT_T_WITH_NATOA)) - { - nat_traversal_natoa_lookup(md); - } + if ((st->nat_traversal & NAT_T_DETECTED) + && (st->nat_traversal & NAT_T_WITH_NATOA)) + { + nat_traversal_natoa_lookup(md); + } /* ??? We used to copy the accepted proposal into the state, but it was * never used. From sa_pd->pbs.start, length pbs_room(&sa_pd->pbs). diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c index 510667e67..d980e7f14 100644 --- a/src/pluto/ocsp.c +++ b/src/pluto/ocsp.c @@ -329,7 +329,7 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio if (authKeyID.ptr == NULL) { - x509cert_t *authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA); + x509cert_t *authcert = get_authcert(issuer_dn, authKeyID, X509_CA); if (authcert != NULL) { @@ -983,7 +983,7 @@ static bool valid_ocsp_response(response_t *res) lock_authcert_list("valid_ocsp_response"); authcert = get_authcert(res->responder_id_name, res->responder_id_key, - AUTH_OCSP | AUTH_CA); + X509_OCSP_SIGNER | X509_CA); if (authcert == NULL) { plog("no matching ocsp signer cert found"); @@ -1040,7 +1040,7 @@ static bool valid_ocsp_response(response_t *res) DBG_log("certificate is valid") ) - authcert = get_authcert(issuer->get_encoding(issuer), authKeyID, AUTH_CA); + authcert = get_authcert(issuer->get_encoding(issuer), authKeyID, X509_CA); if (authcert == NULL) { plog("issuer cacert not found"); @@ -1168,7 +1168,7 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) if ((x509->get_flags(x509) & X509_OCSP_SIGNER) && trust_authcert_candidate(cert, NULL)) { - add_authcert(cert, AUTH_OCSP); + add_authcert(cert, X509_OCSP_SIGNER); } else { diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index 78afeacb6..203c24c84 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -720,11 +720,11 @@ int main(int argc, char **argv) #endif /* CAPABILITIES */ /* loading X.509 CA certificates */ - load_authcerts("CA", CA_CERT_PATH, AUTH_CA); + load_authcerts("CA", CA_CERT_PATH, X509_CA); /* loading X.509 AA certificates */ - load_authcerts("AA", AA_CERT_PATH, AUTH_AA); + load_authcerts("AA", AA_CERT_PATH, X509_AA); /* loading X.509 OCSP certificates */ - load_authcerts("OCSP", OCSP_CERT_PATH, AUTH_OCSP); + load_authcerts("OCSP", OCSP_CERT_PATH, X509_OCSP_SIGNER); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c index ef984f66a..d84a9f5f1 100644 --- a/src/pluto/rcv_whack.c +++ b/src/pluto/rcv_whack.c @@ -451,17 +451,17 @@ whack_handle(int whackctlfd) if (msg.whack_reread & REREAD_CACERTS) { - load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA); + load_authcerts("CA cert", CA_CERT_PATH, X509_CA); } if (msg.whack_reread & REREAD_AACERTS) { - load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA); + load_authcerts("AA cert", AA_CERT_PATH, X509_AA); } if (msg.whack_reread & REREAD_OCSPCERTS) { - load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP); + load_authcerts("OCSP cert", OCSP_CERT_PATH, X509_OCSP_SIGNER); } if (msg.whack_reread & REREAD_ACERTS) @@ -492,17 +492,17 @@ whack_handle(int whackctlfd) if (msg.whack_list & LIST_CACERTS) { - list_authcerts("CA", AUTH_CA, msg.whack_utc); + list_authcerts("CA", X509_CA, msg.whack_utc); } if (msg.whack_list & LIST_AACERTS) { - list_authcerts("AA", AUTH_AA, msg.whack_utc); + list_authcerts("AA", X509_AA, msg.whack_utc); } if (msg.whack_list & LIST_OCSPCERTS) { - list_authcerts("OCSP", AUTH_OCSP, msg.whack_utc); + list_authcerts("OCSP", X509_OCSP_SIGNER, msg.whack_utc); } if (msg.whack_list & LIST_ACERTS) @@ -510,11 +510,6 @@ whack_handle(int whackctlfd) list_acerts(msg.whack_utc); } - if (msg.whack_list & LIST_GROUPS) - { - list_groups(msg.whack_utc); - } - if (msg.whack_list & LIST_CAINFOS) { list_ca_infos(msg.whack_utc); diff --git a/src/pluto/x509.c b/src/pluto/x509.c index d0a57b39a..61d263948 100644 --- a/src/pluto/x509.c +++ b/src/pluto/x509.c @@ -126,8 +126,7 @@ const x509cert_t empty_x509cert = { NULL , /* *next */ UNDEFINED_TIME, /* installed */ 0 , /* count */ - FALSE , /* smartcard */ - AUTH_NONE , /* authority_flags */ + FALSE /* smartcard */ }; /* coding of X.501 distinguished name */ @@ -1038,7 +1037,7 @@ void store_x509certs(x509cert_t **firstcert, bool strict) if (trust_authcert_candidate(cert, cacerts)) { - add_authcert(cert, AUTH_CA); + add_authcert(cert, X509_CA); } else { @@ -1393,7 +1392,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until) lock_authcert_list("verify_x509cert"); issuer_cert = get_authcert(issuer->get_encoding(issuer), - authKeyID, AUTH_CA); + authKeyID, X509_CA); if (issuer_cert == NULL) { plog("issuer cacert not found"); @@ -1495,7 +1494,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until) * List all X.509 certs in a chained list */ void list_x509cert_chain(const char *caption, x509cert_t* cert, - u_char auth_flags, bool utc) + x509_flag_t flags, bool utc) { bool first = TRUE; time_t now; @@ -1505,14 +1504,15 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert, while (cert != NULL) { - if (auth_flags == AUTH_NONE || (auth_flags & cert->authority_flags)) + certificate_t *certificate = cert->cert; + x509_t *x509 = (x509_t*)certificate; + + if (flags == X509_NONE || (flags & x509->get_flags(x509))) { time_t notBefore, notAfter; public_key_t *key; chunk_t serial, keyid, subjkey, authkey; cert_t c; - certificate_t *certificate = cert->cert; - x509_t *x509 = (x509_t*)certificate; c.type = CERT_X509_SIGNATURE; c.u.x509 = cert; @@ -1579,5 +1579,5 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert, */ void list_x509_end_certs(bool utc) { - list_x509cert_chain("End", x509certs, AUTH_NONE, utc); + list_x509cert_chain("End", x509certs, X509_NONE, utc); } diff --git a/src/pluto/x509.h b/src/pluto/x509.h index 490ffc370..a61d6c06b 100644 --- a/src/pluto/x509.h +++ b/src/pluto/x509.h @@ -58,7 +58,6 @@ struct x509cert { time_t installed; int count; bool smartcard; - u_char authority_flags; }; /* used for initialization */ @@ -91,7 +90,7 @@ extern void release_x509cert(x509cert_t *cert); extern void free_x509cert(x509cert_t *cert); extern void store_x509certs(x509cert_t **firstcert, bool strict); extern void list_x509cert_chain(const char *caption, x509cert_t* cert, - u_char auth_flags, bool utc); + x509_flag_t flags, bool utc); extern void list_x509_end_certs(bool utc); extern void free_generalNames(generalName_t* gn, bool free_name); |