1c9f115b260409f4c0060f02eee552100fc4bf43
[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 DBG1(DBG_IKE, "%s: state %d", __func__, this->state);
365
366 version = this->ike_sa->get_version(this->ike_sa);
367 if(version == IKEV1)
368 {
369 if(this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
370 {
371 DBG1(DBG_IKE, "!!!!!!!!!!!!!!!!!!!!!!!!!NEED_MORE!!!!!!!!!!!!!!!!!!!!!");
372 return NEED_MORE;
373 }
374
375 if(!this->auth_cfg)
376 {
377 this->auth_cfg = get_auth_cfg(this, TRUE);
378 }
379 switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
380 {
381 case AUTH_CLASS_XAUTH_PSK:
382 case AUTH_CLASS_XAUTH_PUBKEY:
383 break;
384 default:
385 /* We aren't XAuth, so do nothing */
386 DBG1(DBG_IKE, "!!!!!!!!!!!!!!!!!!!!!!!!!SUCCESS!!!!!!!!!!!!!!!!!!!!!");
387 return SUCCESS;
388 }
389 cp_type = CONFIGURATION_V1;
390 ca_type = CONFIGURATION_ATTRIBUTE_V1;
391 }
392 else /* IKEv2 */
393 {
394 /* IKEv2 does not support XAuth, skip those states. */
395 this->state = TASK_XAUTH_COMPLETE;
396 if (message->get_message_id(message) == 1)
397 { /* in first IKE_AUTH only */
398 DBG1(DBG_IKE, "!!!!!!!!!!!!!!!!!!!!!!!!!NEED_MORE!!!!!!!!!!!!!!!!!!!!!");
399 return NEED_MORE;
400 }
401 cp_type = CONFIGURATION;
402 ca_type = CONFIGURATION_ATTRIBUTE;
403 }
404 switch(this->state)
405 {
406 case TASK_XAUTH_INIT:
407 cp = cp_payload_create_type(cp_type, CFG_REQUEST);
408 cp->add_attribute(cp, configuration_attribute_create_chunk(
409 ca_type, XAUTH_USER_NAME, chunk));
410 cp->add_attribute(cp, configuration_attribute_create_chunk(
411 ca_type, XAUTH_USER_PASSWORD, chunk));
412 break;
413 case TASK_XAUTH_PASS_VERIFY:
414 cp = cp_payload_create_type(cp_type, CFG_SET);
415 cp->add_attribute(cp, configuration_attribute_create_value(
416 XAUTH_STATUS,
417 (this->status == FAILED ? XAUTH_STATUS_FAIL : XAUTH_STATUS_OK)));
418 break;
419 case TASK_XAUTH_COMPLETE:
420 /* ConfigMode stuff */
421 /* reuse virtual IP if we already have one */
422 vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
423 if (!vip)
424 {
425 config = this->ike_sa->get_peer_cfg(this->ike_sa);
426 vip = config->get_virtual_ip(config);
427 }
428 if (vip)
429 {
430 cp = cp_payload_create_type(cp_type, CFG_REQUEST);
431 cp->add_attribute(cp, build_vip(vip));
432 }
433
434 enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
435 this->ike_sa->get_other_id(this->ike_sa), vip);
436 while (enumerator->enumerate(enumerator, &handler, &type, &data))
437 {
438 configuration_attribute_t *ca;
439 entry_t *entry;
440
441 /* create configuration attribute */
442 DBG2(DBG_IKE, "building %N attribute",
443 configuration_attribute_type_names, type);
444 ca = configuration_attribute_create_chunk(ca_type,
445 type, data);
446 if (!cp)
447 {
448 cp = cp_payload_create_type(cp_type, CFG_REQUEST);
449 }
450 cp->add_attribute(cp, ca);
451
452 /* save handler along with requested type */
453 entry = malloc_thing(entry_t);
454 entry->type = type;
455 entry->handler = handler;
456
457 this->requested->insert_last(this->requested, entry);
458 }
459 enumerator->destroy(enumerator);
460
461 break;
462 default:
463 DBG1(DBG_IKE, "!!!!!!!!!!!!!!!!!!!!!!!!!FAILED!!!!!!!!!!!!!!!!!!!!!");
464 return FAILED;
465
466 }
467 /* Add the payloads into the message */
468 if(cp)
469 {
470 message->add_payload(message, (payload_t *)cp);
471 }
472
473 DBG1(DBG_IKE, "!!!!!!!!!!!!!!!!!!!!!!!!!NEED_MORE!!!!!!!!!!!!!!!!!!!!!");
474 return NEED_MORE;
475 }
476
477 METHOD(task_t, process_r, status_t,
478 private_xauth_request_t *this, message_t *message)
479 {
480 ike_version_t version;
481 payload_type_t cp_type;
482 DBG1(DBG_IKE, "%s: state %d", __func__, this->state);
483
484 version = this->ike_sa->get_version(this->ike_sa);
485 if(version == IKEV1)
486 {
487 if(this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
488 {
489 return NEED_MORE;
490 }
491 if(!this->auth_cfg)
492 {
493 this->auth_cfg = get_auth_cfg(this, TRUE);
494 }
495 switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
496 {
497 case AUTH_CLASS_XAUTH_PSK:
498 case AUTH_CLASS_XAUTH_PUBKEY:
499 break;
500 default:
501 /* We aren't XAuth, so do we should expect ConfigMode stuff */
502 return SUCCESS;
503 }
504 cp_type = CONFIGURATION_V1;
505 }
506 else /* IKEv2 */
507 {
508 /* IKEv2 does not support XAuth, skip those states. */
509 this->state = TASK_XAUTH_COMPLETE;
510 if (message->get_message_id(message) == 1)
511 { /* in first IKE_AUTH only */
512 return NEED_MORE;
513 }
514 cp_type = CONFIGURATION;
515 }
516
517 return process_payloads(this, message);
518 }
519
520 METHOD(task_t, build_r, status_t,
521 private_xauth_request_t *this, message_t *message)
522 {
523 chunk_t user_name = chunk_from_chars('j', 'o', 's', 't');
524 chunk_t user_pass = chunk_from_chars('j', 'o', 's', 't');
525 status_t status;
526 cp_payload_t *cp = NULL;
527 payload_type_t cp_type = CONFIGURATION;
528 payload_type_t ca_type = CONFIGURATION_ATTRIBUTE;
529 ike_version_t version;
530 identification_t *id;
531 enumerator_t *enumerator;
532 configuration_attribute_type_t type;
533 chunk_t value;
534 host_t *vip = NULL;
535 peer_cfg_t *config;
536
537 DBG1(DBG_IKE, "%s: state %d", __func__, this->state);
538 if(this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
539 {
540 return NEED_MORE;
541 }
542 version = this->ike_sa->get_version(this->ike_sa);
543 if(version == IKEV1)
544 {
545 if(!this->auth_cfg)
546 {
547 this->auth_cfg = get_auth_cfg(this, TRUE);
548 }
549 switch((uintptr_t)this->auth_cfg->get(this->auth_cfg, AUTH_RULE_AUTH_CLASS))
550 {
551 case AUTH_CLASS_XAUTH_PSK:
552 case AUTH_CLASS_XAUTH_PUBKEY:
553 break;
554 default:
555 this->state = TASK_XAUTH_COMPLETE;
556 return SUCCESS;
557 }
558 cp_type = CONFIGURATION_V1;
559 ca_type = CONFIGURATION_ATTRIBUTE_V1;
560 }
561
562 switch(this->state)
563 {
564 case TASK_XAUTH_INIT:
565 /* TODO-IKEv1: Fetch the user/pass from an authenticator */
566 cp = cp_payload_create_type(cp_type, CFG_REPLY);
567 cp->add_attribute(cp, configuration_attribute_create_chunk(
568 ca_type, XAUTH_USER_NAME, user_name));
569 cp->add_attribute(cp, configuration_attribute_create_chunk(
570 ca_type, XAUTH_USER_PASSWORD, user_pass));
571 chunk_clear(&user_name);
572 chunk_clear(&user_pass);
573
574 this->state = TASK_XAUTH_PASS_VERIFY;
575 status = NEED_MORE;
576 break;
577 case TASK_XAUTH_PASS_VERIFY:
578 cp = cp_payload_create_type(cp_type, CFG_ACK);
579 cp->add_attribute(cp, configuration_attribute_create_value(
580 XAUTH_STATUS, XAUTH_STATUS_OK));
581 status = this->status;
582 this->state = TASK_XAUTH_COMPLETE;
583 break;
584 case TASK_XAUTH_COMPLETE:
585 id = this->ike_sa->get_other_eap_id(this->ike_sa);
586
587 config = this->ike_sa->get_peer_cfg(this->ike_sa);
588 if (this->virtual_ip)
589 {
590 DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
591 if (config->get_pool(config))
592 {
593 vip = hydra->attributes->acquire_address(hydra->attributes,
594 config->get_pool(config), id, this->virtual_ip);
595 }
596 if (vip == NULL)
597 {
598 DBG1(DBG_IKE, "no virtual IP found, sending %N",
599 notify_type_names, INTERNAL_ADDRESS_FAILURE);
600 message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
601 chunk_empty);
602 return SUCCESS;
603 }
604 DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
605 this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
606
607 cp = cp_payload_create_type(cp_type, CFG_REPLY);
608 cp->add_attribute(cp, build_vip(vip));
609 }
610
611 /* query registered providers for additional attributes to include */
612 enumerator = hydra->attributes->create_responder_enumerator(
613 hydra->attributes, config->get_pool(config), id, vip);
614 while (enumerator->enumerate(enumerator, &type, &value))
615 {
616 if (!cp)
617 {
618 cp = cp_payload_create_type(cp_type, CFG_REPLY);
619 }
620 DBG2(DBG_IKE, "building %N attribute",
621 configuration_attribute_type_names, type);
622 cp->add_attribute(cp,
623 configuration_attribute_create_chunk(ca_type,
624 type, value));
625 }
626 enumerator->destroy(enumerator);
627 status = SUCCESS;
628 break;
629 default:
630 return FAILED;
631 }
632 return status;
633 }
634
635 METHOD(task_t, process_i, status_t,
636 private_xauth_request_t *this, message_t *message)
637 {
638 status_t status;
639 DBG1(DBG_IKE, "%s: state %d", __func__, this->state);
640 if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
641 { /* in last IKE_AUTH exchange */
642
643 status = process_payloads(this, message);
644 this->state = this->next_state;
645
646 DBG1(DBG_IKE, "state %d, complete state %d", this->state, TASK_XAUTH_COMPLETE);
647 DBG1(DBG_IKE, "status %d SUCCESS %d", this->status, SUCCESS);
648
649 if (this->virtual_ip)
650 {
651 this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
652 }
653 if(this->state == TASK_XAUTH_COMPLETE)
654 return this->status;
655 return status;
656 }
657 return NEED_MORE;
658
659 }
660
661 METHOD(task_t, get_type, task_type_t,
662 private_xauth_request_t *this)
663 {
664 return TASK_XAUTH_REQUEST;
665 }
666
667 METHOD(task_t, migrate, void,
668 private_xauth_request_t *this, ike_sa_t *ike_sa)
669 {
670 DESTROY_IF(this->virtual_ip);
671
672 this->ike_sa = ike_sa;
673 this->virtual_ip = NULL;
674 this->requested->destroy_function(this->requested, free);
675 this->requested = linked_list_create();
676 }
677
678 METHOD(task_t, destroy, void,
679 private_xauth_request_t *this)
680 {
681 DESTROY_IF(this->virtual_ip);
682 this->requested->destroy_function(this->requested, free);
683 free(this);
684 }
685
686 METHOD(task_t, swap_initiator, void,
687 private_xauth_request_t *this)
688 {
689 if(this->initiator)
690 {
691 this->public.task.build = _build_r;
692 this->public.task.process = _process_r;
693 this->initiator = FALSE;
694 }
695 else
696 {
697 this->public.task.build = _build_i;
698 this->public.task.process = _process_i;
699 this->initiator = TRUE;
700 }
701 }
702
703 /*
704 * Described in header.
705 */
706 xauth_request_t *xauth_request_create(ike_sa_t *ike_sa, bool initiator)
707 {
708 private_xauth_request_t *this;
709
710 INIT(this,
711 .public = {
712 .task = {
713 .get_type = _get_type,
714 .migrate = _migrate,
715 .destroy = _destroy,
716 .swap_initiator = _swap_initiator,
717 },
718 },
719 .initiator = initiator,
720 .ike_sa = ike_sa,
721 .requested = linked_list_create(),
722 .state = TASK_XAUTH_INIT,
723 .next_state = TASK_XAUTH_INIT,
724 .xauth_status_data = XAUTH_STATUS_FAIL,
725 .xauth_user_name = chunk_empty,
726 .xauth_user_pass = chunk_empty,
727 .xauth_user_name_recv = FALSE,
728 .xauth_user_pass_recv = FALSE,
729 .xauth_status_recv = FALSE,
730 );
731
732 if (initiator)
733 {
734 this->public.task.build = _build_i;
735 this->public.task.process = _process_i;
736 }
737 else
738 {
739 this->public.task.build = _build_r;
740 this->public.task.process = _process_r;
741 }
742
743 return &this->public;
744 }