Annotation of embedaddon/strongswan/src/libcharon/plugins/ipseckey/ipseckey_cred.c, revision 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>