Return to ipseckey_cred.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / ipseckey |
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: }