Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/cert_payload.c, revision 1.1.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>