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