Annotation of embedaddon/strongswan/src/libstrongswan/plugins/x509/x509_ac.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2017 Tobias Brunner
        !             3:  * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
        !             4:  * Copyright (C) 2003 Martin Berner, Lukas Suter
        !             5:  * Copyright (C) 2002-2017 Andreas Steffen
        !             6:  * Copyright (C) 2009 Martin Willi
        !             7:  * HSR Hochschule fuer Technik Rapperswil
        !             8:  *
        !             9:  * This program is free software; you can redistribute it and/or modify it
        !            10:  * under the terms of the GNU General Public License as published by the
        !            11:  * Free Software Foundation; either version 2 of the License, or (at your
        !            12:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            13:  *
        !            14:  * This program is distributed in the hope that it will be useful, but
        !            15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            16:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            17:  * for more details.
        !            18:  */
        !            19: 
        !            20: #include "x509_ac.h"
        !            21: 
        !            22: #include <time.h>
        !            23: 
        !            24: #include <library.h>
        !            25: #include <utils/debug.h>
        !            26: #include <asn1/oid.h>
        !            27: #include <asn1/asn1.h>
        !            28: #include <asn1/asn1_parser.h>
        !            29: #include <utils/identification.h>
        !            30: #include <collections/linked_list.h>
        !            31: #include <credentials/certificates/x509.h>
        !            32: #include <credentials/keys/private_key.h>
        !            33: 
        !            34: extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob,
        !            35:                                                                        int level0, chunk_t *authKeySerialNumber);
        !            36: 
        !            37: typedef struct private_x509_ac_t private_x509_ac_t;
        !            38: 
        !            39: /**
        !            40:  * private data of x509_ac_t object
        !            41:  */
        !            42: struct private_x509_ac_t {
        !            43: 
        !            44:        /**
        !            45:         * public functions
        !            46:         */
        !            47:        x509_ac_t public;
        !            48: 
        !            49:        /**
        !            50:         * X.509 attribute certificate encoding in ASN.1 DER format
        !            51:         */
        !            52:        chunk_t encoding;
        !            53: 
        !            54:        /**
        !            55:         * X.509 attribute certificate body over which signature is computed
        !            56:         */
        !            57:        chunk_t certificateInfo;
        !            58: 
        !            59:        /**
        !            60:         * Version of the X.509 attribute certificate
        !            61:         */
        !            62:        u_int version;
        !            63: 
        !            64:        /**
        !            65:         * Serial number of the X.509 attribute certificate
        !            66:         */
        !            67:        chunk_t serialNumber;
        !            68: 
        !            69:        /**
        !            70:         * ID representing the issuer of the holder certificate
        !            71:         */
        !            72:        identification_t *holderIssuer;
        !            73: 
        !            74:        /**
        !            75:         * Serial number of the holder certificate
        !            76:         */
        !            77:        identification_t *holderSerial;
        !            78: 
        !            79:        /**
        !            80:         * ID representing the holder
        !            81:         */
        !            82:        identification_t *entityName;
        !            83: 
        !            84:        /**
        !            85:         * ID representing the attribute certificate issuer
        !            86:         */
        !            87:        identification_t *issuerName;
        !            88: 
        !            89:        /**
        !            90:         * Start time of certificate validity
        !            91:         */
        !            92:        time_t notBefore;
        !            93: 
        !            94:        /**
        !            95:         * End time of certificate validity
        !            96:         */
        !            97:        time_t notAfter;
        !            98: 
        !            99:        /**
        !           100:         * List of group attributes, as group_t
        !           101:         */
        !           102:        linked_list_t *groups;
        !           103: 
        !           104:        /**
        !           105:         * Authority Key Identifier
        !           106:         */
        !           107:        chunk_t authKeyIdentifier;
        !           108: 
        !           109:        /**
        !           110:         * Authority Key Serial Number
        !           111:         */
        !           112:        chunk_t authKeySerialNumber;
        !           113: 
        !           114:        /**
        !           115:         * No revocation information available
        !           116:         */
        !           117:        bool noRevAvail;
        !           118: 
        !           119:        /**
        !           120:         * Signature scheme
        !           121:         */
        !           122:        signature_params_t *scheme;
        !           123: 
        !           124:        /**
        !           125:         * Signature
        !           126:         */
        !           127:        chunk_t signature;
        !           128: 
        !           129:        /**
        !           130:         * Holder certificate
        !           131:         */
        !           132:        certificate_t *holderCert;
        !           133: 
        !           134:        /**
        !           135:         * Signer certificate
        !           136:         */
        !           137:        certificate_t *signerCert;
        !           138: 
        !           139:        /**
        !           140:        * Signer private key;
        !           141:        */
        !           142:        private_key_t *signerKey;
        !           143: 
        !           144:        /**
        !           145:         * reference count
        !           146:         */
        !           147:        refcount_t ref;
        !           148: };
        !           149: 
        !           150: /**
        !           151:  * Group definition, an IETF attribute
        !           152:  */
        !           153: typedef struct {
        !           154:        /** Attribute type */
        !           155:        ac_group_type_t type;
        !           156:        /* attribute value */
        !           157:        chunk_t value;
        !           158: } group_t;
        !           159: 
        !           160: /**
        !           161:  * Clean up a group entry
        !           162:  */
        !           163: static void group_destroy(group_t *group)
        !           164: {
        !           165:        free(group->value.ptr);
        !           166:        free(group);
        !           167: }
        !           168: 
        !           169: static chunk_t ASN1_noRevAvail_ext = chunk_from_chars(
        !           170:        0x30, 0x09,
        !           171:                  0x06, 0x03,
        !           172:                                0x55, 0x1d, 0x38,
        !           173:                  0x04, 0x02,
        !           174:                                0x05, 0x00
        !           175: );
        !           176: 
        !           177: /**
        !           178:  * declaration of function implemented in x509_cert.c
        !           179:  */
        !           180: extern bool x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
        !           181:                                                                        linked_list_t *list);
        !           182: /**
        !           183:  * parses a directoryName
        !           184:  */
        !           185: static bool parse_directoryName(chunk_t blob, int level, bool implicit,
        !           186:                                                                identification_t **name)
        !           187: {
        !           188:        identification_t *directoryName;
        !           189:        enumerator_t *enumerator;
        !           190:        bool first = TRUE;
        !           191:        linked_list_t *list;
        !           192: 
        !           193:        list = linked_list_create();
        !           194:        if (!x509_parse_generalNames(blob, level, implicit, list))
        !           195:        {
        !           196:                list->destroy(list);
        !           197:                return FALSE;
        !           198:        }
        !           199: 
        !           200:        enumerator = list->create_enumerator(list);
        !           201:        while (enumerator->enumerate(enumerator, &directoryName))
        !           202:        {
        !           203:                if (first)
        !           204:                {
        !           205:                        *name = directoryName;
        !           206:                        first = FALSE;
        !           207:                }
        !           208:                else
        !           209:                {
        !           210:                        DBG1(DBG_ASN, "more than one directory name - first selected");
        !           211:                        directoryName->destroy(directoryName);
        !           212:                        break;
        !           213:                }
        !           214:        }
        !           215:        enumerator->destroy(enumerator);
        !           216:        list->destroy(list);
        !           217: 
        !           218:        if (first)
        !           219:        {
        !           220:                DBG1(DBG_ASN, "no directoryName found");
        !           221:                return FALSE;
        !           222:        }
        !           223:        return TRUE;
        !           224: }
        !           225: 
        !           226: /**
        !           227:  * ASN.1 definition of roleSyntax
        !           228:  */
        !           229: static const asn1Object_t roleSyntaxObjects[] =
        !           230: {
        !           231:        { 0, "roleSyntax",              ASN1_SEQUENCE,          ASN1_NONE }, /* 0 */
        !           232:        { 1,   "roleAuthority", ASN1_CONTEXT_C_0,       ASN1_OPT |
        !           233:                                                                                                ASN1_OBJ  }, /* 1 */
        !           234:        { 1,   "end opt",               ASN1_EOC,                       ASN1_END  }, /* 2 */
        !           235:        { 1,   "roleName",              ASN1_CONTEXT_C_1,       ASN1_OBJ  }, /* 3 */
        !           236:        { 0, "exit",                    ASN1_EOC,                       ASN1_EXIT }
        !           237: };
        !           238: 
        !           239: /**
        !           240:  * Parses roleSyntax
        !           241:  */
        !           242: static void parse_roleSyntax(chunk_t blob, int level0)
        !           243: {
        !           244:        asn1_parser_t *parser;
        !           245:        chunk_t object;
        !           246:        int objectID;
        !           247: 
        !           248:        parser = asn1_parser_create(roleSyntaxObjects, blob);
        !           249:        parser->set_top_level(parser, level0);
        !           250: 
        !           251:        while (parser->iterate(parser, &objectID, &object))
        !           252:        {
        !           253:                switch (objectID)
        !           254:                {
        !           255:                        default:
        !           256:                                break;
        !           257:                }
        !           258:        }
        !           259:        parser->destroy(parser);
        !           260: }
        !           261: 
        !           262: /**
        !           263:  * ASN.1 definition of ietfAttrSyntax
        !           264:  */
        !           265: static const asn1Object_t ietfAttrSyntaxObjects[] =
        !           266: {
        !           267:        { 0, "ietfAttrSyntax",          ASN1_SEQUENCE,          ASN1_NONE }, /*  0 */
        !           268:        { 1,   "policyAuthority",       ASN1_CONTEXT_C_0,       ASN1_OPT |
        !           269:                                                                                                        ASN1_BODY }, /*  1 */
        !           270:        { 1,   "end opt",                       ASN1_EOC,                       ASN1_END  }, /*  2 */
        !           271:        { 1,   "values",                        ASN1_SEQUENCE,          ASN1_LOOP }, /*  3 */
        !           272:        { 2,     "octets",                      ASN1_OCTET_STRING,      ASN1_OPT |
        !           273:                                                                                                        ASN1_BODY }, /*  4 */
        !           274:        { 2,     "end choice",          ASN1_EOC,                       ASN1_END  }, /*  5 */
        !           275:        { 2,     "oid",                         ASN1_OID,                       ASN1_OPT |
        !           276:                                                                                                        ASN1_BODY }, /*  6 */
        !           277:        { 2,     "end choice",          ASN1_EOC,                       ASN1_END  }, /*  7 */
        !           278:        { 2,     "string",                      ASN1_UTF8STRING,        ASN1_OPT |
        !           279:                                                                                                        ASN1_BODY }, /*  8 */
        !           280:        { 2,     "end choice",          ASN1_EOC,                       ASN1_END  }, /*  9 */
        !           281:        { 1,   "end loop",                      ASN1_EOC,                       ASN1_END  }, /* 10 */
        !           282:        { 0, "exit",                            ASN1_EOC,                       ASN1_EXIT }
        !           283: };
        !           284: #define IETF_ATTR_OCTETS        4
        !           285: #define IETF_ATTR_OID           6
        !           286: #define IETF_ATTR_STRING        8
        !           287: 
        !           288: /**
        !           289:  * Parse group memberships, IETF attributes
        !           290:  */
        !           291: static bool parse_groups(private_x509_ac_t *this, chunk_t encoded, int level0)
        !           292: {
        !           293:        ac_group_type_t type;
        !           294:        group_t *group;
        !           295:        asn1_parser_t *parser;
        !           296:        chunk_t object;
        !           297:        int objectID;
        !           298:        bool success;
        !           299: 
        !           300:        parser = asn1_parser_create(ietfAttrSyntaxObjects, encoded);
        !           301:        parser->set_top_level(parser, level0);
        !           302:        while (parser->iterate(parser, &objectID, &object))
        !           303:        {
        !           304:                switch (objectID)
        !           305:                {
        !           306:                        case IETF_ATTR_OCTETS:
        !           307:                                type = AC_GROUP_TYPE_OCTETS;
        !           308:                                break;
        !           309:                        case IETF_ATTR_OID:
        !           310:                                type = AC_GROUP_TYPE_OID;
        !           311:                                break;
        !           312:                        case IETF_ATTR_STRING:
        !           313:                                type = AC_GROUP_TYPE_STRING;
        !           314:                                break;
        !           315:                        default:
        !           316:                                continue;
        !           317:                }
        !           318:                INIT(group,
        !           319:                        .type = type,
        !           320:                        .value = chunk_clone(object),
        !           321:                );
        !           322:                this->groups->insert_last(this->groups, group);
        !           323:        }
        !           324:        success = parser->success(parser);
        !           325:        parser->destroy(parser);
        !           326: 
        !           327:        return success;
        !           328: }
        !           329: 
        !           330: /**
        !           331:  * ASN.1 definition of an X509 attribute certificate
        !           332:  */
        !           333: static const asn1Object_t acObjects[] =
        !           334: {
        !           335:        { 0, "AttributeCertificate",                    ASN1_SEQUENCE,            ASN1_OBJ  }, /*  0 */
        !           336:        { 1,   "AttributeCertificateInfo",              ASN1_SEQUENCE,            ASN1_OBJ  }, /*  1 */
        !           337:        { 2,       "version",                                   ASN1_INTEGER,             ASN1_DEF |
        !           338:                                                                                                                                  ASN1_BODY }, /*  2 */
        !           339:        { 2,       "holder",                                    ASN1_SEQUENCE,            ASN1_NONE }, /*  3 */
        !           340:        { 3,         "baseCertificateID",               ASN1_CONTEXT_C_0,         ASN1_OPT  }, /*  4 */
        !           341:        { 4,           "issuer",                                ASN1_SEQUENCE,            ASN1_OBJ  }, /*  5 */
        !           342:        { 4,           "serial",                                ASN1_INTEGER,             ASN1_BODY }, /*  6 */
        !           343:        { 4,         "issuerUID",                               ASN1_BIT_STRING,          ASN1_OPT |
        !           344:                                                                                                                                  ASN1_BODY }, /*  7 */
        !           345:        { 4,         "end opt",                                 ASN1_EOC,                         ASN1_END  }, /*  8 */
        !           346:        { 3,       "end opt",                                   ASN1_EOC,                         ASN1_END  }, /*  9 */
        !           347:        { 3,       "entityName",                                ASN1_CONTEXT_C_1,         ASN1_OPT |
        !           348:                                                                                                                                  ASN1_OBJ  }, /* 10 */
        !           349:        { 3,       "end opt",                                   ASN1_EOC,                         ASN1_END  }, /* 11 */
        !           350:        { 3,         "objectDigestInfo",                ASN1_CONTEXT_C_2,         ASN1_OPT  }, /* 12 */
        !           351:        { 4,           "digestedObjectType",    ASN1_ENUMERATED,          ASN1_BODY }, /* 13 */
        !           352:        { 4,           "otherObjectTypeID",             ASN1_OID,                         ASN1_OPT |
        !           353:                                                                                                                                  ASN1_BODY }, /* 14 */
        !           354:        { 4,         "end opt",                                 ASN1_EOC,                         ASN1_END  }, /* 15 */
        !           355:        { 4,         "digestAlgorithm",                 ASN1_EOC,                         ASN1_RAW  }, /* 16 */
        !           356:        { 3,       "end opt",                                   ASN1_EOC,                         ASN1_END  }, /* 17 */
        !           357:        { 2,       "v2Form",                                    ASN1_CONTEXT_C_0,         ASN1_NONE }, /* 18 */
        !           358:        { 3,         "issuerName",                              ASN1_SEQUENCE,            ASN1_OPT |
        !           359:                                                                                                                                  ASN1_OBJ  }, /* 19 */
        !           360:        { 3,       "end opt",                                   ASN1_EOC,                         ASN1_END  }, /* 20 */
        !           361:        { 3,         "baseCertificateID",               ASN1_CONTEXT_C_0,         ASN1_OPT  }, /* 21 */
        !           362:        { 4,           "issuerSerial",                  ASN1_SEQUENCE,            ASN1_NONE }, /* 22 */
        !           363:        { 5,             "issuer",                              ASN1_SEQUENCE,            ASN1_OBJ  }, /* 23 */
        !           364:        { 5,         "serial",                                  ASN1_INTEGER,             ASN1_BODY }, /* 24 */
        !           365:        { 5,           "issuerUID",                             ASN1_BIT_STRING,          ASN1_OPT |
        !           366:                                                                                                                                  ASN1_BODY }, /* 25 */
        !           367:        { 5,           "end opt",                               ASN1_EOC,                         ASN1_END  }, /* 26 */
        !           368:        { 3,       "end opt",                                   ASN1_EOC,                         ASN1_END  }, /* 27 */
        !           369:        { 3,       "objectDigestInfo",                  ASN1_CONTEXT_C_1,         ASN1_OPT  }, /* 28 */
        !           370:        { 4,           "digestInfo",                    ASN1_SEQUENCE,            ASN1_OBJ  }, /* 29 */
        !           371:        { 5,     "digestedObjectType",                  ASN1_ENUMERATED,          ASN1_BODY }, /* 30 */
        !           372:        { 5,         "otherObjectTypeID",               ASN1_OID,                         ASN1_OPT |
        !           373:                                                                                                                                  ASN1_BODY }, /* 31 */
        !           374:        { 5,           "end opt",                               ASN1_EOC,                         ASN1_END  }, /* 32 */
        !           375:        { 5,           "digestAlgorithm",               ASN1_EOC,                         ASN1_RAW  }, /* 33 */
        !           376:        { 3,       "end opt",                                   ASN1_EOC,                         ASN1_END  }, /* 34 */
        !           377:        { 2,       "signature",                                 ASN1_EOC,                         ASN1_RAW  }, /* 35 */
        !           378:        { 2,       "serialNumber",                              ASN1_INTEGER,             ASN1_BODY }, /* 36 */
        !           379:        { 2,       "attrCertValidityPeriod",    ASN1_SEQUENCE,            ASN1_NONE }, /* 37 */
        !           380:        { 3,         "notBeforeTime",                   ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
        !           381:        { 3,         "notAfterTime",                    ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
        !           382:        { 2,       "attributes",                                ASN1_SEQUENCE,            ASN1_LOOP }, /* 40 */
        !           383:        { 3,       "attribute",                                 ASN1_SEQUENCE,            ASN1_NONE }, /* 41 */
        !           384:        { 4,         "type",                                    ASN1_OID,                         ASN1_BODY }, /* 42 */
        !           385:        { 4,         "values",                                  ASN1_SET,                         ASN1_LOOP }, /* 43 */
        !           386:        { 5,           "value",                                 ASN1_EOC,                         ASN1_RAW  }, /* 44 */
        !           387:        { 4,           "end loop",                              ASN1_EOC,                         ASN1_END  }, /* 45 */
        !           388:        { 2,     "end loop",                                    ASN1_EOC,                         ASN1_END  }, /* 46 */
        !           389:        { 2,     "extensions",                                  ASN1_SEQUENCE,            ASN1_LOOP }, /* 47 */
        !           390:        { 3,       "extension",                                 ASN1_SEQUENCE,            ASN1_NONE }, /* 48 */
        !           391:        { 4,         "extnID",                                  ASN1_OID,                         ASN1_BODY }, /* 49 */
        !           392:        { 4,         "critical",                                ASN1_BOOLEAN,             ASN1_DEF |
        !           393:                                                                                                                                  ASN1_BODY }, /* 50 */
        !           394:        { 4,         "extnValue",                               ASN1_OCTET_STRING,        ASN1_BODY }, /* 51 */
        !           395:        { 2,     "end loop",                                    ASN1_EOC,                         ASN1_END  }, /* 52 */
        !           396:        { 1,   "signatureAlgorithm",                    ASN1_EOC,                         ASN1_RAW  }, /* 53 */
        !           397:        { 1,   "signatureValue",                                ASN1_BIT_STRING,          ASN1_BODY }, /* 54 */
        !           398:        { 0, "exit",                                                    ASN1_EOC,                         ASN1_EXIT }
        !           399: };
        !           400: #define AC_OBJ_CERTIFICATE_INFO                 1
        !           401: #define AC_OBJ_VERSION                          2
        !           402: #define AC_OBJ_HOLDER_ISSUER            5
        !           403: #define AC_OBJ_HOLDER_SERIAL            6
        !           404: #define AC_OBJ_ENTITY_NAME                     10
        !           405: #define AC_OBJ_ISSUER_NAME                     19
        !           406: #define AC_OBJ_ISSUER                          23
        !           407: #define AC_OBJ_SIG_ALG                         35
        !           408: #define AC_OBJ_SERIAL_NUMBER           36
        !           409: #define AC_OBJ_NOT_BEFORE                      38
        !           410: #define AC_OBJ_NOT_AFTER                       39
        !           411: #define AC_OBJ_ATTRIBUTE_TYPE          42
        !           412: #define AC_OBJ_ATTRIBUTE_VALUE         44
        !           413: #define AC_OBJ_EXTN_ID                         49
        !           414: #define AC_OBJ_CRITICAL                                50
        !           415: #define AC_OBJ_EXTN_VALUE                      51
        !           416: #define AC_OBJ_ALGORITHM                       53
        !           417: #define AC_OBJ_SIGNATURE                       54
        !           418: 
        !           419: /**
        !           420:  * Parses an X.509 attribute certificate
        !           421:  */
        !           422: static bool parse_certificate(private_x509_ac_t *this)
        !           423: {
        !           424:        asn1_parser_t *parser;
        !           425:        chunk_t object;
        !           426:        int objectID;
        !           427:        int type     = OID_UNKNOWN;
        !           428:        int extn_oid = OID_UNKNOWN;
        !           429:        signature_params_t sig_alg = {};
        !           430:        bool success = FALSE;
        !           431:        bool critical;
        !           432: 
        !           433:        parser = asn1_parser_create(acObjects, this->encoding);
        !           434: 
        !           435:        while (parser->iterate(parser, &objectID, &object))
        !           436:        {
        !           437:                u_int level = parser->get_level(parser)+1;
        !           438: 
        !           439:                switch (objectID)
        !           440:                {
        !           441:                        case AC_OBJ_CERTIFICATE_INFO:
        !           442:                                this->certificateInfo = object;
        !           443:                                break;
        !           444:                        case AC_OBJ_VERSION:
        !           445:                                this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
        !           446:                                DBG2(DBG_ASN, "  v%d", this->version);
        !           447:                                if (this->version != 2)
        !           448:                                {
        !           449:                                        DBG1(DBG_ASN, "v%d attribute certificates are not "
        !           450:                                                 "supported", this->version);
        !           451:                                        goto end;
        !           452:                                }
        !           453:                                break;
        !           454:                        case AC_OBJ_HOLDER_ISSUER:
        !           455:                                if (!parse_directoryName(object, level, FALSE,
        !           456:                                                                                 &this->holderIssuer))
        !           457:                                {
        !           458:                                        goto end;
        !           459:                                }
        !           460:                                break;
        !           461:                        case AC_OBJ_HOLDER_SERIAL:
        !           462:                                this->holderSerial = identification_create_from_encoding(
        !           463:                                                                                                                        ID_KEY_ID, object);
        !           464:                                break;
        !           465:                        case AC_OBJ_ENTITY_NAME:
        !           466:                                if (!parse_directoryName(object, level, TRUE,
        !           467:                                                                                 &this->entityName))
        !           468:                                {
        !           469:                                        goto end;
        !           470:                                }
        !           471:                                break;
        !           472:                        case AC_OBJ_ISSUER_NAME:
        !           473:                                if (!parse_directoryName(object, level, FALSE,
        !           474:                                                                                 &this->issuerName))
        !           475:                                {
        !           476:                                        goto end;
        !           477:                                }
        !           478:                                break;
        !           479:                        case AC_OBJ_SIG_ALG:
        !           480:                                if (!signature_params_parse(object, level, &sig_alg))
        !           481:                                {
        !           482:                                        DBG1(DBG_ASN, "  unable to parse signature algorithm");
        !           483:                                        goto end;
        !           484:                                }
        !           485:                                break;
        !           486:                        case AC_OBJ_SERIAL_NUMBER:
        !           487:                                this->serialNumber = chunk_clone(object);
        !           488:                                break;
        !           489:                        case AC_OBJ_NOT_BEFORE:
        !           490:                                this->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
        !           491:                                break;
        !           492:                        case AC_OBJ_NOT_AFTER:
        !           493:                                this->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
        !           494:                                break;
        !           495:                        case AC_OBJ_ATTRIBUTE_TYPE:
        !           496:                                type = asn1_known_oid(object);
        !           497:                                break;
        !           498:                        case AC_OBJ_ATTRIBUTE_VALUE:
        !           499:                        {
        !           500:                                switch (type)
        !           501:                                {
        !           502:                                        case OID_AUTHENTICATION_INFO:
        !           503:                                                DBG2(DBG_ASN, "  need to parse authenticationInfo");
        !           504:                                                break;
        !           505:                                        case OID_ACCESS_IDENTITY:
        !           506:                                                DBG2(DBG_ASN, "  need to parse accessIdentity");
        !           507:                                                break;
        !           508:                                        case OID_CHARGING_IDENTITY:
        !           509:                                                DBG2(DBG_ASN, "  need to parse chargingIdentity");
        !           510:                                                break;
        !           511:                                        case OID_GROUP:
        !           512:                                                DBG2(DBG_ASN, "-- > --");
        !           513:                                                if (!parse_groups(this, object, level))
        !           514:                                                {
        !           515:                                                        goto end;
        !           516:                                                }
        !           517:                                                DBG2(DBG_ASN, "-- < --");
        !           518:                                                break;
        !           519:                                        case OID_ROLE:
        !           520:                                                parse_roleSyntax(object, level);
        !           521:                                                break;
        !           522:                                        default:
        !           523:                                                break;
        !           524:                                }
        !           525:                                break;
        !           526:                        }
        !           527:                        case AC_OBJ_EXTN_ID:
        !           528:                                extn_oid = asn1_known_oid(object);
        !           529:                                break;
        !           530:                        case AC_OBJ_CRITICAL:
        !           531:                                critical = object.len && *object.ptr;
        !           532:                                DBG2(DBG_ASN, "  %s",(critical)?"TRUE":"FALSE");
        !           533:                                break;
        !           534:                        case AC_OBJ_EXTN_VALUE:
        !           535:                        {
        !           536:                                switch (extn_oid)
        !           537:                                {
        !           538:                                        case OID_CRL_DISTRIBUTION_POINTS:
        !           539:                                                DBG2(DBG_ASN, "  need to parse crlDistributionPoints");
        !           540:                                                break;
        !           541:                                        case OID_AUTHORITY_KEY_ID:
        !           542:                                                this->authKeyIdentifier =
        !           543:                                                                x509_parse_authorityKeyIdentifier(object,
        !           544:                                                                                        level, &this->authKeySerialNumber);
        !           545:                                                break;
        !           546:                                        case OID_TARGET_INFORMATION:
        !           547:                                                DBG2(DBG_ASN, "  need to parse targetInformation");
        !           548:                                                break;
        !           549:                                        case OID_NO_REV_AVAIL:
        !           550:                                                this->noRevAvail = TRUE;
        !           551:                                                break;
        !           552:                                        default:
        !           553:                                                break;
        !           554:                                }
        !           555:                                break;
        !           556:                        }
        !           557:                        case AC_OBJ_ALGORITHM:
        !           558:                                INIT(this->scheme);
        !           559:                                if (!signature_params_parse(object, level, this->scheme))
        !           560:                                {
        !           561:                                        DBG1(DBG_ASN, "  unable to parse signature algorithm");
        !           562:                                        goto end;
        !           563:                                }
        !           564:                                if (!signature_params_equal(this->scheme, &sig_alg))
        !           565:                                {
        !           566:                                        DBG1(DBG_ASN, "  signature algorithms do not agree");
        !           567:                                        goto end;
        !           568:                                }
        !           569:                                break;
        !           570:                        case AC_OBJ_SIGNATURE:
        !           571:                                this->signature = chunk_skip(object, 1);
        !           572:                                break;
        !           573:                        default:
        !           574:                                break;
        !           575:                }
        !           576:        }
        !           577:        success = parser->success(parser);
        !           578: 
        !           579: end:
        !           580:        parser->destroy(parser);
        !           581:        signature_params_clear(&sig_alg);
        !           582:        return success;
        !           583: }
        !           584: 
        !           585: /**
        !           586:  * build directoryName
        !           587:  */
        !           588: static chunk_t build_directoryName(asn1_t tag, chunk_t name)
        !           589: {
        !           590:        return asn1_wrap(tag, "m",
        !           591:                                asn1_simple_object(ASN1_CONTEXT_C_4, name));
        !           592: }
        !           593: 
        !           594: /**
        !           595:  * build holder
        !           596:  */
        !           597: static chunk_t build_holder(private_x509_ac_t *this)
        !           598: {
        !           599:        x509_t* x509 = (x509_t*)this->holderCert;
        !           600:        identification_t *issuer, *subject;
        !           601: 
        !           602:        issuer = this->holderCert->get_issuer(this->holderCert);
        !           603:        subject = this->holderCert->get_subject(this->holderCert);
        !           604: 
        !           605:        return asn1_wrap(ASN1_SEQUENCE, "mm",
        !           606:                asn1_wrap(ASN1_CONTEXT_C_0, "mm",
        !           607:                        build_directoryName(ASN1_SEQUENCE, issuer->get_encoding(issuer)),
        !           608:                        asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509))),
        !           609:                build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject)));
        !           610: }
        !           611: 
        !           612: /**
        !           613:  * build v2Form
        !           614:  */
        !           615: static chunk_t build_v2_form(private_x509_ac_t *this)
        !           616: {
        !           617:        identification_t *subject;
        !           618: 
        !           619:        subject = this->signerCert->get_subject(this->signerCert);
        !           620:        return asn1_wrap(ASN1_CONTEXT_C_0, "m",
        !           621:                                build_directoryName(ASN1_SEQUENCE,
        !           622:                                        subject->get_encoding(subject)));
        !           623: }
        !           624: 
        !           625: /**
        !           626:  * build attrCertValidityPeriod
        !           627:  */
        !           628: static chunk_t build_attr_cert_validity(private_x509_ac_t *this)
        !           629: {
        !           630:        return asn1_wrap(ASN1_SEQUENCE, "mm",
        !           631:                                asn1_from_time(&this->notBefore, ASN1_GENERALIZEDTIME),
        !           632:                                asn1_from_time(&this->notAfter, ASN1_GENERALIZEDTIME));
        !           633: }
        !           634: 
        !           635: /**
        !           636:  * build attribute type
        !           637:  */
        !           638: static chunk_t build_attribute_type(int type, chunk_t content)
        !           639: {
        !           640:        return asn1_wrap(ASN1_SEQUENCE, "mm",
        !           641:                                asn1_build_known_oid(type),
        !           642:                                asn1_wrap(ASN1_SET, "m", content));
        !           643: }
        !           644: 
        !           645: /**
        !           646:  * build attributes
        !           647:  */
        !           648: static chunk_t build_attributes(private_x509_ac_t *this)
        !           649: {
        !           650:        enumerator_t *enumerator;
        !           651:        group_t *group;
        !           652:        chunk_t values;
        !           653:        size_t size = 0, len;
        !           654:        u_char *pos;
        !           655: 
        !           656:        /* precalculate the total size of all values */
        !           657:        enumerator = this->groups->create_enumerator(this->groups);
        !           658:        while (enumerator->enumerate(enumerator, &group))
        !           659:        {
        !           660:                len = group->value.len;
        !           661:                size += 1 + (len > 0) + (len >= 128) +
        !           662:                                (len >= 256) + (len >= 65536) + len;
        !           663:        }
        !           664:        enumerator->destroy(enumerator);
        !           665: 
        !           666:        pos = asn1_build_object(&values, ASN1_SEQUENCE, size);
        !           667: 
        !           668:        enumerator = this->groups->create_enumerator(this->groups);
        !           669:        while (enumerator->enumerate(enumerator, &group))
        !           670:        {
        !           671:                chunk_t attr;
        !           672:                asn1_t type;
        !           673: 
        !           674:                switch (group->type)
        !           675:                {
        !           676:                        case AC_GROUP_TYPE_OCTETS:
        !           677:                                type = ASN1_OCTET_STRING;
        !           678:                                break;
        !           679:                        case AC_GROUP_TYPE_STRING:
        !           680:                                type = ASN1_UTF8STRING;
        !           681:                                break;
        !           682:                        case AC_GROUP_TYPE_OID:
        !           683:                                type = ASN1_OID;
        !           684:                                break;
        !           685:                        default:
        !           686:                                continue;
        !           687:                }
        !           688:                attr = asn1_simple_object(type, group->value);
        !           689: 
        !           690:                memcpy(pos, attr.ptr, attr.len);
        !           691:                pos += attr.len;
        !           692:                free(attr.ptr);
        !           693:        }
        !           694:        enumerator->destroy(enumerator);
        !           695: 
        !           696:        return asn1_wrap(ASN1_SEQUENCE, "m",
        !           697:                                build_attribute_type(OID_GROUP,
        !           698:                                        asn1_wrap(ASN1_SEQUENCE, "m", values)));
        !           699: }
        !           700: 
        !           701: /**
        !           702:  * build authorityKeyIdentifier
        !           703:  */
        !           704: static chunk_t build_authorityKeyIdentifier(private_x509_ac_t *this)
        !           705: {
        !           706:        chunk_t keyIdentifier = chunk_empty;
        !           707:        chunk_t authorityCertIssuer;
        !           708:        chunk_t authorityCertSerialNumber;
        !           709:        identification_t *issuer;
        !           710:        public_key_t *public;
        !           711:        x509_t *x509;
        !           712: 
        !           713:        x509 = (x509_t*)this->signerCert;
        !           714:        issuer = this->signerCert->get_issuer(this->signerCert);
        !           715:        public = this->signerCert->get_public_key(this->signerCert);
        !           716:        if (public)
        !           717:        {
        !           718:                if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyIdentifier))
        !           719:                {
        !           720:                        this->authKeyIdentifier = chunk_clone(keyIdentifier);
        !           721:                        keyIdentifier = asn1_simple_object(ASN1_CONTEXT_S_0, keyIdentifier);
        !           722:                }
        !           723:                public->destroy(public);
        !           724:        }
        !           725:        authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1,
        !           726:                                                                                        issuer->get_encoding(issuer));
        !           727:        authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2,
        !           728:                                                                                        x509->get_serial(x509));
        !           729:        return asn1_wrap(ASN1_SEQUENCE, "mm",
        !           730:                                asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
        !           731:                                asn1_wrap(ASN1_OCTET_STRING, "m",
        !           732:                                        asn1_wrap(ASN1_SEQUENCE, "mmm",
        !           733:                                                keyIdentifier,
        !           734:                                                authorityCertIssuer,
        !           735:                                                authorityCertSerialNumber
        !           736:                                        )
        !           737:                                )
        !           738:                   );
        !           739: }
        !           740: 
        !           741: /**
        !           742:  * build extensions
        !           743:  */
        !           744: static chunk_t build_extensions(private_x509_ac_t *this)
        !           745: {
        !           746:        return asn1_wrap(ASN1_SEQUENCE, "mc",
        !           747:                                build_authorityKeyIdentifier(this),
        !           748:                                ASN1_noRevAvail_ext);
        !           749: }
        !           750: 
        !           751: /**
        !           752:  * build attributeCertificateInfo
        !           753:  */
        !           754: static chunk_t build_attr_cert_info(private_x509_ac_t *this, chunk_t sig_scheme)
        !           755: {
        !           756:        return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm",
        !           757:                                ASN1_INTEGER_1,
        !           758:                                build_holder(this),
        !           759:                                build_v2_form(this),
        !           760:                                sig_scheme,
        !           761:                                asn1_simple_object(ASN1_INTEGER, this->serialNumber),
        !           762:                                build_attr_cert_validity(this),
        !           763:                                build_attributes(this),
        !           764:                                build_extensions(this));
        !           765: }
        !           766: 
        !           767: /**
        !           768:  * build an X.509 attribute certificate
        !           769:  */
        !           770: static bool build_ac(private_x509_ac_t *this, hash_algorithm_t digest_alg)
        !           771: {
        !           772:        chunk_t signatureValue, attributeCertificateInfo, sig_scheme;
        !           773:        private_key_t *key = this->signerKey;
        !           774: 
        !           775:        if (!this->scheme)
        !           776:        {
        !           777:                INIT(this->scheme,
        !           778:                        .scheme = signature_scheme_from_oid(
        !           779:                                                                hasher_signature_algorithm_to_oid(digest_alg,
        !           780:                                                                                                key->get_type(key))),
        !           781:                );
        !           782:        }
        !           783:        if (this->scheme->scheme == SIGN_UNKNOWN)
        !           784:        {
        !           785:                return FALSE;
        !           786:        }
        !           787:        if (!signature_params_build(this->scheme, &sig_scheme))
        !           788:        {
        !           789:                return FALSE;
        !           790:        }
        !           791: 
        !           792:        attributeCertificateInfo = build_attr_cert_info(this, sig_scheme);
        !           793:        if (!key->sign(key, this->scheme->scheme, this->scheme->params,
        !           794:                                   attributeCertificateInfo, &signatureValue))
        !           795:        {
        !           796:                free(attributeCertificateInfo.ptr);
        !           797:                free(sig_scheme.ptr);
        !           798:                return FALSE;
        !           799:        }
        !           800:        this->encoding = asn1_wrap(ASN1_SEQUENCE, "mmm",
        !           801:                                                attributeCertificateInfo,
        !           802:                                                sig_scheme,
        !           803:                                                asn1_bitstring("m", signatureValue));
        !           804:        return TRUE;
        !           805: }
        !           806: 
        !           807: METHOD(ac_t, get_serial, chunk_t,
        !           808:        private_x509_ac_t *this)
        !           809: {
        !           810:        return this->serialNumber;
        !           811: }
        !           812: 
        !           813: METHOD(ac_t, get_holderSerial, chunk_t,
        !           814:        private_x509_ac_t *this)
        !           815: {
        !           816:        if (this->holderSerial)
        !           817:        {
        !           818:                return this->holderSerial->get_encoding(this->holderSerial);
        !           819:        }
        !           820:        return chunk_empty;
        !           821: }
        !           822: 
        !           823: METHOD(ac_t, get_holderIssuer, identification_t*,
        !           824:        private_x509_ac_t *this)
        !           825: {
        !           826:        return this->holderIssuer;
        !           827: }
        !           828: 
        !           829: METHOD(ac_t, get_authKeyIdentifier, chunk_t,
        !           830:        private_x509_ac_t *this)
        !           831: {
        !           832:        return this->authKeyIdentifier;
        !           833: }
        !           834: 
        !           835: CALLBACK(attr_filter, bool,
        !           836:        void *null, enumerator_t *orig, va_list args)
        !           837: {
        !           838:        group_t *group;
        !           839:        ac_group_type_t *type;
        !           840:        chunk_t *out;
        !           841: 
        !           842:        VA_ARGS_VGET(args, type, out);
        !           843: 
        !           844:        while (orig->enumerate(orig, &group))
        !           845:        {
        !           846:                if (group->type == AC_GROUP_TYPE_STRING &&
        !           847:                        !chunk_printable(group->value, NULL, 0))
        !           848:                {       /* skip non-printable strings */
        !           849:                        continue;
        !           850:                }
        !           851:                *type = group->type;
        !           852:                *out = group->value;
        !           853:                return TRUE;
        !           854:        }
        !           855:        return FALSE;
        !           856: }
        !           857: 
        !           858: METHOD(ac_t, create_group_enumerator, enumerator_t*,
        !           859:        private_x509_ac_t *this)
        !           860: {
        !           861:        return enumerator_create_filter(
        !           862:                                                        this->groups->create_enumerator(this->groups),
        !           863:                                                        attr_filter, NULL, NULL);
        !           864: }
        !           865: 
        !           866: METHOD(certificate_t, get_type, certificate_type_t,
        !           867:        private_x509_ac_t *this)
        !           868: {
        !           869:        return CERT_X509_AC;
        !           870: }
        !           871: 
        !           872: METHOD(certificate_t, get_subject, identification_t*,
        !           873:        private_x509_ac_t *this)
        !           874: {
        !           875:        if (this->entityName)
        !           876:        {
        !           877:                return this->entityName;
        !           878:        }
        !           879:        return this->holderSerial;
        !           880: }
        !           881: 
        !           882: METHOD(certificate_t, get_issuer, identification_t*,
        !           883:        private_x509_ac_t *this)
        !           884: {
        !           885:        return this->issuerName;
        !           886: }
        !           887: 
        !           888: METHOD(certificate_t, has_subject, id_match_t,
        !           889:        private_x509_ac_t *this, identification_t *subject)
        !           890: {
        !           891:        id_match_t entity = ID_MATCH_NONE, serial = ID_MATCH_NONE;
        !           892: 
        !           893:        if (this->entityName)
        !           894:        {
        !           895:                entity = this->entityName->matches(this->entityName, subject);
        !           896:        }
        !           897:        if (this->holderSerial)
        !           898:        {
        !           899:                serial = this->holderSerial->matches(this->holderSerial, subject);
        !           900:        }
        !           901:        return max(entity, serial);
        !           902: }
        !           903: 
        !           904: METHOD(certificate_t, has_issuer, id_match_t,
        !           905:        private_x509_ac_t *this, identification_t *issuer)
        !           906: {
        !           907:        if (issuer->get_type(issuer) == ID_KEY_ID &&
        !           908:                this->authKeyIdentifier.ptr &&
        !           909:                chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
        !           910:        {
        !           911:                return ID_MATCH_PERFECT;
        !           912:        }
        !           913:        return this->issuerName->matches(this->issuerName, issuer);
        !           914: }
        !           915: 
        !           916: METHOD(certificate_t, issued_by, bool,
        !           917:        private_x509_ac_t *this, certificate_t *issuer,
        !           918:        signature_params_t **scheme)
        !           919: {
        !           920:        public_key_t *key;
        !           921:        bool valid;
        !           922:        x509_t *x509 = (x509_t*)issuer;
        !           923: 
        !           924:        /* check if issuer is an X.509 AA certificate */
        !           925:        if (issuer->get_type(issuer) != CERT_X509)
        !           926:        {
        !           927:                return FALSE;
        !           928:        }
        !           929:        if (!(x509->get_flags(x509) & X509_AA))
        !           930:        {
        !           931:                return FALSE;
        !           932:        }
        !           933: 
        !           934:        /* get the public key of the issuer */
        !           935:        key = issuer->get_public_key(issuer);
        !           936: 
        !           937:        /* compare keyIdentifiers if available, otherwise use DNs */
        !           938:        if (this->authKeyIdentifier.ptr && key)
        !           939:        {
        !           940:                chunk_t fingerprint;
        !           941: 
        !           942:                if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
        !           943:                        !chunk_equals(fingerprint, this->authKeyIdentifier))
        !           944:                {
        !           945:                        return FALSE;
        !           946:                }
        !           947:        }
        !           948:        else
        !           949:        {
        !           950:                if (!this->issuerName->equals(this->issuerName,
        !           951:                                                                          issuer->get_subject(issuer)))
        !           952:                {
        !           953:                        return FALSE;
        !           954:                }
        !           955:        }
        !           956: 
        !           957:        if (!key)
        !           958:        {
        !           959:                return FALSE;
        !           960:        }
        !           961:        valid = key->verify(key, this->scheme->scheme, this->scheme->params,
        !           962:                                                this->certificateInfo, this->signature);
        !           963:        key->destroy(key);
        !           964:        if (valid && scheme)
        !           965:        {
        !           966:                *scheme = signature_params_clone(this->scheme);
        !           967:        }
        !           968:        return valid;
        !           969: }
        !           970: 
        !           971: METHOD(certificate_t, get_public_key, public_key_t*,
        !           972:        private_x509_ac_t *this)
        !           973: {
        !           974:        return NULL;
        !           975: }
        !           976: 
        !           977: METHOD(certificate_t, get_ref, certificate_t*,
        !           978:        private_x509_ac_t *this)
        !           979: {
        !           980:        ref_get(&this->ref);
        !           981:        return &this->public.interface.certificate;
        !           982: }
        !           983: 
        !           984: METHOD(certificate_t, get_validity, bool,
        !           985:        private_x509_ac_t *this, time_t *when, time_t *not_before, time_t *not_after)
        !           986: {
        !           987:        time_t t = when ? *when : time(NULL);
        !           988: 
        !           989:        if (not_before)
        !           990:        {
        !           991:                *not_before = this->notBefore;
        !           992:        }
        !           993:        if (not_after)
        !           994:        {
        !           995:                *not_after = this->notAfter;
        !           996:        }
        !           997:        return (t >= this->notBefore && t <= this->notAfter);
        !           998: }
        !           999: 
        !          1000: METHOD(certificate_t, get_encoding, bool,
        !          1001:        private_x509_ac_t *this, cred_encoding_type_t type, chunk_t *encoding)
        !          1002: {
        !          1003:        if (type == CERT_ASN1_DER)
        !          1004:        {
        !          1005:                *encoding = chunk_clone(this->encoding);
        !          1006:                return TRUE;
        !          1007:        }
        !          1008:        return lib->encoding->encode(lib->encoding, type, NULL, encoding,
        !          1009:                                        CRED_PART_X509_AC_ASN1_DER, this->encoding, CRED_PART_END);
        !          1010: }
        !          1011: 
        !          1012: METHOD(certificate_t, equals, bool,
        !          1013:        private_x509_ac_t *this, certificate_t *other)
        !          1014: {
        !          1015:        chunk_t encoding;
        !          1016:        bool equal;
        !          1017: 
        !          1018:        if ((certificate_t*)this == other)
        !          1019:        {
        !          1020:                return TRUE;
        !          1021:        }
        !          1022:        if (other->equals == _equals)
        !          1023:        {       /* skip allocation if we have the same implementation */
        !          1024:                return chunk_equals(this->encoding,
        !          1025:                                                        ((private_x509_ac_t*)other)->encoding);
        !          1026:        }
        !          1027:        if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
        !          1028:        {
        !          1029:                return FALSE;
        !          1030:        }
        !          1031:        equal = chunk_equals(this->encoding, encoding);
        !          1032:        free(encoding.ptr);
        !          1033:        return equal;
        !          1034: }
        !          1035: 
        !          1036: METHOD(certificate_t, destroy, void,
        !          1037:        private_x509_ac_t *this)
        !          1038: {
        !          1039:        if (ref_put(&this->ref))
        !          1040:        {
        !          1041:                DESTROY_IF(this->holderIssuer);
        !          1042:                DESTROY_IF(this->holderSerial);
        !          1043:                DESTROY_IF(this->entityName);
        !          1044:                DESTROY_IF(this->issuerName);
        !          1045:                DESTROY_IF(this->holderCert);
        !          1046:                DESTROY_IF(this->signerCert);
        !          1047:                DESTROY_IF(this->signerKey);
        !          1048:                this->groups->destroy_function(this->groups, (void*)group_destroy);
        !          1049:                signature_params_destroy(this->scheme);
        !          1050:                free(this->serialNumber.ptr);
        !          1051:                free(this->authKeyIdentifier.ptr);
        !          1052:                free(this->encoding.ptr);
        !          1053:                free(this);
        !          1054:        }
        !          1055: }
        !          1056: 
        !          1057: /**
        !          1058:  * create an empty but initialized X.509 attribute certificate
        !          1059:  */
        !          1060: static private_x509_ac_t *create_empty(void)
        !          1061: {
        !          1062:        private_x509_ac_t *this;
        !          1063: 
        !          1064:        INIT(this,
        !          1065:                .public = {
        !          1066:                        .interface = {
        !          1067:                                .certificate = {
        !          1068:                                        .get_type = _get_type,
        !          1069:                                        .get_subject = _get_subject,
        !          1070:                                        .get_issuer = _get_issuer,
        !          1071:                                        .has_subject = _has_subject,
        !          1072:                                        .has_issuer = _has_issuer,
        !          1073:                                        .issued_by = _issued_by,
        !          1074:                                        .get_public_key = _get_public_key,
        !          1075:                                        .get_validity = _get_validity,
        !          1076:                                        .get_encoding = _get_encoding,
        !          1077:                                        .equals = _equals,
        !          1078:                                        .get_ref = _get_ref,
        !          1079:                                        .destroy = _destroy,
        !          1080:                                },
        !          1081:                                .get_serial = _get_serial,
        !          1082:                                .get_holderSerial = _get_holderSerial,
        !          1083:                                .get_holderIssuer = _get_holderIssuer,
        !          1084:                                .get_authKeyIdentifier = _get_authKeyIdentifier,
        !          1085:                                .create_group_enumerator = _create_group_enumerator,
        !          1086:                        },
        !          1087:                },
        !          1088:                .groups = linked_list_create(),
        !          1089:                .ref = 1,
        !          1090:        );
        !          1091: 
        !          1092:        return this;
        !          1093: }
        !          1094: 
        !          1095: /**
        !          1096:  * See header.
        !          1097:  */
        !          1098: x509_ac_t *x509_ac_load(certificate_type_t type, va_list args)
        !          1099: {
        !          1100:        chunk_t blob = chunk_empty;
        !          1101: 
        !          1102:        while (TRUE)
        !          1103:        {
        !          1104:                switch (va_arg(args, builder_part_t))
        !          1105:                {
        !          1106:                        case BUILD_BLOB_ASN1_DER:
        !          1107:                                blob = va_arg(args, chunk_t);
        !          1108:                                continue;
        !          1109:                        case BUILD_END:
        !          1110:                                break;
        !          1111:                        default:
        !          1112:                                return NULL;
        !          1113:                }
        !          1114:                break;
        !          1115:        }
        !          1116:        if (blob.ptr)
        !          1117:        {
        !          1118:                private_x509_ac_t *ac = create_empty();
        !          1119: 
        !          1120:                ac->encoding = chunk_clone(blob);
        !          1121:                if (parse_certificate(ac))
        !          1122:                {
        !          1123:                        return &ac->public;
        !          1124:                }
        !          1125:                destroy(ac);
        !          1126:        }
        !          1127:        return NULL;
        !          1128: }
        !          1129: 
        !          1130: /**
        !          1131:  * Add groups from a list into AC group memberships
        !          1132:  */
        !          1133: static void add_groups_from_list(private_x509_ac_t *this, linked_list_t *list)
        !          1134: {
        !          1135:        enumerator_t *enumerator;
        !          1136:        group_t *group;
        !          1137:        char *name;
        !          1138: 
        !          1139:        enumerator = list->create_enumerator(list);
        !          1140:        while (enumerator->enumerate(enumerator, &name))
        !          1141:        {
        !          1142:                INIT(group,
        !          1143:                        .type = AC_GROUP_TYPE_STRING,
        !          1144:                        .value = chunk_clone(chunk_from_str(name)),
        !          1145:                );
        !          1146:                this->groups->insert_last(this->groups, group);
        !          1147:        }
        !          1148:        enumerator->destroy(enumerator);
        !          1149: }
        !          1150: 
        !          1151: /**
        !          1152:  * See header.
        !          1153:  */
        !          1154: x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args)
        !          1155: {
        !          1156:        hash_algorithm_t digest_alg = HASH_SHA1;
        !          1157:        private_x509_ac_t *ac;
        !          1158: 
        !          1159:        ac = create_empty();
        !          1160:        while (TRUE)
        !          1161:        {
        !          1162:                switch (va_arg(args, builder_part_t))
        !          1163:                {
        !          1164:                        case BUILD_NOT_BEFORE_TIME:
        !          1165:                                ac->notBefore = va_arg(args, time_t);
        !          1166:                                continue;
        !          1167:                        case BUILD_NOT_AFTER_TIME:
        !          1168:                                ac->notAfter = va_arg(args, time_t);
        !          1169:                                continue;
        !          1170:                        case BUILD_SERIAL:
        !          1171:                                ac->serialNumber = chunk_clone(va_arg(args, chunk_t));
        !          1172:                                continue;
        !          1173:                        case BUILD_AC_GROUP_STRINGS:
        !          1174:                                add_groups_from_list(ac, va_arg(args, linked_list_t*));
        !          1175:                                continue;
        !          1176:                        case BUILD_CERT:
        !          1177:                                ac->holderCert = va_arg(args, certificate_t*);
        !          1178:                                ac->holderCert->get_ref(ac->holderCert);
        !          1179:                                continue;
        !          1180:                        case BUILD_SIGNING_CERT:
        !          1181:                                ac->signerCert = va_arg(args, certificate_t*);
        !          1182:                                ac->signerCert->get_ref(ac->signerCert);
        !          1183:                                continue;
        !          1184:                        case BUILD_SIGNING_KEY:
        !          1185:                                ac->signerKey = va_arg(args, private_key_t*);
        !          1186:                                ac->signerKey->get_ref(ac->signerKey);
        !          1187:                                continue;
        !          1188:                        case BUILD_SIGNATURE_SCHEME:
        !          1189:                                ac->scheme = va_arg(args, signature_params_t*);
        !          1190:                                ac->scheme = signature_params_clone(ac->scheme);
        !          1191:                                continue;
        !          1192:                        case BUILD_DIGEST_ALG:
        !          1193:                                digest_alg = va_arg(args, int);
        !          1194:                                continue;
        !          1195:                        case BUILD_END:
        !          1196:                                break;
        !          1197:                        default:
        !          1198:                                destroy(ac);
        !          1199:                                return NULL;
        !          1200:                }
        !          1201:                break;
        !          1202:        }
        !          1203: 
        !          1204:        if (ac->signerKey && ac->holderCert && ac->signerCert &&
        !          1205:                ac->holderCert->get_type(ac->holderCert) == CERT_X509 &&
        !          1206:                ac->signerCert->get_type(ac->signerCert) == CERT_X509)
        !          1207:        {
        !          1208:                if (build_ac(ac, digest_alg))
        !          1209:                {
        !          1210:                        return &ac->public;
        !          1211:                }
        !          1212:        }
        !          1213:        destroy(ac);
        !          1214:        return NULL;
        !          1215: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>