32783ff93a57549e312e9def308a5c62ff0058b2
[strongswan.git] / src / charon / credentials / sets / auth_info_wrapper.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
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 * $Id$
17 */
18
19 #include <daemon.h>
20
21 #include "auth_info_wrapper.h"
22
23 typedef struct private_auth_info_wrapper_t private_auth_info_wrapper_t;
24
25 /**
26 * private data of auth_info_wrapper
27 */
28 struct private_auth_info_wrapper_t {
29
30 /**
31 * public functions
32 */
33 auth_info_wrapper_t public;
34
35 /**
36 * wrapped auth info
37 */
38 auth_info_t *auth;
39 };
40
41 /**
42 * enumerator for auth_info_wrapper_t.create_cert_enumerator()
43 */
44 typedef struct {
45 /** implements enumerator_t */
46 enumerator_t public;
47 /** inner enumerator from auth_info */
48 enumerator_t *inner;
49 /** wrapped auth info */
50 auth_info_t *auth;
51 /** enumerated cert type */
52 certificate_type_t cert;
53 /** enumerated key type */
54 key_type_t key;
55 /** enumerated id */
56 identification_t *id;
57 } wrapper_enumerator_t;
58
59 /**
60 * Tries to fetch a certificate that was supplied as "Hash and URL" (replaces the
61 * item's type and value in place).
62 */
63 static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, 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) != 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_item(enumerator->inner, *type, 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
87 if (!cert)
88 {
89 DBG1(DBG_CFG, " parsing fetched certificate failed");
90 /* we set the item to NULL, so we can skip it */
91 enumerator->auth->replace_item(enumerator->inner, *type, NULL);
92 return FALSE;
93 }
94
95 DBG1(DBG_CFG, " fetched certificate \"%D\"", cert->get_subject(cert));
96 charon->credentials->cache_cert(charon->credentials, cert);
97
98 *type = (*type == AUTHN_IM_HASH_URL) ? AUTHN_IM_CERT : AUTHN_SUBJECT_CERT;
99 *value = cert;
100 enumerator->auth->replace_item(enumerator->inner, *type, cert);
101
102 return TRUE;
103 }
104
105 /**
106 * enumerate function for wrapper_enumerator_t
107 */
108 static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
109 {
110 auth_item_t type;
111 certificate_t *current;
112 public_key_t *public;
113
114 while (this->inner->enumerate(this->inner, &type, &current))
115 {
116 if (type == AUTHN_IM_HASH_URL ||
117 type == AUTHN_SUBJECT_HASH_URL)
118 {
119 if (!fetch_cert(this, &type, (void**)&current))
120 {
121 continue;
122 }
123 }
124 else if (type != AUTHN_SUBJECT_CERT &&
125 type != AUTHN_IM_CERT)
126 {
127 continue;
128 }
129
130 if (this->cert != CERT_ANY && this->cert != current->get_type(current))
131 { /* CERT type requested, but does not match */
132 continue;
133 }
134 public = current->get_public_key(current);
135 if (this->key != KEY_ANY && !public)
136 { /* key type requested, but no public key */
137 DESTROY_IF(public);
138 continue;
139 }
140 if (this->key != KEY_ANY && public && this->key != public->get_type(public))
141 { /* key type requested, but public key has another type */
142 DESTROY_IF(public);
143 continue;
144 }
145 DESTROY_IF(public);
146 if (this->id && !current->has_subject(current, this->id))
147 { /* subject requested, but does not match */
148 continue;
149 }
150 *cert = current;
151 return TRUE;
152 }
153 return FALSE;
154 }
155
156 /**
157 * destroy function for wrapper_enumerator_t
158 */
159 static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
160 {
161 this->inner->destroy(this->inner);
162 free(this);
163 }
164
165 /**
166 * implementation of auth_info_wrapper_t.set.create_cert_enumerator
167 */
168 static enumerator_t *create_enumerator(private_auth_info_wrapper_t *this,
169 certificate_type_t cert, key_type_t key,
170 identification_t *id, bool trusted)
171 {
172 wrapper_enumerator_t *enumerator;
173
174 if (trusted)
175 {
176 return NULL;
177 }
178 enumerator = malloc_thing(wrapper_enumerator_t);
179 enumerator->auth = this->auth;
180 enumerator->cert = cert;
181 enumerator->key = key;
182 enumerator->id = id;
183 enumerator->inner = this->auth->create_item_enumerator(this->auth);
184 enumerator->public.enumerate = (void*)enumerate;
185 enumerator->public.destroy = (void*)wrapper_enumerator_destroy;
186 return &enumerator->public;
187 }
188
189 /**
190 * Implementation of auth_info_wrapper_t.destroy
191 */
192 static void destroy(private_auth_info_wrapper_t *this)
193 {
194 free(this);
195 }
196
197 /*
198 * see header file
199 */
200 auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth)
201 {
202 private_auth_info_wrapper_t *this = malloc_thing(private_auth_info_wrapper_t);
203
204 this->public.set.create_private_enumerator = (void*)return_null;
205 this->public.set.create_cert_enumerator = (void*)create_enumerator;
206 this->public.set.create_shared_enumerator = (void*)return_null;
207 this->public.set.create_cdp_enumerator = (void*)return_null;
208 this->public.set.cache_cert = (void*)nop;
209 this->public.destroy = (void(*)(auth_info_wrapper_t*))destroy;
210
211 this->auth = auth;
212
213 return &this->public;
214 }
215