4ab486ac7bb13a32371c58911e2385426bbbbf72
[strongswan.git] / src / charon / sa / tasks / ike_auth.c
1 /**
2 * @file ike_auth.c
3 *
4 * @brief Implementation of the ike_auth task.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2007 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include "ike_auth.h"
25
26 #include <string.h>
27
28 #include <daemon.h>
29 #include <crypto/diffie_hellman.h>
30 #include <encoding/payloads/id_payload.h>
31 #include <encoding/payloads/auth_payload.h>
32 #include <encoding/payloads/nonce_payload.h>
33
34
35 typedef struct private_ike_auth_t private_ike_auth_t;
36
37 /**
38 * Private members of a ike_auth_t task.
39 */
40 struct private_ike_auth_t {
41
42 /**
43 * Public methods and task_t interface.
44 */
45 ike_auth_t public;
46
47 /**
48 * Assigned IKE_SA.
49 */
50 ike_sa_t *ike_sa;
51
52 /**
53 * Are we the initiator?
54 */
55 bool initiator;
56
57 /**
58 * Nonce chosen by us in ike_init
59 */
60 chunk_t my_nonce;
61
62 /**
63 * Nonce chosen by peer in ike_init
64 */
65 chunk_t other_nonce;
66
67 /**
68 * IKE_SA_INIT message sent by us
69 */
70 packet_t *my_packet;
71
72 /**
73 * IKE_SA_INIT message sent by peer
74 */
75 packet_t *other_packet;
76
77 /**
78 * authenticator to authenticate us
79 */
80 authenticator_t *my_auth;
81
82 /**
83 * authenticator to authenticate peer
84 */
85 authenticator_t *other_auth;
86
87 /**
88 * has the peer been authenticated successfully?
89 */
90 bool peer_authenticated;
91 };
92
93 /**
94 * build the payloads for the message
95 */
96 static status_t build_payloads(private_ike_auth_t *this, message_t *message)
97 {
98 authenticator_t *auth;
99 auth_payload_t *auth_payload;
100 id_payload_t *id_payload;
101 chunk_t ike_sa_init;
102 identification_t *me, *other;
103 policy_t *policy;
104 auth_method_t method = AUTH_RSA;
105 status_t status;
106
107 /* add own ID payload */
108 me = this->ike_sa->get_my_id(this->ike_sa);
109 other = this->ike_sa->get_other_id(this->ike_sa);
110
111
112 /* create own authenticator and add auth payload */
113 policy = this->ike_sa->get_policy(this->ike_sa);
114 if (!policy)
115 {
116 SIG(IKE_UP_FAILED, "no acceptable policy found");
117 return FAILED;
118 }
119
120 method = policy->get_auth_method(policy);
121 if (me->contains_wildcards(me))
122 {
123 me = policy->get_my_id(policy);
124 if (me->contains_wildcards(me))
125 {
126 SIG(IKE_UP_FAILED, "negotiation of own ID failed");
127 return FAILED;
128 }
129 this->ike_sa->set_my_id(this->ike_sa, me);
130 }
131
132 id_payload = id_payload_create_from_identification(this->initiator, me);
133 message->add_payload(message, (payload_t*)id_payload);
134
135 /* as initiator, include other ID if it does not contain wildcards */
136 if (this->initiator && !other->contains_wildcards(other))
137 {
138 id_payload = id_payload_create_from_identification(FALSE, other);
139 message->add_payload(message, (payload_t*)id_payload);
140 }
141
142 auth = authenticator_create(this->ike_sa, method);
143 if (auth == NULL)
144 {
145 SIG(IKE_UP_FAILED, "configured authentication method %N not supported",
146 auth_method_names, method);
147 return FAILED;
148 }
149
150 ike_sa_init = this->my_packet->get_data(this->my_packet);
151 status = auth->build(auth, ike_sa_init, this->other_nonce, &auth_payload);
152 auth->destroy(auth);
153 if (status != SUCCESS)
154 {
155 SIG(IKE_UP_FAILED, "generating authentication data failed");
156 return FAILED;
157 }
158 message->add_payload(message, (payload_t*)auth_payload);
159
160 return SUCCESS;
161 }
162
163 /**
164 * process payloads from message
165 */
166 static void process_payloads(private_ike_auth_t *this, message_t *message)
167 {
168 iterator_t *iterator;
169 payload_t *payload;
170 payload_type_t type;
171 identification_t *idi = NULL, *idr = NULL;
172 auth_payload_t *auth_payload = NULL;
173 authenticator_t *auth;
174 auth_method_t auth_method;
175 status_t status;
176
177 iterator = message->get_payload_iterator(message);
178 while (iterator->iterate(iterator, (void**)&payload))
179 {
180 type = payload->get_type(payload);
181 switch (type)
182 {
183 case ID_INITIATOR:
184 {
185 id_payload_t *id_payload = (id_payload_t*)payload;
186 idi = id_payload->get_identification(id_payload);
187 break;
188 }
189 case ID_RESPONDER:
190 {
191 id_payload_t *id_payload = (id_payload_t*)payload;
192 idr = id_payload->get_identification(id_payload);
193 break;
194 }
195 case AUTHENTICATION:
196 {
197 auth_payload = (auth_payload_t*)payload;
198 break;
199 }
200 default:
201 break;
202 }
203 }
204 iterator->destroy(iterator);
205
206 /* apply IDs */
207 if ((this->initiator && idr == NULL) || (!this->initiator && idi == NULL))
208 {
209 SIG(IKE_UP_FAILED, "ID payload missing in message");
210 DESTROY_IF(idr); DESTROY_IF(idi);
211 return;
212 }
213
214 if (this->initiator)
215 {
216 this->ike_sa->set_other_id(this->ike_sa, idr);
217 }
218 else
219 {
220 if (idr)
221 {
222 this->ike_sa->set_my_id(this->ike_sa, idr);
223 }
224 this->ike_sa->set_other_id(this->ike_sa, idi);
225 }
226
227 /* verify auth payload */
228 if (auth_payload == NULL)
229 {
230 SIG(IKE_UP_FAILED, "AUTH payload missing in message");
231 return;
232 }
233
234 auth_method = auth_payload->get_auth_method(auth_payload);
235 auth = authenticator_create(this->ike_sa, auth_method);
236 if (auth == NULL)
237 {
238 SIG(IKE_UP_FAILED, "authentication method %N used by %D not "
239 "supported", auth_method_names, auth_method,
240 this->ike_sa->get_other_id(this->ike_sa));
241 return;
242 }
243 status = auth->verify(auth, this->other_packet->get_data(this->other_packet),
244 this->my_nonce, auth_payload);
245 auth->destroy(auth);
246 if (status != SUCCESS)
247 {
248 SIG(IKE_UP_FAILED, "authentication of %D using %N failed",
249 this->ike_sa->get_other_id(this->ike_sa),
250 auth_method_names, auth_method);
251 return;
252 }
253 this->peer_authenticated = TRUE;
254 }
255
256 /**
257 * collect the needed information in the IKE_SA_INIT exchange from our message
258 */
259 static status_t collect_my_init_data(private_ike_auth_t *this, message_t *message)
260 {
261 nonce_payload_t *nonce;
262
263 /* get the nonce that was generated in ike_init */
264 nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
265 if (nonce == NULL)
266 {
267 return FAILED;
268 }
269 this->my_nonce = nonce->get_nonce(nonce);
270
271 /* pre-generate the message, so we can store it for us */
272 if (this->ike_sa->generate_message(this->ike_sa, message,
273 &this->my_packet) != SUCCESS)
274 {
275 return FAILED;
276 }
277 return NEED_MORE;
278 }
279
280 /**
281 * collect the needed information in the IKE_SA_INIT exchange from others message
282 */
283 static status_t collect_other_init_data(private_ike_auth_t *this, message_t *message)
284 {
285 /* we collect the needed information in the IKE_SA_INIT exchange */
286 nonce_payload_t *nonce;
287
288 /* get the nonce that was generated in ike_init */
289 nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
290 if (nonce == NULL)
291 {
292 return FAILED;
293 }
294 this->other_nonce = nonce->get_nonce(nonce);
295
296 /* pre-generate the message, so we can store it for us */
297 this->other_packet = message->get_packet(message);
298 return NEED_MORE;
299 }
300
301 /**
302 * Implementation of task_t.build for initiator
303 */
304 static status_t build_i(private_ike_auth_t *this, message_t *message)
305 {
306 if (message->get_exchange_type(message) == IKE_SA_INIT)
307 {
308 return collect_my_init_data(this, message);
309 }
310
311 if (build_payloads(this, message) == SUCCESS)
312 {
313 return NEED_MORE;
314 }
315 return FAILED;
316 }
317
318 /**
319 * Implementation of task_t.process for initiator
320 */
321 static status_t process_r(private_ike_auth_t *this, message_t *message)
322 {
323 if (message->get_exchange_type(message) == IKE_SA_INIT)
324 {
325 return collect_other_init_data(this, message);
326 }
327
328 process_payloads(this, message);
329
330 return NEED_MORE;
331 }
332
333 /**
334 * Implementation of task_t.build for responder
335 */
336 static status_t build_r(private_ike_auth_t *this, message_t *message)
337 {
338 if (message->get_exchange_type(message) == IKE_SA_INIT)
339 {
340 return collect_my_init_data(this, message);
341 }
342
343 if (this->peer_authenticated && build_payloads(this, message) == SUCCESS)
344 {
345 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
346 SIG(IKE_UP_SUCCESS, "IKE_SA established between %D[%H]...[%H]%D",
347 this->ike_sa->get_my_id(this->ike_sa),
348 this->ike_sa->get_my_host(this->ike_sa),
349 this->ike_sa->get_other_host(this->ike_sa),
350 this->ike_sa->get_other_id(this->ike_sa));
351 return SUCCESS;
352 }
353 message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
354 return FAILED;
355 }
356
357 /**
358 * Implementation of task_t.process for initiator
359 */
360 static status_t process_i(private_ike_auth_t *this, message_t *message)
361 {
362 iterator_t *iterator;
363 payload_t *payload;
364
365 if (message->get_exchange_type(message) == IKE_SA_INIT)
366 {
367 return collect_other_init_data(this, message);
368 }
369
370 iterator = message->get_payload_iterator(message);
371 while (iterator->iterate(iterator, (void**)&payload))
372 {
373 if (payload->get_type(payload) == NOTIFY)
374 {
375 notify_payload_t *notify = (notify_payload_t*)payload;
376 notify_type_t type = notify->get_notify_type(notify);
377
378 switch (type)
379 {
380 case NO_PROPOSAL_CHOSEN:
381 case SINGLE_PAIR_REQUIRED:
382 case NO_ADDITIONAL_SAS:
383 case INTERNAL_ADDRESS_FAILURE:
384 case FAILED_CP_REQUIRED:
385 case TS_UNACCEPTABLE:
386 case INVALID_SELECTORS:
387 /* these are errors, but are not critical as only the
388 * CHILD_SA won't get build, but IKE_SA establishes anyway */
389 DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
390 notify_type_names, type);
391 iterator->destroy(iterator);
392 return SUCCESS;
393 default:
394 {
395 if (type < 16383)
396 {
397 DBG1(DBG_IKE, "received %N notify error",
398 notify_type_names, type);
399 iterator->destroy(iterator);
400 return FAILED;
401 }
402 }
403 }
404 }
405 }
406 iterator->destroy(iterator);
407
408 process_payloads(this, message);
409
410 if (this->peer_authenticated)
411 {
412 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
413 SIG(IKE_UP_SUCCESS, "IKE_SA established between %D[%H]...[%H]%D",
414 this->ike_sa->get_my_id(this->ike_sa),
415 this->ike_sa->get_my_host(this->ike_sa),
416 this->ike_sa->get_other_host(this->ike_sa),
417 this->ike_sa->get_other_id(this->ike_sa));
418 return SUCCESS;
419 }
420 return FAILED;
421 }
422
423 /**
424 * Implementation of task_t.get_type
425 */
426 static task_type_t get_type(private_ike_auth_t *this)
427 {
428 return IKE_AUTHENTICATE;
429 }
430
431 /**
432 * Implementation of task_t.migrate
433 */
434 static void migrate(private_ike_auth_t *this, ike_sa_t *ike_sa)
435 {
436 chunk_free(&this->my_nonce);
437 chunk_free(&this->other_nonce);
438 DESTROY_IF(this->my_packet);
439 DESTROY_IF(this->other_packet);
440 DESTROY_IF(this->my_auth);
441 DESTROY_IF(this->other_auth);
442 this->my_packet = NULL;
443 this->other_packet = NULL;
444 this->my_auth = NULL;
445 this->other_auth = NULL;
446 this->peer_authenticated = FALSE;
447 this->ike_sa = ike_sa;
448 }
449
450 /**
451 * Implementation of task_t.destroy
452 */
453 static void destroy(private_ike_auth_t *this)
454 {
455 chunk_free(&this->my_nonce);
456 chunk_free(&this->other_nonce);
457 DESTROY_IF(this->my_packet);
458 DESTROY_IF(this->other_packet);
459 DESTROY_IF(this->my_auth);
460 DESTROY_IF(this->other_auth);
461 free(this);
462 }
463
464 /*
465 * Described in header.
466 */
467 ike_auth_t *ike_auth_create(ike_sa_t *ike_sa, bool initiator)
468 {
469 private_ike_auth_t *this = malloc_thing(private_ike_auth_t);
470
471 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
472 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
473 this->public.task.destroy = (void(*)(task_t*))destroy;
474
475 if (initiator)
476 {
477 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
478 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
479 }
480 else
481 {
482 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
483 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
484 }
485
486 this->ike_sa = ike_sa;
487 this->initiator = initiator;
488 this->my_nonce = chunk_empty;
489 this->other_nonce = chunk_empty;
490 this->my_packet = NULL;
491 this->other_packet = NULL;
492 this->my_auth = NULL;
493 this->other_auth = NULL;
494 this->peer_authenticated = FALSE;
495
496 return &this->public;
497 }