IKEv1 XAuth: Moving the state change to IKE_CONNECTED until after XAuth exchanges...
[strongswan.git] / src / libcharon / sa / tasks / xauth_request.c
1
2 #include "xauth_request.h"
3
4 #include <daemon.h>
5 #include <hydra.h>
6 #include <encoding/payloads/cp_payload.h>
7
8 typedef struct private_xauth_request_t private_xauth_request_t;
9
10 enum {
11 XAUTH_STATUS_FAIL = 0,
12 XAUTH_STATUS_OK = 1,
13 };
14
15 /**
16 * Private members of a xauth_request_t task.
17 */
18 struct private_xauth_request_t {
19
20 /**
21 * Public methods and task_t interface.
22 */
23 xauth_request_t public;
24
25 /**
26 * Assigned IKE_SA.
27 */
28 ike_sa_t *ike_sa;
29
30 /**
31 * Are we the initiator?
32 */
33 bool initiator;
34
35 /**
36 * virtual ip
37 */
38 host_t *virtual_ip;
39
40 /**
41 * list of attributes requested and its handler, entry_t
42 */
43 linked_list_t *requested;
44
45 /**
46 * The current and next state of the task
47 */
48 enum {
49 TASK_XAUTH_INIT,
50 TASK_XAUTH_PASS_VERIFY,
51 TASK_XAUTH_COMPLETE,
52 } state, next_state;
53
54 /**
55 * The status of the XAuth request
56 */
57 status_t status;
58
59 /**
60 * The current auth config
61 */
62 auth_cfg_t *auth_cfg;
63
64 /**
65 * The received XAuth Status
66 */
67 u_int16_t xauth_status_data;
68
69 /**
70 * The received XAuth user name
71 */
72 chunk_t xauth_user_name;
73
74 /**
75 * The received XAuth user pass
76 */
77 chunk_t xauth_user_pass;
78
79 /**
80 * Whether the user name attribute was received
81 */
82 bool xauth_user_name_recv;
83
84 /**
85 * Whether the user pass attribute was received
86 */
87 bool xauth_user_pass_recv;
88
89 /**
90 * Whether the XAuth status attribute was received
91 */
92 bool xauth_status_recv;
93 };
94
95 /**
96 * Entry for a requested attribute and the requesting handler
97 */
98 typedef struct {
99 /** attribute requested */
100 configuration_attribute_type_t type;
101 /** handler requesting this attribute */
102 attribute_handler_t *handler;
103 } entry_t;
104
105 /**
106 * Get the first authentcation config from peer config
107 */
108 static auth_cfg_t *get_auth_cfg(private_xauth_request_t *this, bool local)
109 {
110 enumerator_t *enumerator;
111 auth_cfg_t *cfg = NULL;
112 peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
113
114 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg,
115 local);
116 enumerator->enumerate(enumerator, &cfg);
117 enumerator->destroy(enumerator);
118 return cfg;
119 }
120
121 /**
122 * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
123 */
124 static configuration_attribute_t *build_vip(host_t *vip)
125 {
126 configuration_attribute_type_t type;
127 chunk_t chunk, prefix;
128
129 if (vip->get_family(vip) == AF_INET)
130 {
131 type = INTERNAL_IP4_ADDRESS;
132 if (vip->is_anyaddr(vip))
133 {
134 chunk = chunk_empty;
135 }
136 else
137 {
138 chunk = vip->get_address(vip);
139 }
140 }
141 else
142 {
143 type = INTERNAL_IP6_ADDRESS;
144 if (vip->is_anyaddr(vip))
145 {
146 chunk = chunk_empty;
147 }
148 else
149 {
150 prefix = chunk_alloca(1);
151 *prefix.ptr = 64;
152 chunk = vip->get_address(vip);
153 chunk = chunk_cata("cc", chunk, prefix);
154 }
155 }
156 return configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE,
157 type, chunk);
158 }
159
160 /**
161 * Handle a received attribute as initiator
162 */
163 static void handle_attribute(private_xauth_request_t *this,
164 configuration_attribute_t *ca)
165 {
166 attribute_handler_t *handler = NULL;
167 enumerator_t *enumerator;
168 entry_t *entry;
169
170 /* find the handler which requested this attribute */
171 enumerator = this->requested->create_enumerator(this->requested);
172 while (enumerator->enumerate(enumerator, &entry))
173 {
174 if (entry->type == ca->get_type(ca))
175 {
176 handler = entry->handler;
177 this->requested->remove_at(this->requested, enumerator);
178 free(entry);
179 break;
180 }
181 }
182 enumerator->destroy(enumerator);
183
184 /* and pass it to the handle function */
185 handler = hydra->attributes->handle(hydra->attributes,
186 this->ike_sa->get_other_id(this->ike_sa), handler,
187 ca->get_type(ca), ca->get_chunk(ca));
188 if (handler)
189 {
190 this->ike_sa->add_configuration_attribute(this->ike_sa,
191 handler, ca->get_type(ca), ca->get_chunk(ca));
192 }
193 }
194
195 /**
196 * process a single configuration attribute
197 */
198 static void process_attribute(private_xauth_request_t *this,
199 configuration_attribute_t *ca)
200 {
201 host_t *ip;
202 chunk_t addr;
203 int family = AF_INET6;
204
205 switch (ca->get_type(ca))
206 {
207 case XAUTH_USER_NAME:
208 this->xauth_user_name = ca->get_chunk(ca);
209 this->xauth_user_name_recv = TRUE;
210 break;
211 case XAUTH_USER_PASSWORD:
212 this->xauth_user_pass = ca->get_chunk(ca);
213 this->xauth_user_pass_recv = TRUE;
214 break;
215 case XAUTH_STATUS:
216 this->xauth_status_data = ca->get_value(ca);
217 this->xauth_status_recv = TRUE;
218 break;
219 case INTERNAL_IP4_ADDRESS:
220 family = AF_INET;
221 /* fall */
222 case INTERNAL_IP6_ADDRESS:
223 {
224 addr = ca->get_chunk(ca);
225 if (addr.len == 0)
226 {
227 ip = host_create_any(family);
228 }
229 else
230 {
231 /* skip prefix byte in IPv6 payload*/
232 if (family == AF_INET6)
233 {
234 addr.len--;
235 }
236 ip = host_create_from_chunk(family, addr, 0);
237 }
238 if (ip)
239 {
240 DESTROY_IF(this->virtual_ip);
241 this->virtual_ip = ip;
242 }
243 break;
244 }
245 case INTERNAL_IP4_SERVER:
246 case INTERNAL_IP6_SERVER:
247 /* assume it's a Windows client if we see proprietary attributes */
248 this->ike_sa->enable_extension(this->ike_sa, EXT_MS_WINDOWS);
249 /* fall */
250 default:
251 {
252 if (this->initiator)
253 {
254 handle_attribute(this, ca);
255 }
256 }
257 }
258 }
259
260 /**
261 * Scan for configuration payloads and attributes
262 */
263 static status_t process_payloads(private_xauth_request_t *this, message_t *message)
264 {
265 enumerator_t *enumerator, *attributes;
266 payload_t *payload;
267
268 enumerator = message->create_payload_enumerator(message);
269 while (enumerator->enumerate(enumerator, &payload))
270 {
271 switch(payload->get_type(payload))
272 {
273 case CONFIGURATION:
274 case CONFIGURATION_V1:
275 {
276 cp_payload_t *cp = (cp_payload_t*)payload;
277 configuration_attribute_t *ca;
278
279 switch (cp->get_type(cp))
280 {
281 case CFG_REQUEST:
282 case CFG_REPLY:
283 case CFG_SET:
284 case CFG_ACK:
285 {
286 attributes = cp->create_attribute_enumerator(cp);
287 while (attributes->enumerate(attributes, &ca))
288 {
289 DBG2(DBG_IKE, "processing %N attribute",
290 configuration_attribute_type_names, ca->get_type(ca));
291 process_attribute(this, ca);
292 }
293 attributes->destroy(attributes);
294 break;
295 }
296 default:
297 DBG1(DBG_IKE, "ignoring %N config payload",
298 config_type_names, cp->get_type(cp));
299 break;
300 }
301
302 switch(this->state)
303 {
304 case TASK_XAUTH_INIT:
305 if(((cp->get_type(cp) != CFG_REQUEST) && (cp->get_type(cp) != CFG_REPLY)) ||
306 (this->xauth_user_name_recv != TRUE) ||
307 (this->xauth_user_pass_recv != TRUE))
308 {
309 /* Didn't get an XAuth message, assume we're a ConfigMode message, set state appropriately */
310 this->state = TASK_XAUTH_COMPLETE;
311 this->next_state = TASK_XAUTH_COMPLETE;
312 this->status = SUCCESS;
313 break;
314 }
315 this->next_state = TASK_XAUTH_PASS_VERIFY;
316 break;
317 case TASK_XAUTH_PASS_VERIFY:
318 if(((cp->get_type(cp) != CFG_SET) && (cp->get_type(cp) != CFG_ACK)) ||
319 (this->xauth_status_recv != TRUE))
320 {
321 DBG1(DBG_IKE, "Didn't receive XAuth status.");
322 return FAILED;
323 }
324 /* Set the return status for the build call */
325 if(cp->get_type(cp) != CFG_ACK)
326 {
327 this->status = (this->xauth_status_data == XAUTH_STATUS_OK ? SUCCESS : FAILED);
328 }
329 else
330 {
331 this->status = SUCCESS;
332 }
333 this->next_state = TASK_XAUTH_COMPLETE;
334 break;
335 default:
336 this->next_state = TASK_XAUTH_COMPLETE;
337 this->status = SUCCESS;
338 break;
339 }
340 }
341 default:
342 break;
343 }
344 }
345 enumerator->destroy(enumerator);
346 return NEED_MORE;
347 }
348
349 METHOD(task_t, build_i, status_t,
350 private_xauth_request_t *this, message_t *message)
351 {
352 cp_payload_t *cp = NULL;
353 chunk_t chunk = chunk_empty;
354 ike_version_t version;
355 payload_type_t cp_type;
356 payload_type_t ca_type;
357 host_t *vip;
358 peer_cfg_t *config;
359 enumerator_t *enumerator;
360 attribute_handler_t *handler;
361 configuration_attribute_type_t type;
362 chunk_t data;
363
364 version = this->ike_sa->get_version(this->ike_sa);
365 if(version == IKEV1)
366 {
367 if(!this->auth_cfg)
368 {
369 this->auth_cfg = get_auth_cfg(this, TRUE);
370 }
371 switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
372 {
373 case AUTH_CLASS_XAUTH_PSK:
374 case AUTH_CLASS_XAUTH_PUBKEY:
375 break;
376 default:
377 /* We aren't XAuth, so do nothing */
378 return SUCCESS;
379 }
380 cp_type = CONFIGURATION_V1;
381 ca_type = CONFIGURATION_ATTRIBUTE_V1;
382 }
383 else /* IKEv2 */
384 {
385 /* IKEv2 does not support XAuth, skip those states. */
386 this->state = TASK_XAUTH_COMPLETE;
387 if (message->get_message_id(message) == 1)
388 { /* in first IKE_AUTH only */
389 return NEED_MORE;
390 }
391 cp_type = CONFIGURATION;
392 ca_type = CONFIGURATION_ATTRIBUTE;
393 }
394 switch(this->state)
395 {
396 case TASK_XAUTH_INIT:
397 cp = cp_payload_create_type(cp_type, CFG_REQUEST);
398 cp->add_attribute(cp, configuration_attribute_create_chunk(
399 ca_type, XAUTH_USER_NAME, chunk));
400 cp->add_attribute(cp, configuration_attribute_create_chunk(
401 ca_type, XAUTH_USER_PASSWORD, chunk));
402 break;
403 case TASK_XAUTH_PASS_VERIFY:
404 cp = cp_payload_create_type(cp_type, CFG_SET);
405 cp->add_attribute(cp, configuration_attribute_create_value(
406 XAUTH_STATUS,
407 (this->status == FAILED ? XAUTH_STATUS_FAIL : XAUTH_STATUS_OK)));
408 break;
409 case TASK_XAUTH_COMPLETE:
410 /* ConfigMode stuff */
411 /* reuse virtual IP if we already have one */
412 vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
413 if (!vip)
414 {
415 config = this->ike_sa->get_peer_cfg(this->ike_sa);
416 vip = config->get_virtual_ip(config);
417 }
418 if (vip)
419 {
420 cp = cp_payload_create_type(cp_type, CFG_REQUEST);
421 cp->add_attribute(cp, build_vip(vip));
422 }
423
424 enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
425 this->ike_sa->get_other_id(this->ike_sa), vip);
426 while (enumerator->enumerate(enumerator, &handler, &type, &data))
427 {
428 configuration_attribute_t *ca;
429 entry_t *entry;
430
431 /* create configuration attribute */
432 DBG2(DBG_IKE, "building %N attribute",
433 configuration_attribute_type_names, type);
434 ca = configuration_attribute_create_chunk(ca_type,
435 type, data);
436 if (!cp)
437 {
438 cp = cp_payload_create_type(cp_type, CFG_REQUEST);
439 }
440 cp->add_attribute(cp, ca);
441
442 /* save handler along with requested type */
443 entry = malloc_thing(entry_t);
444 entry->type = type;
445 entry->handler = handler;
446
447 this->requested->insert_last(this->requested, entry);
448 }
449 enumerator->destroy(enumerator);
450
451 break;
452 default:
453 return FAILED;
454
455 }
456 /* Add the payloads into the message */
457 if(cp)
458 {
459 message->add_payload(message, (payload_t *)cp);
460 }
461
462 return NEED_MORE;
463 }
464
465 METHOD(task_t, process_r, status_t,
466 private_xauth_request_t *this, message_t *message)
467 {
468 ike_version_t version;
469 payload_type_t cp_type;
470
471 version = this->ike_sa->get_version(this->ike_sa);
472 if(version == IKEV1)
473 {
474 if(!this->auth_cfg)
475 {
476 this->auth_cfg = get_auth_cfg(this, TRUE);
477 }
478 switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
479 {
480 case AUTH_CLASS_XAUTH_PSK:
481 case AUTH_CLASS_XAUTH_PUBKEY:
482 this->state = TASK_XAUTH_INIT;
483 break;
484 default:
485 /* We aren't XAuth, so do we should expect ConfigMode stuff */
486 this->state = TASK_XAUTH_COMPLETE;
487 }
488 cp_type = CONFIGURATION_V1;
489 }
490 else /* IKEv2 */
491 {
492 /* IKEv2 does not support XAuth, skip those states. */
493 this->state = TASK_XAUTH_COMPLETE;
494 if (message->get_message_id(message) == 1)
495 { /* in first IKE_AUTH only */
496 return NEED_MORE;
497 }
498 cp_type = CONFIGURATION;
499 }
500
501 return process_payloads(this, message);
502 }
503
504 METHOD(task_t, build_r, status_t,
505 private_xauth_request_t *this, message_t *message)
506 {
507 chunk_t user_name = chunk_from_chars('j', 'o', 's', 't');
508 chunk_t user_pass = chunk_from_chars('j', 'o', 's', 't');
509 status_t status;
510 cp_payload_t *cp = NULL;
511 payload_type_t cp_type = CONFIGURATION;
512 payload_type_t ca_type = CONFIGURATION_ATTRIBUTE;
513 ike_version_t version;
514 identification_t *id;
515 enumerator_t *enumerator;
516 configuration_attribute_type_t type;
517 chunk_t value;
518 host_t *vip = NULL;
519 peer_cfg_t *config;
520
521 if(this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
522 {
523 return NEED_MORE;
524 }
525 version = this->ike_sa->get_version(this->ike_sa);
526 if(version == IKEV1)
527 {
528 if(!this->auth_cfg)
529 {
530 this->auth_cfg = get_auth_cfg(this, TRUE);
531 }
532 switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
533 {
534 case AUTH_CLASS_XAUTH_PSK:
535 case AUTH_CLASS_XAUTH_PUBKEY:
536 break;
537 default:
538 this->state = TASK_XAUTH_COMPLETE;
539 return SUCCESS;
540 }
541 cp_type = CONFIGURATION_V1;
542 ca_type = CONFIGURATION_ATTRIBUTE_V1;
543 }
544
545 switch(this->state)
546 {
547 case TASK_XAUTH_INIT:
548 /* TODO-IKEv1: Fetch the user/pass from an authenticator */
549 cp = cp_payload_create_type(cp_type, CFG_REPLY);
550 cp->add_attribute(cp, configuration_attribute_create_chunk(
551 ca_type, XAUTH_USER_NAME, user_name));
552 cp->add_attribute(cp, configuration_attribute_create_chunk(
553 ca_type, XAUTH_USER_PASSWORD, user_pass));
554 chunk_clear(&user_name);
555 chunk_clear(&user_pass);
556
557 this->state = TASK_XAUTH_PASS_VERIFY;
558 status = NEED_MORE;
559 break;
560 case TASK_XAUTH_PASS_VERIFY:
561 cp = cp_payload_create_type(cp_type, CFG_ACK);
562 cp->add_attribute(cp, configuration_attribute_create_value(
563 XAUTH_STATUS, XAUTH_STATUS_OK));
564 status = this->status;
565 this->state = TASK_XAUTH_COMPLETE;
566 break;
567 case TASK_XAUTH_COMPLETE:
568 id = this->ike_sa->get_other_eap_id(this->ike_sa);
569
570 config = this->ike_sa->get_peer_cfg(this->ike_sa);
571 if (this->virtual_ip)
572 {
573 DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
574 if (config->get_pool(config))
575 {
576 vip = hydra->attributes->acquire_address(hydra->attributes,
577 config->get_pool(config), id, this->virtual_ip);
578 }
579 if (vip == NULL)
580 {
581 DBG1(DBG_IKE, "no virtual IP found, sending %N",
582 notify_type_names, INTERNAL_ADDRESS_FAILURE);
583 message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
584 chunk_empty);
585 return SUCCESS;
586 }
587 DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
588 this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
589
590 cp = cp_payload_create_type(cp_type, CFG_REPLY);
591 cp->add_attribute(cp, build_vip(vip));
592 }
593
594 /* query registered providers for additional attributes to include */
595 enumerator = hydra->attributes->create_responder_enumerator(
596 hydra->attributes, config->get_pool(config), id, vip);
597 while (enumerator->enumerate(enumerator, &type, &value))
598 {
599 if (!cp)
600 {
601 cp = cp_payload_create_type(cp_type, CFG_REPLY);
602 }
603 DBG2(DBG_IKE, "building %N attribute",
604 configuration_attribute_type_names, type);
605 cp->add_attribute(cp,
606 configuration_attribute_create_chunk(ca_type,
607 type, value));
608 }
609 enumerator->destroy(enumerator);
610 status = SUCCESS;
611 break;
612 default:
613 return FAILED;
614 }
615 if(status == SUCCESS)
616 {
617 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
618 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
619 }
620 return status;
621 }
622
623 METHOD(task_t, process_i, status_t,
624 private_xauth_request_t *this, message_t *message)
625 {
626 status_t status;
627 if (((this->ike_sa->get_version(this->ike_sa) == IKEV2) &&
628 (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)) ||
629 (this->ike_sa->get_version(this->ike_sa) == IKEV1))
630 { /* in last IKE_AUTH exchange */
631
632 status = process_payloads(this, message);
633 this->state = this->next_state;
634
635 if (this->virtual_ip)
636 {
637 this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
638 }
639 if(this->state == TASK_XAUTH_COMPLETE)
640 {
641 if(this->status == SUCCESS)
642 {
643 this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
644 charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
645 }
646
647 return this->status;
648 }
649 return status;
650 }
651 return NEED_MORE;
652
653 }
654
655 METHOD(task_t, get_type, task_type_t,
656 private_xauth_request_t *this)
657 {
658 return TASK_XAUTH_REQUEST;
659 }
660
661 METHOD(task_t, migrate, void,
662 private_xauth_request_t *this, ike_sa_t *ike_sa)
663 {
664 DESTROY_IF(this->virtual_ip);
665
666 this->ike_sa = ike_sa;
667 this->virtual_ip = NULL;
668 this->requested->destroy_function(this->requested, free);
669 this->requested = linked_list_create();
670 }
671
672 METHOD(task_t, destroy, void,
673 private_xauth_request_t *this)
674 {
675 DESTROY_IF(this->virtual_ip);
676 this->requested->destroy_function(this->requested, free);
677 free(this);
678 }
679
680 METHOD(task_t, swap_initiator, void,
681 private_xauth_request_t *this)
682 {
683 if(this->initiator)
684 {
685 this->public.task.build = _build_r;
686 this->public.task.process = _process_r;
687 this->initiator = FALSE;
688 }
689 else
690 {
691 this->public.task.build = _build_i;
692 this->public.task.process = _process_i;
693 this->initiator = TRUE;
694 }
695 }
696
697 /*
698 * Described in header.
699 */
700 xauth_request_t *xauth_request_create(ike_sa_t *ike_sa, bool initiator)
701 {
702 private_xauth_request_t *this;
703
704 INIT(this,
705 .public = {
706 .task = {
707 .get_type = _get_type,
708 .migrate = _migrate,
709 .destroy = _destroy,
710 .swap_initiator = _swap_initiator,
711 },
712 },
713 .initiator = initiator,
714 .ike_sa = ike_sa,
715 .requested = linked_list_create(),
716 .state = TASK_XAUTH_INIT,
717 .next_state = TASK_XAUTH_INIT,
718 .xauth_status_data = XAUTH_STATUS_FAIL,
719 .xauth_user_name = chunk_empty,
720 .xauth_user_pass = chunk_empty,
721 .xauth_user_name_recv = FALSE,
722 .xauth_user_pass_recv = FALSE,
723 .xauth_status_recv = FALSE,
724 );
725
726 if (initiator)
727 {
728 this->public.task.build = _build_i;
729 this->public.task.process = _process_i;
730 }
731 else
732 {
733 this->public.task.build = _build_r;
734 this->public.task.process = _process_r;
735 }
736
737 return &this->public;
738 }