Annotation of embedaddon/strongswan/src/libcharon/plugins/ipseckey/ipseckey_cred.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Tobias Brunner
                      3:  * Copyright (C) 2012 Reto Guadagnini
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #define _GNU_SOURCE
                     18: #include <stdio.h>
                     19: #include <string.h>
                     20: 
                     21: #include "ipseckey_cred.h"
                     22: #include "ipseckey.h"
                     23: 
                     24: #include <bio/bio_reader.h>
                     25: 
                     26: typedef struct private_ipseckey_cred_t private_ipseckey_cred_t;
                     27: 
                     28: /**
                     29:  * Private data of an ipseckey_cred_t object
                     30:  */
                     31: struct private_ipseckey_cred_t {
                     32: 
                     33:        /**
                     34:         * Public part
                     35:         */
                     36:        ipseckey_cred_t public;
                     37: 
                     38:        /**
                     39:         * DNS resolver
                     40:         */
                     41:        resolver_t *res;
                     42: };
                     43: 
                     44: /**
                     45:  * enumerator over certificates
                     46:  */
                     47: typedef struct {
                     48:        /** implements enumerator interface */
                     49:        enumerator_t public;
                     50:        /** inner enumerator (enumerates IPSECKEY resource records) */
                     51:        enumerator_t *inner;
                     52:        /** response of the DNS resolver which contains the IPSECKEYs */
                     53:        resolver_response_t *response;
                     54:        /* IPSECKEYs are not valid before this point in time */
                     55:        time_t notBefore;
                     56:        /* IPSECKEYs are not valid after this point in time */
                     57:        time_t notAfter;
                     58:        /* identity to which the IPSECKEY belongs */
                     59:        identification_t *identity;
                     60:        /** most recently enumerated certificate */
                     61:        certificate_t *cert;
                     62: } cert_enumerator_t;
                     63: 
                     64: METHOD(enumerator_t, cert_enumerator_enumerate, bool,
                     65:        cert_enumerator_t *this, va_list args)
                     66: {
                     67:        certificate_t **cert;
                     68:        ipseckey_t *cur_ipseckey;
                     69:        public_key_t *public;
                     70:        rr_t *cur_rr;
                     71:        chunk_t key;
                     72: 
                     73:        VA_ARGS_VGET(args, cert);
                     74: 
                     75:        /* Get the next supported IPSECKEY using the inner enumerator. */
                     76:        while (this->inner->enumerate(this->inner, &cur_rr))
                     77:        {
                     78:                cur_ipseckey = ipseckey_create_frm_rr(cur_rr);
                     79: 
                     80:                if (!cur_ipseckey)
                     81:                {
                     82:                        DBG1(DBG_CFG, "  failed to parse IPSECKEY, skipping");
                     83:                        continue;
                     84:                }
                     85: 
                     86:                if (cur_ipseckey->get_algorithm(cur_ipseckey) != IPSECKEY_ALGORITHM_RSA)
                     87:                {
                     88:                        DBG1(DBG_CFG, "  unsupported IPSECKEY algorithm, skipping");
                     89:                        cur_ipseckey->destroy(cur_ipseckey);
                     90:                        continue;
                     91:                }
                     92: 
                     93:                /* wrap the key of the IPSECKEY in a certificate and return this
                     94:                 * certificate */
                     95:                key = cur_ipseckey->get_public_key(cur_ipseckey);
                     96:                public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
                     97:                                                                        BUILD_BLOB_DNSKEY, key,
                     98:                                                                        BUILD_END);
                     99:                cur_ipseckey->destroy(cur_ipseckey);
                    100:                if (!public)
                    101:                {
                    102:                        DBG1(DBG_CFG, "  failed to create public key from IPSECKEY");
                    103:                        continue;
                    104:                }
                    105:                DESTROY_IF(this->cert);
                    106:                this->cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
                    107:                                                                                CERT_TRUSTED_PUBKEY,
                    108:                                                                                BUILD_PUBLIC_KEY, public,
                    109:                                                                                BUILD_SUBJECT, this->identity,
                    110:                                                                                BUILD_NOT_BEFORE_TIME, this->notBefore,
                    111:                                                                                BUILD_NOT_AFTER_TIME, this->notAfter,
                    112:                                                                                BUILD_END);
                    113:                public->destroy(public);
                    114:                if (!this->cert)
                    115:                {
                    116:                        DBG1(DBG_CFG, "  failed to create certificate from IPSECKEY");
                    117:                        continue;
                    118:                }
                    119:                *cert = this->cert;
                    120:                return TRUE;
                    121:        }
                    122:        return FALSE;
                    123: }
                    124: 
                    125: METHOD(enumerator_t, cert_enumerator_destroy, void,
                    126:        cert_enumerator_t *this)
                    127: {
                    128:        DESTROY_IF(this->cert);
                    129:        this->inner->destroy(this->inner);
                    130:        this->response->destroy(this->response);
                    131:        free(this);
                    132: }
                    133: 
                    134: METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
                    135:        private_ipseckey_cred_t *this, certificate_type_t cert, key_type_t key,
                    136:        identification_t *id, bool trusted)
                    137: {
                    138:        resolver_response_t *response;
                    139:        enumerator_t *rrsig_enum;
                    140:        cert_enumerator_t *e;
                    141:        rr_set_t *rrset;
                    142:        rr_t *rrsig;
                    143:        bio_reader_t *reader;
                    144:        uint32_t nBefore, nAfter;
                    145:        chunk_t ignore;
                    146:        char *fqdn;
                    147: 
                    148:        if (!id || id->get_type(id) != ID_FQDN)
                    149:        {
                    150:                return enumerator_create_empty();
                    151:        }
                    152: 
                    153:        /* query the DNS for the required IPSECKEY RRs */
                    154:        if (asprintf(&fqdn, "%Y", id) <= 0)
                    155:        {
                    156:                DBG1(DBG_CFG, "failed to determine FQDN to retrieve IPSECKEY RRs");
                    157:                return enumerator_create_empty();
                    158:        }
                    159:        DBG1(DBG_CFG, "performing a DNS query for IPSECKEY RRs of '%s'", fqdn);
                    160:        response = this->res->query(this->res, fqdn, RR_CLASS_IN, RR_TYPE_IPSECKEY);
                    161:        if (!response)
                    162:        {
                    163:                DBG1(DBG_CFG, "  query for IPSECKEY RRs failed");
                    164:                free(fqdn);
                    165:                return enumerator_create_empty();
                    166:        }
                    167:        free(fqdn);
                    168: 
                    169:        if (!response->has_data(response) ||
                    170:                !response->query_name_exist(response))
                    171:        {
                    172:                DBG1(DBG_CFG, "  unable to retrieve IPSECKEY RRs from the DNS");
                    173:                response->destroy(response);
                    174:                return enumerator_create_empty();
                    175:        }
                    176: 
                    177:        if (response->get_security_state(response) != SECURE)
                    178:        {
                    179:                DBG1(DBG_CFG, "  DNSSEC state of IPSECKEY RRs is not secure");
                    180:                response->destroy(response);
                    181:                return enumerator_create_empty();
                    182:        }
                    183: 
                    184:        /* determine the validity period of the retrieved IPSECKEYs
                    185:         *
                    186:         * we use the "Signature Inception" and "Signature Expiration" field
                    187:         * of the first RRSIG RR to determine the validity period of the
                    188:         * IPSECKEY RRs.
                    189:         * TODO: Take multiple RRSIGs into account. */
                    190:        rrset = response->get_rr_set(response);
                    191:        rrsig_enum = rrset->create_rrsig_enumerator(rrset);
                    192:        if (!rrsig_enum || !rrsig_enum->enumerate(rrsig_enum, &rrsig))
                    193:        {
                    194:                DBG1(DBG_CFG, "  unable to determine the validity period of "
                    195:                         "IPSECKEY RRs because no RRSIGs are present");
                    196:                DESTROY_IF(rrsig_enum);
                    197:                response->destroy(response);
                    198:                return enumerator_create_empty();
                    199:        }
                    200:        rrsig_enum->destroy(rrsig_enum);
                    201: 
                    202:        /* parse the RRSIG for its validity period (RFC 4034) */
                    203:        reader = bio_reader_create(rrsig->get_rdata(rrsig));
                    204:        if (!reader->read_data(reader, 8, &ignore) ||
                    205:                !reader->read_uint32(reader, &nAfter) ||
                    206:                !reader->read_uint32(reader, &nBefore))
                    207:        {
                    208:                DBG1(DBG_CFG, "  unable to determine the validity period of RRSIG RRs");
                    209:                reader->destroy(reader);
                    210:                response->destroy(response);
                    211:                return enumerator_create_empty();
                    212:        }
                    213:        reader->destroy(reader);
                    214: 
                    215:        INIT(e,
                    216:                .public = {
                    217:                        .enumerate = enumerator_enumerate_default,
                    218:                        .venumerate = _cert_enumerator_enumerate,
                    219:                        .destroy = _cert_enumerator_destroy,
                    220:                },
                    221:                .inner = rrset->create_rr_enumerator(rrset),
                    222:                .response = response,
                    223:                .notBefore = nBefore,
                    224:                .notAfter = nAfter,
                    225:                .identity = id,
                    226:        );
                    227:        return &e->public;
                    228: }
                    229: 
                    230: METHOD(ipseckey_cred_t, destroy, void,
                    231:        private_ipseckey_cred_t *this)
                    232: {
                    233:        this->res->destroy(this->res);
                    234:        free(this);
                    235: }
                    236: 
                    237: /**
                    238:  * Described in header.
                    239:  */
                    240: ipseckey_cred_t *ipseckey_cred_create(resolver_t *res)
                    241: {
                    242:        private_ipseckey_cred_t *this;
                    243: 
                    244:        INIT(this,
                    245:                .public = {
                    246:                        .set = {
                    247:                                .create_private_enumerator = (void*)return_null,
                    248:                                .create_cert_enumerator = _create_cert_enumerator,
                    249:                                .create_shared_enumerator = (void*)return_null,
                    250:                                .create_cdp_enumerator = (void*)return_null,
                    251:                                .cache_cert = (void*)nop,
                    252:                        },
                    253:                        .destroy = _destroy,
                    254:                },
                    255:                .res = res,
                    256:        );
                    257: 
                    258:        return &this->public;
                    259: }

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