- added compution of all needed keys and also creation of needed
[strongswan.git] / Source / charon / config / configuration_manager.c
1 /**
2 * @file configuration.c
3 *
4 * @brief Configuration class used to store IKE_SA-configurations.
5 *
6 * Object of this type represents the configuration for all IKE_SA's and their child_sa's.
7 *
8 */
9
10 /*
11 * Copyright (C) 2005 Jan Hutter, Martin Willi
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #include <stdlib.h>
26
27 #include "configuration_manager.h"
28
29 #include <types.h>
30 #include <globals.h>
31 #include <utils/allocator.h>
32 #include <encoding/payloads/nonce_payload.h>
33 #include <encoding/payloads/proposal_substructure.h>
34 #include <encoding/payloads/ke_payload.h>
35 #include <encoding/payloads/transform_attribute.h>
36
37 typedef struct private_configuration_manager_t private_configuration_manager_t;
38
39 /**
40 * Private data of an configuration_t object
41 */
42 struct private_configuration_manager_t {
43
44 /**
45 * Public part
46 */
47 configuration_manager_t public;
48
49 /**
50 * Assigned logger object
51 */
52 logger_t *logger;
53 };
54
55 /**
56 * Implements function configuration_manager_t.get_remote_host.
57 */
58 static status_t get_remote_host(private_configuration_manager_t *this, char *name, host_t **host)
59 {
60 /*
61 * For testing purposes, hard coded host informations for two configurations are returned.
62 *
63 * Further improvements could store them in a linked list or hash table.
64 */
65
66 host_t *remote;
67 status_t status = SUCCESS;
68
69 if (strcmp(name, "pinflb30") == 0)
70 {
71 remote = host_create(AF_INET, "152.96.193.130", 500);
72 }
73 else if (strcmp(name, "pinflb31") == 0)
74 {
75 remote = host_create(AF_INET, "152.96.193.131", 500);
76 }
77 else if (strcmp(name, "localhost") == 0)
78 {
79 remote = host_create(AF_INET, "127.0.0.1", 500);
80 }
81 else
82 {
83 status = NOT_FOUND;
84 }
85 if ((status != NOT_FOUND) && (remote == NULL))
86 {
87 return OUT_OF_RES;
88 }
89
90 *host = remote;
91 return status;
92 }
93
94 /**
95 * Implements function configuration_manager_t.get_local_host.
96 */
97 static status_t get_local_host(private_configuration_manager_t *this, char *name, host_t **host)
98 {
99 /*
100 * For testing purposes, only the default route is returned for each configuration.
101 *
102 * Further improvements could store different local host informations in a linked list or hash table.
103 */
104 host_t *local;
105 local = host_create(AF_INET, "0.0.0.0", 0);
106 if (local == NULL)
107 {
108 return OUT_OF_RES;
109 }
110 *host = local;
111 return SUCCESS;
112 }
113
114 /**
115 * Implements function configuration_manager_t.get_dh_group_number.
116 */
117 static status_t get_dh_group_number(private_configuration_manager_t *this,char *name, u_int16_t *dh_group_number, u_int16_t priority)
118 {
119 /* Currently only two dh_group_numbers are supported for each configuration*/
120
121 if (priority == 1)
122 {
123 *dh_group_number = MODP_1024_BIT;
124 }
125 else
126 {
127 *dh_group_number = MODP_768_BIT;
128 }
129 return SUCCESS;
130 }
131
132 /**
133 * Implements function configuration_manager_t.get_proposals_for_host.
134 */
135 static status_t get_proposals_for_host(private_configuration_manager_t *this, host_t *host, iterator_t *iterator)
136 {
137 /*
138 * Currently the following hard coded proposal is created and returned for all hosts:
139 * - ENCR_AES_CBC 128Bit
140 * - PRF_HMAC_MD5 128Bit
141 * - AUTH_HMAC_MD5_96 128Bit
142 * - MODP_1024_BIT
143 */
144 proposal_substructure_t *proposal;
145 transform_substructure_t *transform;
146 transform_attribute_t *attribute;
147 status_t status;
148
149 proposal = proposal_substructure_create();
150 if (proposal == NULL)
151 {
152 return OUT_OF_RES;
153 }
154
155 proposal->set_proposal_number(proposal, 1);
156 proposal->set_protocol_id(proposal, 1);
157
158 /*
159 * Encryption Algorithm
160 */
161 transform = transform_substructure_create();
162 if (transform == NULL)
163 {
164 proposal->destroy(proposal);
165 return OUT_OF_RES;
166 }
167 status = proposal->add_transform_substructure(proposal, transform);
168 if (status != SUCCESS)
169 {
170 proposal->destroy(proposal);
171 return OUT_OF_RES;
172 }
173 transform->set_transform_type(transform, ENCRYPTION_ALGORITHM);
174 transform->set_transform_id(transform, ENCR_AES_CBC);
175
176 attribute = transform_attribute_create();
177 if (attribute == NULL)
178 {
179 proposal->destroy(proposal);
180 return OUT_OF_RES;
181 }
182 status = transform->add_transform_attribute(transform, attribute);
183 if (status != SUCCESS)
184 {
185 proposal->destroy(proposal);
186 return OUT_OF_RES;
187 }
188 attribute->set_attribute_type(attribute, KEY_LENGTH);
189 attribute->set_value(attribute, 16);
190
191 /*
192 * Pseudo-random Function
193 */
194 transform = transform_substructure_create();
195 if (transform == NULL)
196 {
197 proposal->destroy(proposal);
198 return OUT_OF_RES;
199 }
200 status = proposal->add_transform_substructure(proposal, transform);
201 if (status != SUCCESS)
202 {
203 proposal->destroy(proposal);
204 return OUT_OF_RES;
205 }
206 transform->set_transform_type(transform, PSEUDO_RANDOM_FUNCTION);
207 transform->set_transform_id(transform, PRF_HMAC_MD5);
208
209 attribute = transform_attribute_create();
210 if (attribute == NULL)
211 {
212 proposal->destroy(proposal);
213 return OUT_OF_RES;
214 }
215 status = transform->add_transform_attribute(transform, attribute);
216 if (status != SUCCESS)
217 {
218 proposal->destroy(proposal);
219 return OUT_OF_RES;
220 }
221 attribute->set_attribute_type(attribute, KEY_LENGTH);
222 attribute->set_value(attribute, 16);
223
224
225 /*
226 * Integrity Algorithm
227 */
228 transform = transform_substructure_create();
229 if (transform == NULL)
230 {
231 proposal->destroy(proposal);
232 return OUT_OF_RES;
233 }
234 status = proposal->add_transform_substructure(proposal, transform);
235 if (status != SUCCESS)
236 {
237 proposal->destroy(proposal);
238 return OUT_OF_RES;
239 }
240 transform->set_transform_type(transform, INTEGRITY_ALGORITHM);
241 transform->set_transform_id(transform, AUTH_HMAC_MD5_96);
242
243 attribute = transform_attribute_create();
244 if (attribute == NULL)
245 {
246 proposal->destroy(proposal);
247 return OUT_OF_RES;
248 }
249 status = transform->add_transform_attribute(transform, attribute);
250 if (status != SUCCESS)
251 {
252 proposal->destroy(proposal);
253 return OUT_OF_RES;
254 }
255 attribute->set_attribute_type(attribute, KEY_LENGTH);
256 attribute->set_value(attribute, 16);
257
258
259 /*
260 * Diffie-Hellman Group
261 */
262 transform = transform_substructure_create();
263 if (transform == NULL)
264 {
265 proposal->destroy(proposal);
266 return OUT_OF_RES;
267 }
268 status = proposal->add_transform_substructure(proposal, transform);
269 if (status != SUCCESS)
270 {
271 proposal->destroy(proposal);
272 return OUT_OF_RES;
273 }
274 transform->set_transform_type(transform, DIFFIE_HELLMAN_GROUP);
275 transform->set_transform_id(transform, MODP_1024_BIT);
276
277 iterator->insert_after(iterator, (void*)proposal);
278
279 return SUCCESS;
280 }
281
282 /**
283 * Implements function configuration_manager_t.select_proposals_for_host.
284 */
285 static status_t select_proposals_for_host(private_configuration_manager_t *this, host_t *host, iterator_t *in, iterator_t *out)
286 {
287 /* Currently the first suggested proposal is selected, cloned and then returned*/
288 status_t status;
289 proposal_substructure_t *first_suggested_proposal;
290 proposal_substructure_t *selected_proposal;
291
292 this->logger->log(this->logger,CONTROL | MORE, "Going to select first suggested proposal");
293 if (!in->has_next(in))
294 {
295 this->logger->log(this->logger,ERROR | MORE, "No proposal suggested");
296 /* no suggested proposal! */
297 return FAILED;
298 }
299
300 status = in->current(in,(void **) &first_suggested_proposal);
301 if (status != SUCCESS)
302 {
303 this->logger->log(this->logger,ERROR, "Fatal error: could not get first proposal from iterator");
304 return status;
305 }
306 status = first_suggested_proposal->clone(first_suggested_proposal,&selected_proposal);
307 if (status != SUCCESS)
308 {
309 this->logger->log(this->logger,ERROR, "Fatal error: could not clone proposal");
310 /* could not clone proposal */
311 return status;
312 }
313
314 status = out->insert_after(out,selected_proposal);
315 if (status != SUCCESS)
316 {
317 this->logger->log(this->logger,ERROR, "Fatal error: could not insert selected proposal in out iterator");
318 }
319 return status;
320 }
321
322 /**
323 * Implements function configuration_manager_t.check_selected_proposals_for_host.
324 */
325 static status_t check_selected_proposals_for_host (private_configuration_manager_t *this, host_t *host, iterator_t *proposals,bool *valid)
326 {
327 /*
328 * Currently the given proposals are not checked if they are valid for specific host!
329 *
330 * The first proposal is taken
331 */
332
333 this->logger->log(this->logger,CONTROL|MORE, "Going to check selected proposals");
334 return SUCCESS;
335 }
336
337 /**
338 * Implements function configuration_manager_t.is_dh_group_allowed_for_host.
339 */
340 static status_t is_dh_group_allowed_for_host(private_configuration_manager_t *this, host_t *host, diffie_hellman_group_t group, bool *allowed)
341 {
342 /*
343 * Only the two DH groups 768 and 1024 are supported for each configuration
344 */
345
346 if (group == MODP_768_BIT || group == MODP_1024_BIT)
347 {
348 *allowed = TRUE;
349 }
350 *allowed = FALSE;
351
352 this->logger->log(this->logger,CONTROL | MORE, "DH group %s is %s",mapping_find(diffie_hellman_group_m, group),(allowed)? "allowed" : "not allowed");
353 return SUCCESS;
354 }
355
356
357 /**
358 * Implements function destroy of configuration_t.
359 * See #configuration_s.destroy for description.
360 */
361 static status_t destroy(private_configuration_manager_t *this)
362 {
363 this->logger->log(this->logger,CONTROL | MORE, "Going to destroy configuration manager ");
364
365 this->logger->log(this->logger,CONTROL | MOST, "Destroy assigned logger");
366 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
367 allocator_free(this);
368 return SUCCESS;
369 }
370
371 /*
372 * Described in header-file
373 */
374 configuration_manager_t *configuration_manager_create()
375 {
376 private_configuration_manager_t *this = allocator_alloc_thing(private_configuration_manager_t);
377
378 if (this == NULL)
379 {
380 return NULL;
381 }
382
383 /* public functions */
384 this->public.destroy = (status_t(*)(configuration_manager_t*))destroy;
385 this->public.get_remote_host = (status_t(*)(configuration_manager_t*,char*,host_t**))get_remote_host;
386 this->public.get_local_host = (status_t(*)(configuration_manager_t*,char*,host_t**))get_local_host;
387 this->public.get_dh_group_number = (status_t(*)(configuration_manager_t*,char*,u_int16_t *, u_int16_t))get_dh_group_number;
388 this->public.get_proposals_for_host = (status_t(*)(configuration_manager_t*,host_t*,iterator_t*))get_proposals_for_host;
389 this->public.select_proposals_for_host = (status_t(*)(configuration_manager_t*,host_t*,iterator_t*,iterator_t*))select_proposals_for_host;
390 this->public.check_selected_proposals_for_host = (status_t (*) (configuration_manager_t *, host_t *, iterator_t *,bool *)) check_selected_proposals_for_host;
391 this->public.is_dh_group_allowed_for_host = (status_t(*)(configuration_manager_t*,host_t*,diffie_hellman_group_t,bool*)) is_dh_group_allowed_for_host;
392
393 /* private variables */
394 this->logger = global_logger_manager->create_logger(global_logger_manager,CONFIGURATION_MANAGER,NULL);
395
396 if (this->logger == NULL)
397 {
398 allocator_free(this);
399 return NULL;
400 }
401
402 return (&this->public);
403 }