certificate_t->issued_by takes an argument to receive signature scheme
[strongswan.git] / src / libstrongswan / credentials / sets / auth_cfg_wrapper.c
1 /*
2 * Copyright (C) 2008-2009 Martin Willi
3 * Copyright (C) 2008 Tobias Brunner
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 #include <library.h>
18 #include <debug.h>
19
20 #include "auth_cfg_wrapper.h"
21
22 typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t;
23
24 /**
25 * private data of auth_cfg_wrapper
26 */
27 struct private_auth_cfg_wrapper_t {
28
29 /**
30 * public functions
31 */
32 auth_cfg_wrapper_t public;
33
34 /**
35 * wrapped auth info
36 */
37 auth_cfg_t *auth;
38 };
39
40 /**
41 * enumerator for auth_cfg_wrapper_t.create_cert_enumerator()
42 */
43 typedef struct {
44 /** implements enumerator_t */
45 enumerator_t public;
46 /** inner enumerator from auth_cfg */
47 enumerator_t *inner;
48 /** wrapped auth round */
49 auth_cfg_t *auth;
50 /** enumerated cert type */
51 certificate_type_t cert;
52 /** enumerated key type */
53 key_type_t key;
54 /** enumerated id */
55 identification_t *id;
56 } wrapper_enumerator_t;
57
58 /**
59 * Tries to fetch a certificate that was supplied as "Hash and URL"
60 * (replaces rule type and value in place).
61 */
62 static bool fetch_cert(wrapper_enumerator_t *enumerator,
63 auth_rule_t *rule, void **value)
64 {
65 char *url = (char*)*value;
66 if (!url)
67 {
68 /* fetching the certificate previously failed */
69 return FALSE;
70 }
71
72 chunk_t data;
73 certificate_t *cert;
74
75 DBG1(DBG_CFG, " fetching certificate from '%s' ...", url);
76 if (lib->fetcher->fetch(lib->fetcher, url, &data, FETCH_END) != SUCCESS)
77 {
78 DBG1(DBG_CFG, " fetching certificate failed");
79 /* we set the item to NULL, so we can skip it */
80 enumerator->auth->replace(enumerator->auth, enumerator->inner,
81 *rule, NULL);
82 return FALSE;
83 }
84
85 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
86 BUILD_BLOB_ASN1_DER, data, BUILD_END);
87 free(data.ptr);
88
89 if (!cert)
90 {
91 DBG1(DBG_CFG, " parsing fetched certificate failed");
92 /* we set the item to NULL, so we can skip it */
93 enumerator->auth->replace(enumerator->auth, enumerator->inner,
94 *rule, NULL);
95 return FALSE;
96 }
97
98 DBG1(DBG_CFG, " fetched certificate \"%Y\"", cert->get_subject(cert));
99 lib->credmgr->cache_cert(lib->credmgr, cert);
100
101 if (*rule == AUTH_HELPER_IM_HASH_URL)
102 {
103 *rule = AUTH_HELPER_IM_CERT;
104 }
105 else
106 {
107 *rule = AUTH_HELPER_SUBJECT_CERT;
108 }
109 *value = cert;
110 enumerator->auth->replace(enumerator->auth, enumerator->inner,
111 *rule, cert->get_ref(cert));
112 return TRUE;
113 }
114
115 /**
116 * enumerate function for wrapper_enumerator_t
117 */
118 static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
119 {
120 auth_rule_t rule;
121 certificate_t *current;
122 public_key_t *public;
123
124 while (this->inner->enumerate(this->inner, &rule, &current))
125 {
126 if (rule == AUTH_HELPER_IM_HASH_URL ||
127 rule == AUTH_HELPER_SUBJECT_HASH_URL)
128 { /* on-demand fetching of hash and url certificates */
129 if (!fetch_cert(this, &rule, (void**)&current))
130 {
131 continue;
132 }
133 }
134 else if (rule != AUTH_HELPER_SUBJECT_CERT &&
135 rule != AUTH_HELPER_IM_CERT &&
136 rule != AUTH_HELPER_REVOCATION_CERT)
137 { /* handle only HELPER certificates */
138 continue;
139 }
140 if (this->cert != CERT_ANY && this->cert != current->get_type(current))
141 { /* CERT type requested, but does not match */
142 continue;
143 }
144 public = current->get_public_key(current);
145 if (this->key != KEY_ANY && !public)
146 { /* key type requested, but no public key */
147 DESTROY_IF(public);
148 continue;
149 }
150 if (this->key != KEY_ANY && public && this->key != public->get_type(public))
151 { /* key type requested, but public key has another type */
152 DESTROY_IF(public);
153 continue;
154 }
155 DESTROY_IF(public);
156 if (this->id && !current->has_subject(current, this->id))
157 { /* subject requested, but does not match */
158 continue;
159 }
160 *cert = current;
161 return TRUE;
162 }
163 return FALSE;
164 }
165
166 /**
167 * destroy function for wrapper_enumerator_t
168 */
169 static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
170 {
171 this->inner->destroy(this->inner);
172 free(this);
173 }
174
175 METHOD(credential_set_t, create_enumerator, enumerator_t*,
176 private_auth_cfg_wrapper_t *this, certificate_type_t cert, key_type_t key,
177 identification_t *id, bool trusted)
178 {
179 wrapper_enumerator_t *enumerator;
180
181 if (trusted)
182 {
183 return NULL;
184 }
185 enumerator = malloc_thing(wrapper_enumerator_t);
186 enumerator->auth = this->auth;
187 enumerator->cert = cert;
188 enumerator->key = key;
189 enumerator->id = id;
190 enumerator->inner = this->auth->create_enumerator(this->auth);
191 enumerator->public.enumerate = (void*)enumerate;
192 enumerator->public.destroy = (void*)wrapper_enumerator_destroy;
193 return &enumerator->public;
194 }
195
196 METHOD(auth_cfg_wrapper_t, destroy, void,
197 private_auth_cfg_wrapper_t *this)
198 {
199 free(this);
200 }
201
202 /*
203 * see header file
204 */
205 auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth)
206 {
207 private_auth_cfg_wrapper_t *this;
208
209 INIT(this,
210 .public = {
211 .set = {
212 .create_cert_enumerator = _create_enumerator,
213 .create_shared_enumerator = (void*)return_null,
214 .create_cdp_enumerator = (void*)return_null,
215 .cache_cert = (void*)nop,
216 },
217 .destroy = _destroy,
218 },
219 .auth = auth,
220 );
221
222 return &this->public;
223 }