79025268201a340b078eebd11be409407b3a338b
[strongswan.git] / src / libcharon / plugins / dnscert / dnscert_cred.c
1 /*
2 * Copyright (C) 2013 Tobias Brunner
3 * Copyright (C) 2012 Reto Guadagnini
4 * 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 * Copyright (C) 2013 Ruslan Marchenko
18 *
19 * Permission is hereby granted, free of charge, to any person obtaining a copy
20 * of this software and associated documentation files (the "Software"), to deal
21 * in the Software without restriction, including without limitation the rights
22 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 * copies of the Software, and to permit persons to whom the Software is
24 * furnished to do so, subject to the following conditions:
25 *
26 * The above copyright notice and this permission notice shall be included in
27 * all copies or substantial portions of the Software.
28 *
29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 * THE SOFTWARE.
36 */
37
38 #define _GNU_SOURCE
39 #include <stdio.h>
40 #include <string.h>
41
42 #include "dnscert_cred.h"
43 #include "dnscert.h"
44
45 typedef struct private_dnscert_cred_t private_dnscert_cred_t;
46
47 /**
48 * Private data of an dnscert_cred_t object
49 */
50 struct private_dnscert_cred_t {
51
52 /**
53 * Public part
54 */
55 dnscert_cred_t public;
56
57 /**
58 * DNS resolver
59 */
60 resolver_t *res;
61 };
62
63 /**
64 * enumerator over certificates
65 */
66 typedef struct {
67 /** implements enumerator interface */
68 enumerator_t public;
69 /** inner enumerator (enumerates CERT resource records) */
70 enumerator_t *inner;
71 /** response of the DNS resolver which contains the CERTs */
72 resolver_response_t *response;
73 } cert_enumerator_t;
74
75 METHOD(enumerator_t, cert_enumerator_enumerate, bool,
76 cert_enumerator_t *this, certificate_t **cert)
77 {
78 dnscert_t *cur_crt;
79 rr_t *cur_rr;
80 chunk_t certificate;
81
82 /* Get the next supported CERT using the inner enumerator. */
83 while (this->inner->enumerate(this->inner, &cur_rr))
84 {
85 cur_crt = dnscert_create_frm_rr(cur_rr);
86
87 if (!cur_crt)
88 {
89 DBG1(DBG_CFG, " failed to parse CERT RR, skipping");
90 continue;
91 }
92
93 if (cur_crt->get_cert_type(cur_crt) != DNSCERT_TYPE_PKIX &&
94 cur_crt->get_cert_type(cur_crt) != DNSCERT_TYPE_PGP)
95 {
96 DBG1(DBG_CFG, " unsupported CERT type [%d], skipping",
97 cur_crt->get_cert_type(cur_crt));
98 cur_crt->destroy(cur_crt);
99 continue;
100 }
101 /* Try to parse PEM certificate container. Both x509 and PGP should
102 * presumably come as PEM encoded certs. */
103 certificate = cur_crt->get_certificate(cur_crt);
104 *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_ANY,
105 BUILD_BLOB_PEM, certificate,
106 BUILD_END);
107 if (*cert == NULL)
108 {
109 DBG1(DBG_CFG, " unable to parse certificate, skipping",
110 cur_crt->get_cert_type(cur_crt));
111 cur_crt->destroy(cur_crt);
112 continue;
113 }
114 cur_crt->destroy(cur_crt);
115 return TRUE;
116 }
117 return FALSE;
118 }
119
120 METHOD(enumerator_t, cert_enumerator_destroy, void,
121 cert_enumerator_t *this)
122 {
123 this->inner->destroy(this->inner);
124 this->response->destroy(this->response);
125 free(this);
126 }
127
128 METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
129 private_dnscert_cred_t *this, certificate_type_t cert, key_type_t key,
130 identification_t *id, bool trusted)
131 {
132 resolver_response_t *response;
133 cert_enumerator_t *e;
134 char *fqdn;
135
136 if (!id || id->get_type(id) != ID_FQDN)
137 {
138 return enumerator_create_empty();
139 }
140
141 /* query the DNS for the required CERT RRs */
142 if (asprintf(&fqdn, "%Y", id) <= 0)
143 {
144 DBG1(DBG_CFG, "failed to determine FQDN to retrieve CERT RRs");
145 return enumerator_create_empty();
146 }
147
148 DBG1(DBG_CFG, "performing a DNS query for CERT RRs of '%s'", fqdn);
149 response = this->res->query(this->res, fqdn, RR_CLASS_IN, RR_TYPE_CERT);
150 if (!response)
151 {
152 DBG1(DBG_CFG, " query for CERT RRs failed");
153 free(fqdn);
154 return enumerator_create_empty();
155 }
156 free(fqdn);
157
158 if (!response->has_data(response) ||
159 !response->query_name_exist(response))
160 {
161 DBG1(DBG_CFG, " unable to retrieve CERT RRs from the DNS");
162 response->destroy(response);
163 return enumerator_create_empty();
164 }
165
166 if (response->get_security_state(response) != SECURE)
167 {
168 DBG1(DBG_CFG, " DNSSEC state of CERT RRs is not secure");
169 response->destroy(response);
170 return enumerator_create_empty();
171 }
172
173 INIT(e,
174 .public = {
175 .enumerate = (void*)_cert_enumerator_enumerate,
176 .destroy = _cert_enumerator_destroy,
177 },
178 .inner = response->get_rr_set(response)->create_rr_enumerator(
179 response->get_rr_set(response)),
180 .response = response
181 );
182 return &e->public;
183 }
184
185 METHOD(dnscert_cred_t, destroy, void,
186 private_dnscert_cred_t *this)
187 {
188 this->res->destroy(this->res);
189 free(this);
190 }
191
192 /**
193 * Described in header.
194 */
195 dnscert_cred_t *dnscert_cred_create(resolver_t *res)
196 {
197 private_dnscert_cred_t *this;
198
199 INIT(this,
200 .public = {
201 .set = {
202 .create_private_enumerator = (void*)return_null,
203 .create_cert_enumerator = _create_cert_enumerator,
204 .create_shared_enumerator = (void*)return_null,
205 .create_cdp_enumerator = (void*)return_null,
206 .cache_cert = (void*)nop,
207 },
208 .destroy = _destroy,
209 },
210 .res = res,
211 );
212
213 return &this->public;
214 }