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>