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>