Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/cert_payload.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008 Tobias Brunner
        !             3:  * Copyright (C) 2005-2010 Martin Willi
        !             4:  * Copyright (C) 2010 revosec AG
        !             5:  * Copyright (C) 2005 Jan Hutter
        !             6:  * HSR Hochschule fuer Technik Rapperswil
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify it
        !             9:  * under the terms of the GNU General Public License as published by the
        !            10:  * Free Software Foundation; either version 2 of the License, or (at your
        !            11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful, but
        !            14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            16:  * for more details.
        !            17:  */
        !            18: 
        !            19: #include <stddef.h>
        !            20: #include <ctype.h>
        !            21: 
        !            22: #include <daemon.h>
        !            23: 
        !            24: #include "cert_payload.h"
        !            25: 
        !            26: ENUM(cert_encoding_names, ENC_PKCS7_WRAPPED_X509, ENC_OCSP_CONTENT,
        !            27:        "ENC_PKCS7_WRAPPED_X509",
        !            28:        "ENC_PGP",
        !            29:        "ENC_DNS_SIGNED_KEY",
        !            30:        "ENC_X509_SIGNATURE",
        !            31:        "ENC_X509_KEY_EXCHANGE",
        !            32:        "ENC_KERBEROS_TOKENS",
        !            33:        "ENC_CRL",
        !            34:        "ENC_ARL",
        !            35:        "ENC_SPKI",
        !            36:        "ENC_X509_ATTRIBUTE",
        !            37:        "ENC_RAW_RSA_KEY",
        !            38:        "ENC_X509_HASH_AND_URL",
        !            39:        "ENC_X509_HASH_AND_URL_BUNDLE",
        !            40:        "ENC_OCSP_CONTENT",
        !            41: );
        !            42: 
        !            43: typedef struct private_cert_payload_t private_cert_payload_t;
        !            44: 
        !            45: /**
        !            46:  * Private data of an cert_payload_t object.
        !            47:  */
        !            48: struct private_cert_payload_t {
        !            49: 
        !            50:        /**
        !            51:         * Public cert_payload_t interface.
        !            52:         */
        !            53:        cert_payload_t public;
        !            54: 
        !            55:        /**
        !            56:         * Next payload type.
        !            57:         */
        !            58:        uint8_t  next_payload;
        !            59: 
        !            60:        /**
        !            61:         * Critical flag.
        !            62:         */
        !            63:        bool critical;
        !            64: 
        !            65:        /**
        !            66:         * reserved bits
        !            67:         */
        !            68:        bool reserved[7];
        !            69: 
        !            70:        /**
        !            71:         * Length of this payload.
        !            72:         */
        !            73:        uint16_t payload_length;
        !            74: 
        !            75:        /**
        !            76:         * Encoding of the CERT Data.
        !            77:         */
        !            78:        uint8_t encoding;
        !            79: 
        !            80:        /**
        !            81:         * The contained cert data value.
        !            82:         */
        !            83:        chunk_t data;
        !            84: 
        !            85:        /**
        !            86:         * TRUE if the "Hash and URL" data is invalid
        !            87:         */
        !            88:        bool invalid_hash_and_url;
        !            89: 
        !            90:        /**
        !            91:         * The payload type.
        !            92:         */
        !            93:        payload_type_t type;
        !            94: };
        !            95: 
        !            96: /**
        !            97:  * Encoding rules to parse or generate a CERT payload
        !            98:  *
        !            99:  * The defined offsets are the positions in a object of type
        !           100:  * private_cert_payload_t.
        !           101:  *
        !           102:  */
        !           103: static encoding_rule_t encodings[] = {
        !           104:        /* 1 Byte next payload type, stored in the field next_payload */
        !           105:        { U_INT_8,                      offsetof(private_cert_payload_t, next_payload)  },
        !           106:        /* the critical bit */
        !           107:        { FLAG,                         offsetof(private_cert_payload_t, critical)              },
        !           108:        /* 7 Bit reserved bits, nowhere stored */
        !           109:        { RESERVED_BIT,         offsetof(private_cert_payload_t, reserved[0])   },
        !           110:        { RESERVED_BIT,         offsetof(private_cert_payload_t, reserved[1])   },
        !           111:        { RESERVED_BIT,         offsetof(private_cert_payload_t, reserved[2])   },
        !           112:        { RESERVED_BIT,         offsetof(private_cert_payload_t, reserved[3])   },
        !           113:        { RESERVED_BIT,         offsetof(private_cert_payload_t, reserved[4])   },
        !           114:        { RESERVED_BIT,         offsetof(private_cert_payload_t, reserved[5])   },
        !           115:        { RESERVED_BIT,         offsetof(private_cert_payload_t, reserved[6])   },
        !           116:        /* Length of the whole payload*/
        !           117:        { PAYLOAD_LENGTH,       offsetof(private_cert_payload_t, payload_length)},
        !           118:        /* 1 Byte CERT type*/
        !           119:        { U_INT_8,                      offsetof(private_cert_payload_t, encoding)              },
        !           120:        /* some cert data bytes, length is defined in PAYLOAD_LENGTH */
        !           121:        { CHUNK_DATA,           offsetof(private_cert_payload_t, data)                  }
        !           122: };
        !           123: 
        !           124: /*
        !           125:                            1                   2                   3
        !           126:        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        !           127:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           128:       ! Next Payload  !C!  RESERVED   !         Payload Length        !
        !           129:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           130:       ! Cert Encoding !                                               !
        !           131:       +-+-+-+-+-+-+-+-+                                               !
        !           132:       ~                       Certificate Data                        ~
        !           133:       !                                                               !
        !           134:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           135: */
        !           136: 
        !           137: METHOD(payload_t, verify, status_t,
        !           138:        private_cert_payload_t *this)
        !           139: {
        !           140:        if (this->encoding == ENC_X509_HASH_AND_URL ||
        !           141:                this->encoding == ENC_X509_HASH_AND_URL_BUNDLE)
        !           142:        {
        !           143:                int i;
        !           144: 
        !           145:                /* coarse verification of "Hash and URL" encoded certificates */
        !           146:                if (this->data.len <= 20)
        !           147:                {
        !           148:                        DBG1(DBG_ENC, "invalid payload length for hash-and-url (%d), ignore",
        !           149:                                 this->data.len);
        !           150:                        this->invalid_hash_and_url = TRUE;
        !           151:                        return SUCCESS;
        !           152:                }
        !           153:                for (i = 20; i < this->data.len; ++i)
        !           154:                {
        !           155:                        if (this->data.ptr[i] == '\0')
        !           156:                        {
        !           157:                                /* null terminated, fine */
        !           158:                                return SUCCESS;
        !           159:                        }
        !           160:                        else if (!isprint(this->data.ptr[i]))
        !           161:                        {
        !           162:                                DBG1(DBG_ENC, "non printable characters in url of hash-and-url"
        !           163:                                         " encoded certificate payload, ignore");
        !           164:                                this->invalid_hash_and_url = TRUE;
        !           165:                                return SUCCESS;
        !           166:                        }
        !           167:                }
        !           168:                /* URL is not null terminated, correct that */
        !           169:                this->data = chunk_cat("mc", this->data, chunk_from_chars(0));
        !           170:        }
        !           171:        return SUCCESS;
        !           172: }
        !           173: 
        !           174: METHOD(payload_t, get_encoding_rules, int,
        !           175:        private_cert_payload_t *this, encoding_rule_t **rules)
        !           176: {
        !           177:        *rules = encodings;
        !           178:        return countof(encodings);
        !           179: }
        !           180: 
        !           181: METHOD(payload_t, get_header_length, int,
        !           182:        private_cert_payload_t *this)
        !           183: {
        !           184:        return 5;
        !           185: }
        !           186: 
        !           187: METHOD(payload_t, get_type, payload_type_t,
        !           188:        private_cert_payload_t *this)
        !           189: {
        !           190:        return this->type;
        !           191: }
        !           192: 
        !           193: METHOD(payload_t, get_next_type, payload_type_t,
        !           194:        private_cert_payload_t *this)
        !           195: {
        !           196:        return this->next_payload;
        !           197: }
        !           198: 
        !           199: METHOD(payload_t, set_next_type, void,
        !           200:        private_cert_payload_t *this, payload_type_t type)
        !           201: {
        !           202:        this->next_payload = type;
        !           203: }
        !           204: 
        !           205: METHOD(payload_t, get_length, size_t,
        !           206:        private_cert_payload_t *this)
        !           207: {
        !           208:        return this->payload_length;
        !           209: }
        !           210: 
        !           211: METHOD(cert_payload_t, get_cert_encoding, cert_encoding_t,
        !           212:        private_cert_payload_t *this)
        !           213: {
        !           214:        return this->encoding;
        !           215: }
        !           216: 
        !           217: METHOD(cert_payload_t, get_cert, certificate_t*,
        !           218:        private_cert_payload_t *this)
        !           219: {
        !           220:        int type;
        !           221: 
        !           222:        switch (this->encoding)
        !           223:        {
        !           224:                case ENC_X509_SIGNATURE:
        !           225:                        type = CERT_X509;
        !           226:                        break;
        !           227:                case ENC_X509_ATTRIBUTE:
        !           228:                        type = CERT_X509_AC;
        !           229:                        break;
        !           230:                case ENC_CRL:
        !           231:                        type = CERT_X509_CRL;
        !           232:                        break;
        !           233:                default:
        !           234:                        return NULL;
        !           235:        }
        !           236:        return lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
        !           237:                                                          BUILD_BLOB_ASN1_DER, this->data, BUILD_END);
        !           238: }
        !           239: 
        !           240: METHOD(cert_payload_t, get_container, container_t*,
        !           241:        private_cert_payload_t *this)
        !           242: {
        !           243:        int type;
        !           244: 
        !           245:        switch (this->encoding)
        !           246:        {
        !           247:                case ENC_PKCS7_WRAPPED_X509:
        !           248:                        type = CONTAINER_PKCS7;
        !           249:                        break;
        !           250:                default:
        !           251:                        return NULL;
        !           252:        }
        !           253:        return lib->creds->create(lib->creds, CRED_CONTAINER, type,
        !           254:                                                          BUILD_BLOB_ASN1_DER, this->data, BUILD_END);
        !           255: }
        !           256: 
        !           257: METHOD(cert_payload_t, get_hash, chunk_t,
        !           258:        private_cert_payload_t *this)
        !           259: {
        !           260:        chunk_t hash = chunk_empty;
        !           261: 
        !           262:        if ((this->encoding != ENC_X509_HASH_AND_URL &&
        !           263:                 this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
        !           264:                this->invalid_hash_and_url)
        !           265:        {
        !           266:                return hash;
        !           267:        }
        !           268:        hash.ptr = this->data.ptr;
        !           269:        hash.len = 20;
        !           270:        return hash;
        !           271: }
        !           272: 
        !           273: METHOD(cert_payload_t, get_url, char*,
        !           274:        private_cert_payload_t *this)
        !           275: {
        !           276:        if ((this->encoding != ENC_X509_HASH_AND_URL &&
        !           277:                 this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) ||
        !           278:                this->invalid_hash_and_url)
        !           279:        {
        !           280:                return NULL;
        !           281:        }
        !           282:        return (char*)this->data.ptr + 20;
        !           283: }
        !           284: 
        !           285: METHOD2(payload_t, cert_payload_t, destroy, void,
        !           286:        private_cert_payload_t *this)
        !           287: {
        !           288:        free(this->data.ptr);
        !           289:        free(this);
        !           290: }
        !           291: 
        !           292: /*
        !           293:  * Described in header
        !           294:  */
        !           295: cert_payload_t *cert_payload_create(payload_type_t type)
        !           296: {
        !           297:        private_cert_payload_t *this;
        !           298: 
        !           299:        INIT(this,
        !           300:                .public = {
        !           301:                        .payload_interface = {
        !           302:                                .verify = _verify,
        !           303:                                .get_encoding_rules = _get_encoding_rules,
        !           304:                                .get_header_length = _get_header_length,
        !           305:                                .get_length = _get_length,
        !           306:                                .get_next_type = _get_next_type,
        !           307:                                .set_next_type = _set_next_type,
        !           308:                                .get_type = _get_type,
        !           309:                                .destroy = _destroy,
        !           310:                        },
        !           311:                        .get_cert = _get_cert,
        !           312:                        .get_container = _get_container,
        !           313:                        .get_cert_encoding = _get_cert_encoding,
        !           314:                        .get_hash = _get_hash,
        !           315:                        .get_url = _get_url,
        !           316:                        .destroy = _destroy,
        !           317:                },
        !           318:                .next_payload = PL_NONE,
        !           319:                .payload_length = get_header_length(this),
        !           320:                .type = type,
        !           321:        );
        !           322:        return &this->public;
        !           323: }
        !           324: 
        !           325: /*
        !           326:  * Described in header
        !           327:  */
        !           328: cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
        !           329:                                                                                          certificate_t *cert)
        !           330: {
        !           331:        private_cert_payload_t *this;
        !           332: 
        !           333:        this = (private_cert_payload_t*)cert_payload_create(type);
        !           334:        switch (cert->get_type(cert))
        !           335:        {
        !           336:                case CERT_X509:
        !           337:                        this->encoding = ENC_X509_SIGNATURE;
        !           338:                        break;
        !           339:                case CERT_X509_AC:
        !           340:                        this->encoding = ENC_X509_ATTRIBUTE;
        !           341:                        break;
        !           342:                default:
        !           343:                        DBG1(DBG_ENC, "embedding %N certificate in payload failed",
        !           344:                                 certificate_type_names, cert->get_type(cert));
        !           345:                        free(this);
        !           346:                        return NULL;
        !           347:        }
        !           348:        if (!cert->get_encoding(cert, CERT_ASN1_DER, &this->data))
        !           349:        {
        !           350:                DBG1(DBG_ENC, "encoding certificate for cert payload failed");
        !           351:                free(this);
        !           352:                return NULL;
        !           353:        }
        !           354:        this->payload_length = get_header_length(this) + this->data.len;
        !           355: 
        !           356:        return &this->public;
        !           357: }
        !           358: 
        !           359: /*
        !           360:  * Described in header
        !           361:  */
        !           362: cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
        !           363: {
        !           364:        private_cert_payload_t *this;
        !           365: 
        !           366:        this = (private_cert_payload_t*)cert_payload_create(PLV2_CERTIFICATE);
        !           367:        this->encoding = ENC_X509_HASH_AND_URL;
        !           368:        this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
        !           369:        this->payload_length = get_header_length(this) + this->data.len;
        !           370: 
        !           371:        return &this->public;
        !           372: }
        !           373: 
        !           374: /*
        !           375:  * Described in header
        !           376:  */
        !           377: cert_payload_t *cert_payload_create_custom(payload_type_t type,
        !           378:                                                                                cert_encoding_t encoding, chunk_t data)
        !           379: {
        !           380:        private_cert_payload_t *this;
        !           381: 
        !           382:        this = (private_cert_payload_t*)cert_payload_create(type);
        !           383:        this->encoding = encoding;
        !           384:        this->data = data;
        !           385:        this->payload_length = get_header_length(this) + this->data.len;
        !           386: 
        !           387:        return &this->public;
        !           388: }

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