refactoring of Mode Config functionality allows transport and handling of any attribute
[strongswan.git] / src / pluto / modecfg.c
1 /* Mode config related functions
2 * Copyright (C) 2001-2002 Colubris Networks
3 * Copyright (C) 2003 Sean Mathews - Nu Tech Software Solutions, inc.
4 * Copyright (C) 2003-2004 Xelerance Corporation
5 * Copyright (C) 2006-2010 Andreas Steffen - Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 * This code originally written by Colubris Networks, Inc.
18 * Extraction of patch and porting to 1.99 codebases by Xelerance Corporation
19 * Porting to 2.x by Sean Mathews
20 */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <freeswan.h>
27
28 #include <library.h>
29 #include <hydra.h>
30 #include <utils/linked_list.h>
31 #include <crypto/prfs/prf.h>
32
33 #include "constants.h"
34 #include "defs.h"
35 #include "state.h"
36 #include "demux.h"
37 #include "timer.h"
38 #include "ipsec_doi.h"
39 #include "log.h"
40 #include "crypto.h"
41 #include "modecfg.h"
42 #include "whack.h"
43 #include "xauth.h"
44
45 #define MAX_XAUTH_TRIES 3
46
47 #define DEFAULT_UNITY_BANNER "Welcome to strongSwan - the Linux VPN Solution!\n"
48
49 /**
50 * Creates a modecfg_attribute_t object
51 */
52 static modecfg_attribute_t *modecfg_attribute_create(configuration_attribute_type_t type,
53 chunk_t value)
54 {
55 modecfg_attribute_t *this;
56
57 this = malloc_thing(modecfg_attribute_t);
58 this->type = ((u_int16_t)type) & 0x7FFF;
59 this->is_tv = FALSE;
60 this->value = chunk_clone(value);
61 this->handler = NULL;
62
63 return this;
64 }
65
66 /**
67 * Creates a modecfg_attribute_t object coded in TV format
68 */
69 static modecfg_attribute_t *modecfg_attribute_create_tv(configuration_attribute_type_t type,
70 size_t value)
71 {
72 modecfg_attribute_t *this;
73
74 this = modecfg_attribute_create(type, chunk_empty);
75 this->value.len = value;
76 this->is_tv = TRUE;
77
78 return this;
79 }
80
81 /**
82 * Destroys a modecfg_attribute_t object
83 */
84 void modecfg_attribute_destroy(modecfg_attribute_t *this)
85 {
86 free(this->value.ptr);
87 free(this);
88 }
89
90 /**
91 * Get attributes to be sent to client
92 */
93 static void get_attributes(connection_t *c, linked_list_t *ca_list)
94 {
95 configuration_attribute_type_t type;
96 modecfg_attribute_t *ca;
97 enumerator_t *enumerator;
98 chunk_t value;
99 host_t *vip = NULL, *requested_vip = NULL;
100 bool want_unity_banner = FALSE;
101 int family;
102
103 #ifdef CISCO_QUIRKS
104 /* always send banner in ModeCfg push mode */
105 if (ca_list->get_count(ca_list) == 0)
106 {
107 want_unity_banner = TRUE;
108 }
109 #endif
110
111 /* scan list of requested attributes in ModeCfg pull mode */
112 while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
113 {
114 switch (ca->type)
115 {
116 case INTERNAL_IP4_ADDRESS:
117 case INTERNAL_IP6_ADDRESS:
118 {
119 int family;
120
121 family = (ca->type == INTERNAL_IP4_ADDRESS) ? AF_INET : AF_INET6;
122 requested_vip = (ca->value.len) ?
123 host_create_from_chunk(family, ca->value, 0) :
124 host_create_any(family);
125 plog("peer requested virtual IP %H", requested_vip);
126 break;
127 }
128 #ifdef CISCO_QUIRKS
129 case UNITY_BANNER:
130 want_unity_banner = TRUE;
131 break;
132 #endif
133 default:
134 break;
135 }
136 modecfg_attribute_destroy(ca);
137 }
138
139 if (requested_vip == NULL)
140 {
141 requested_vip = host_create_any(AF_INET);
142 }
143
144 /* if no virtual IP has been assigned yet - acquire one */
145 if (c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
146 {
147 if (c->spd.that.pool)
148 {
149 vip = hydra->attributes->acquire_address(hydra->attributes,
150 c->spd.that.pool, c->spd.that.id,
151 requested_vip);
152 if (vip)
153 {
154 c->spd.that.host_srcip->destroy(c->spd.that.host_srcip);
155 c->spd.that.host_srcip = vip;
156 }
157 }
158 else
159 {
160 plog("no virtual IP found");
161 }
162 }
163
164 requested_vip->destroy(requested_vip);
165
166 /* if we have a virtual IP address - send it */
167 if (!c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
168 {
169 vip = c->spd.that.host_srcip;
170 plog("assigning virtual IP %H to peer", vip);
171 family = vip->get_family(vip);
172 ca = modecfg_attribute_create((family == AF_INET) ?
173 INTERNAL_IP4_ADDRESS :
174 INTERNAL_IP6_ADDRESS,
175 vip->get_address(vip));
176 ca_list->insert_last(ca_list, ca);
177
178 /* set the remote client subnet to virtual IP */
179 c->spd.that.client.addr = *(ip_address*)vip->get_sockaddr(vip);
180 c->spd.that.client.maskbits = (family == AF_INET) ? 32 : 128;
181 c->spd.that.has_client = TRUE;
182 }
183
184 /* assign attributes from registered providers */
185 enumerator = hydra->attributes->create_responder_enumerator(hydra->attributes,
186 c->spd.that.id, vip);
187 while (enumerator->enumerate(enumerator, &type, &value))
188 {
189 ca = modecfg_attribute_create(type, value);
190 ca_list->insert_last(ca_list, ca);
191 if (type == UNITY_BANNER)
192 {
193 want_unity_banner = FALSE;
194 }
195 }
196 enumerator->destroy(enumerator);
197
198 if (want_unity_banner)
199 {
200 ca = modecfg_attribute_create(UNITY_BANNER,
201 chunk_create(DEFAULT_UNITY_BANNER,
202 strlen(DEFAULT_UNITY_BANNER)));
203 ca_list->insert_last(ca_list, ca);
204 }
205 }
206
207 /**
208 * Set srcip and client subnet to internal IP address
209 */
210 static bool set_attributes(connection_t *c, linked_list_t *ca_list)
211 {
212 host_t *vip, *srcip;
213 modecfg_attribute_t *ca, *ca_handler;
214 enumerator_t *enumerator;
215 bool vip_set = FALSE;
216
217 enumerator = ca_list->create_enumerator(ca_list);
218 while (enumerator->enumerate(enumerator, &ca))
219 {
220 int family = AF_INET6;
221 attribute_handler_t *handler = NULL;
222 enumerator_t *e;
223
224 switch (ca->type)
225 {
226 case INTERNAL_IP4_ADDRESS:
227 family = AF_INET;
228 /* fall */
229 case INTERNAL_IP6_ADDRESS:
230 if (ca->value.len == 0)
231 {
232 vip = host_create_any(family);
233 }
234 else
235 {
236 /* skip prefix byte in IPv6 payload*/
237 if (family == AF_INET6)
238 {
239 ca->value.len = 16;
240 }
241 vip = host_create_from_chunk(family, ca->value, 0);
242 }
243 if (vip)
244 {
245 srcip = c->spd.this.host_srcip;
246
247 if (srcip->is_anyaddr(srcip) || srcip->equals(srcip, vip))
248 {
249 plog("setting virtual IP source address to %H", vip);
250 }
251 else
252 {
253 plog("replacing virtual IP source address %H by %H",
254 srcip, vip);
255 }
256 srcip->destroy(srcip);
257 c->spd.this.host_srcip = vip;
258
259 /* setting client subnet to vip/32 */
260 addrtosubnet((ip_address*)vip->get_sockaddr(vip),
261 &c->spd.this.client);
262 setportof(0, &c->spd.this.client.addr);
263 c->spd.this.has_client = TRUE;
264
265 vip_set = TRUE;
266 }
267 continue;
268 case APPLICATION_VERSION:
269 #ifdef CISCO_QUIRKS
270 case UNITY_BANNER:
271 #endif
272 if (ca->value.len > 0)
273 {
274 DBG(DBG_PARSING | DBG_CONTROLMORE,
275 DBG_log(" '%.*s'", ca->value.len, ca->value.ptr)
276 )
277 }
278 break;
279 default:
280 break;
281 }
282
283 /* find the first handler which requested this attribute */
284 e = c->requested->create_enumerator(c->requested);
285 while (e->enumerate(e, &ca_handler))
286 {
287 if (ca_handler->type == ca->type)
288 {
289 handler = ca_handler->handler;
290 break;
291 }
292 }
293 e->destroy(e);
294
295 /* and pass it to the handle function */
296 handler = hydra->attributes->handle(hydra->attributes,
297 c->spd.that.id, handler, ca->type, ca->value);
298 if (handler)
299 {
300 ca_handler = modecfg_attribute_create(ca->type, ca->value);
301 ca_handler->handler = handler;
302
303 if (c->attributes == NULL)
304 {
305 c->attributes = linked_list_create();
306 }
307 c->attributes->insert_last(c->attributes, ca_handler);
308 }
309 }
310 enumerator->destroy(enumerator);
311 c->requested->destroy_function(c->requested, (void*)modecfg_attribute_destroy);
312 c->requested = NULL;
313 return vip_set;
314 }
315
316 /**
317 * Register configuration attribute handlers
318 */
319 static void register_attribute_handlers(connection_t *c)
320 {
321 configuration_attribute_type_t type;
322 modecfg_attribute_t *ca;
323 chunk_t value;
324 attribute_handler_t *handler;
325 enumerator_t *enumerator;
326
327 /* add configuration attributes requested by handlers */
328 if (c->requested == NULL)
329 {
330 c->requested = linked_list_create();
331 }
332 enumerator = hydra->attributes->create_initiator_enumerator(
333 hydra->attributes,c->spd.that.id, c->spd.this.host_srcip);
334 while (enumerator->enumerate(enumerator, &handler, &type, &value))
335 {
336 ca = modecfg_attribute_create(type, value);
337 ca->handler = handler;
338 c->requested->insert_last(c->requested, ca);
339 }
340 enumerator->destroy(enumerator);
341 }
342
343 /**
344 * Compute HASH of Mode Config.
345 */
346 static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
347 const struct state *st)
348 {
349 chunk_t msgid_chunk = chunk_from_thing(st->st_msgid);
350 chunk_t msg_chunk = { start, roof - start };
351 size_t prf_block_size;
352 pseudo_random_function_t prf_alg;
353 prf_t *prf;
354
355 prf_alg = oakley_to_prf(st->st_oakley.hash);
356 prf = lib->crypto->create_prf(lib->crypto, prf_alg);
357 prf->set_key(prf, st->st_skeyid_a);
358 prf->get_bytes(prf, msgid_chunk, NULL);
359 prf->get_bytes(prf, msg_chunk, dest);
360 prf_block_size = prf->get_block_size(prf);
361 prf->destroy(prf);
362
363 DBG(DBG_CRYPT,
364 DBG_log("ModeCfg HASH computed:");
365 DBG_dump("", dest, prf_block_size)
366 )
367 return prf_block_size;
368 }
369
370
371 /**
372 * Generate an IKE message containing ModeCfg information (eg: IP, DNS, WINS)
373 */
374 static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody,
375 u_int16_t msg_type, linked_list_t *ca_list,
376 u_int16_t ap_id)
377 {
378 u_char *r_hash_start, *r_hashval;
379 struct isakmp_mode_attr attrh;
380 struct isakmp_attribute attr;
381 pb_stream strattr,attrval;
382 enumerator_t *enumerator;
383 modecfg_attribute_t *ca;
384
385 START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR);
386
387 attrh.isama_np = ISAKMP_NEXT_NONE;
388 attrh.isama_type = msg_type;
389 attrh.isama_identifier = ap_id;
390
391 if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
392 {
393 return STF_INTERNAL_ERROR;
394 }
395
396 enumerator = ca_list->create_enumerator(ca_list);
397 while (enumerator->enumerate(enumerator, &ca))
398 {
399 DBG(DBG_CONTROLMORE,
400 DBG_log("building %N attribute", configuration_attribute_type_names, ca->type)
401 )
402 if (ca->is_tv)
403 {
404 attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TV;
405 attr.isaat_lv = ca->value.len;
406 out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
407 }
408 else
409 {
410 char buf[BUF_LEN];
411
412 attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TLV;
413 out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
414 snprintf(buf, BUF_LEN, "%N", configuration_attribute_type_names, ca->type);
415 out_raw(ca->value.ptr, ca->value.len, &attrval, buf);
416 }
417 close_output_pbs(&attrval);
418 }
419 enumerator->destroy(enumerator);
420 close_message(&strattr);
421
422 modecfg_hash(r_hashval, r_hash_start, rbody->cur, st);
423 close_message(rbody);
424 encrypt_message(rbody, st);
425 return STF_OK;
426 }
427
428 /**
429 * Send ModeCfg message
430 */
431 static stf_status modecfg_send_msg(struct state *st, int isama_type,
432 linked_list_t *ca_list)
433 {
434 pb_stream msg;
435 pb_stream rbody;
436 char buf[BUF_LEN];
437
438 /* set up attr */
439 init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer");
440
441 /* this is the beginning of a new exchange */
442 st->st_msgid = generate_msgid(st);
443 init_phase2_iv(st, &st->st_msgid);
444
445 /* HDR out */
446 {
447 struct isakmp_hdr hdr;
448
449 zero(&hdr); /* default to 0 */
450 hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
451 hdr.isa_np = ISAKMP_NEXT_HASH;
452 hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;
453 hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
454 memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
455 memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
456 hdr.isa_msgid = st->st_msgid;
457
458 if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody))
459 {
460 return STF_INTERNAL_ERROR;
461 }
462 }
463
464 /* ATTR out with isama_id of 0 */
465 modecfg_build_msg(st, &rbody, isama_type, ca_list, 0);
466
467 free(st->st_tpacket.ptr);
468 st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg));
469 st->st_tpacket = chunk_clone(st->st_tpacket);
470
471 /* Transmit */
472 send_packet(st, "ModeCfg msg");
473
474 if (st->st_event->ev_type != EVENT_RETRANSMIT)
475 {
476 delete_event(st);
477 event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
478 }
479 return STF_OK;
480 }
481
482 /**
483 * Parse a ModeCfg attribute payload
484 */
485 static stf_status modecfg_parse_attributes(pb_stream *attrs, linked_list_t *ca_list)
486 {
487 struct isakmp_attribute attr;
488 pb_stream strattr;
489 u_int16_t attr_type;
490 u_int16_t attr_len;
491 chunk_t attr_chunk;
492 modecfg_attribute_t *ca;
493
494 while (pbs_left(attrs) >= sizeof(struct isakmp_attribute))
495 {
496 if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr))
497 {
498 return STF_FAIL;
499 }
500 attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK;
501 attr_len = attr.isaat_lv;
502 DBG(DBG_CONTROLMORE,
503 DBG_log("processing %N attribute",
504 configuration_attribute_type_names, attr_type)
505 )
506
507 switch (attr_type)
508 {
509 case INTERNAL_IP4_ADDRESS:
510 case INTERNAL_IP4_NETMASK:
511 case INTERNAL_IP4_DNS:
512 case INTERNAL_IP4_NBNS:
513 case INTERNAL_ADDRESS_EXPIRY:
514 case INTERNAL_IP4_DHCP:
515 if (attr_len != 4 && attr_len != 0)
516 {
517 goto error;
518 }
519 break;
520 case INTERNAL_IP4_SUBNET:
521 if (attr_len != 8 && attr_len != 0)
522 {
523 goto error;
524 }
525 break;
526 case INTERNAL_IP6_NETMASK:
527 case INTERNAL_IP6_DNS:
528 case INTERNAL_IP6_NBNS:
529 case INTERNAL_IP6_DHCP:
530 if (attr_len != 16 && attr_len != 0)
531 {
532 goto error;
533 }
534 break;
535 case INTERNAL_IP6_ADDRESS:
536 if (attr_len != 17 && attr_len != 16 && attr_len != 0)
537 {
538 goto error;
539 }
540 break;
541 case INTERNAL_IP6_SUBNET:
542 if (attr_len != 17 && attr_len != 0)
543 {
544 goto error;
545 }
546 break;
547 case SUPPORTED_ATTRIBUTES:
548 if (attr_len % 2)
549 {
550 goto error;
551 }
552 break;
553 case APPLICATION_VERSION:
554 break;
555 /* XAUTH attributes */
556 case XAUTH_TYPE:
557 case XAUTH_STATUS:
558 if (!(attr.isaat_af_type & ISAKMP_ATTR_AF_TV))
559 {
560 plog("%N attribute is not TV encoded",
561 configuration_attribute_type_names, attr_type);
562 return STF_FAIL;
563 }
564 case XAUTH_USER_NAME:
565 case XAUTH_USER_PASSWORD:
566 case XAUTH_PASSCODE:
567 case XAUTH_MESSAGE:
568 case XAUTH_CHALLENGE:
569 case XAUTH_DOMAIN:
570 case XAUTH_NEXT_PIN:
571 case XAUTH_ANSWER:
572 break;
573 /* Microsoft attributes */
574 case INTERNAL_IP4_SERVER:
575 case INTERNAL_IP6_SERVER:
576 break;
577 /* Cisco Unity attributes */
578 case UNITY_BANNER:
579 case UNITY_SAVE_PASSWD:
580 case UNITY_DEF_DOMAIN:
581 case UNITY_SPLITDNS_NAME:
582 case UNITY_SPLIT_INCLUDE:
583 case UNITY_NATT_PORT:
584 case UNITY_LOCAL_LAN:
585 case UNITY_PFS:
586 case UNITY_FW_TYPE:
587 case UNITY_BACKUP_SERVERS:
588 case UNITY_DDNS_HOSTNAME:
589 break;
590 default:
591 plog("unknown attribute type (%u)", attr_type);
592 continue;
593 }
594
595 /* add attribute */
596 if (attr.isaat_af_type & ISAKMP_ATTR_AF_TV)
597 {
598 ca = modecfg_attribute_create_tv(attr_type, attr_len);
599 }
600 else
601 {
602 attr_chunk = chunk_create(strattr.cur, attr_len);
603 ca = modecfg_attribute_create(attr_type, attr_chunk);
604 }
605 ca_list->insert_last(ca_list, ca);
606 }
607 return STF_OK;
608
609 error:
610 plog("%N attribute has invalid size of %u octets",
611 configuration_attribute_type_names, attr_type, attr_len);
612 return STF_FAIL;
613 }
614
615 /**
616 * Parse a ModeCfg message
617 */
618 static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type,
619 u_int16_t *isama_id, linked_list_t *ca_list)
620 {
621 modecfg_attribute_t *ca;
622 struct state *const st = md->st;
623 struct payload_digest *p;
624 stf_status stat;
625
626 st->st_msgid = md->hdr.isa_msgid;
627
628 CHECK_QUICK_HASH(md, modecfg_hash(hash_val, hash_pbs->roof,
629 md->message_pbs.roof, st), "MODECFG-HASH", "ISAKMP_CFG_MSG");
630
631 /* process the ModeCfg payloads received */
632 for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
633 {
634 if (p->payload.attribute.isama_type == isama_type)
635 {
636 *isama_id = p->payload.attribute.isama_identifier;
637
638 stat = modecfg_parse_attributes(&p->pbs, ca_list);
639 if (stat == STF_OK)
640 {
641 /* return with a valid set of attributes */
642 return STF_OK;
643 }
644 }
645 else
646 {
647 plog("expected %s, got %s instead (ignored)"
648 , enum_name(&attr_msg_type_names, isama_type)
649 , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type));
650
651 stat = modecfg_parse_attributes(&p->pbs, ca_list);
652 }
653
654 /* abort if a parsing error occurred */
655 if (stat != STF_OK)
656 {
657 ca_list->destroy_function(ca_list, (void*)modecfg_attribute_destroy);
658 return stat;
659 }
660
661 /* discard the parsed attributes and look for another payload */
662 while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS) {}
663 }
664 return STF_IGNORE;
665 }
666
667 /**
668 * Used in ModeCfg pull mode on the client (initiator)
669 * called in demux.c
670 * client -> CFG_REQUEST
671 * STF_OK transitions to STATE_MODE_CFG_I1
672 */
673 stf_status modecfg_send_request(struct state *st)
674 {
675 connection_t *c = st->st_connection;
676 stf_status stat;
677 modecfg_attribute_t *ca;
678 enumerator_t *enumerator;
679 int family;
680 chunk_t value;
681 host_t *vip;
682 linked_list_t *ca_list = linked_list_create();
683
684 vip = c->spd.this.host_srcip;
685 value = vip->is_anyaddr(vip) ? chunk_empty : vip->get_address(vip);
686 family = vip->get_family(vip);
687 ca = modecfg_attribute_create((family == AF_INET) ?
688 INTERNAL_IP4_ADDRESS : INTERNAL_IP6_ADDRESS,
689 value);
690 ca_list->insert_last(ca_list, ca);
691
692 register_attribute_handlers(c);
693 enumerator = c->requested->create_enumerator(c->requested);
694 while (enumerator->enumerate(enumerator, &ca))
695 {
696 ca = modecfg_attribute_create(ca->type, chunk_empty);
697 ca_list->insert_last(ca_list, ca);
698 }
699 enumerator->destroy(enumerator);
700
701 plog("sending ModeCfg request");
702
703 st->st_state = STATE_MODE_CFG_I1;
704 stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, ca_list);
705 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
706 if (stat == STF_OK)
707 {
708 st->st_modecfg.started = TRUE;
709 }
710 return stat;
711 }
712
713 /**
714 * Used in ModeCfg pull mode on the server (responder)
715 * called in demux.c from STATE_MODE_CFG_R0
716 * server <- CFG_REQUEST
717 * server -> CFG_REPLY
718 * STF_OK transitions to STATE_MODE_CFG_R0
719 */
720 stf_status modecfg_inR0(struct msg_digest *md)
721 {
722 struct state *const st = md->st;
723 u_int16_t isama_id;
724 stf_status stat, stat_build;
725 linked_list_t *ca_list = linked_list_create();
726
727 plog("parsing ModeCfg request");
728
729 stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, ca_list);
730 if (stat != STF_OK)
731 {
732 return stat;
733 }
734
735 /* build the CFG_REPLY */
736 get_attributes(st->st_connection, ca_list);
737
738 plog("sending ModeCfg reply");
739
740 stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY,
741 ca_list, isama_id);
742 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
743
744 if (stat_build != STF_OK)
745 {
746 return stat_build;
747 }
748 st->st_msgid = 0;
749 return STF_OK;
750 }
751
752 /**
753 * Used in ModeCfg pull mode on the client (initiator)
754 * called in demux.c from STATE_MODE_CFG_I1
755 * client <- CFG_REPLY
756 * STF_OK transitions to STATE_MODE_CFG_I2
757 */
758 stf_status modecfg_inI1(struct msg_digest *md)
759 {
760 struct state *const st = md->st;
761 u_int16_t isama_id;
762 stf_status stat;
763 linked_list_t *ca_list = linked_list_create();
764
765 plog("parsing ModeCfg reply");
766
767 stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, ca_list);
768 if (stat != STF_OK)
769 {
770 return stat;
771 }
772 st->st_modecfg.vars_set = set_attributes(st->st_connection, ca_list);
773 st->st_msgid = 0;
774 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
775 return STF_OK;
776 }
777
778 /**
779 * Used in ModeCfg push mode on the server (responder)
780 * called in demux.c
781 * server -> CFG_SET
782 * STF_OK transitions to STATE_MODE_CFG_R3
783 */
784 stf_status modecfg_send_set(struct state *st)
785 {
786 stf_status stat;
787 linked_list_t *ca_list = linked_list_create();
788
789
790 plog("sending ModeCfg set");
791
792 get_attributes(st->st_connection, ca_list);
793 st->st_state = STATE_MODE_CFG_R3;
794 stat = modecfg_send_msg(st, ISAKMP_CFG_SET, ca_list);
795 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
796 if (stat == STF_OK)
797 {
798 st->st_modecfg.started = TRUE;
799 }
800 return stat;
801 }
802
803 /**
804 * Used in ModeCfg push mode on the client (initiator)
805 * called in demux.c from STATE_MODE_CFG_I0
806 * client <- CFG_SET
807 * client -> CFG_ACK
808 * STF_OK transitions to STATE_MODE_CFG_I3
809 */
810 stf_status modecfg_inI0(struct msg_digest *md)
811 {
812 struct state *const st = md->st;
813 u_int16_t isama_id;
814 stf_status stat, stat_build;
815 modecfg_attribute_t *ca;
816 linked_list_t *ca_list, *ca_ack_list;
817
818 plog("parsing ModeCfg set");
819
820 ca_list = linked_list_create();
821 stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, ca_list);
822 if (stat != STF_OK)
823 {
824 return stat;
825 }
826 register_attribute_handlers(st->st_connection);
827 st->st_modecfg.vars_set = set_attributes(st->st_connection, ca_list);
828
829 /* prepare ModeCfg ack which sends zero length attributes */
830 ca_ack_list = linked_list_create();
831 while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
832 {
833 switch (ca->type)
834 {
835 case INTERNAL_IP4_ADDRESS:
836 case INTERNAL_IP4_DNS:
837 case INTERNAL_IP4_NBNS:
838 case APPLICATION_VERSION:
839 case INTERNAL_IP6_ADDRESS:
840 case INTERNAL_IP6_DNS:
841 case INTERNAL_IP6_NBNS:
842 #ifdef CISCO_QUIRKS
843 case UNITY_BANNER:
844 #endif
845 /* supported attributes */
846 ca->value.len = 0;
847 ca_ack_list->insert_last(ca_ack_list, ca);
848 break;
849 default:
850 /* unsupportd attributes */
851 modecfg_attribute_destroy(ca);
852 }
853 }
854 ca_list->destroy(ca_list);
855
856 plog("sending ModeCfg ack");
857
858 stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK,
859 ca_ack_list, isama_id);
860 ca_ack_list->destroy_function(ca_ack_list, (void *)modecfg_attribute_destroy);
861 if (stat_build != STF_OK)
862 {
863 return stat_build;
864 }
865 st->st_msgid = 0;
866 return STF_OK;
867 }
868
869 /**
870 * Used in ModeCfg push mode on the server (responder)
871 * called in demux.c from STATE_MODE_CFG_R3
872 * server <- CFG_ACK
873 * STF_OK transitions to STATE_MODE_CFG_R4
874 */
875 stf_status modecfg_inR3(struct msg_digest *md)
876 {
877 struct state *const st = md->st;
878 u_int16_t isama_id;
879 stf_status stat;
880 linked_list_t *ca_list = linked_list_create();
881
882 plog("parsing ModeCfg ack");
883
884 stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, ca_list);
885 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
886 if (stat != STF_OK)
887 {
888 return stat;
889 }
890 st->st_msgid = 0;
891 return STF_OK;
892 }
893
894 /**
895 * Used on the XAUTH server (responder)
896 * called in demux.c
897 * server -> CFG_REQUEST
898 * STF_OK transitions to STATE_XAUTH_R1
899 */
900 stf_status xauth_send_request(struct state *st)
901 {
902 stf_status stat;
903 modecfg_attribute_t *ca;
904 linked_list_t *ca_list = linked_list_create();
905
906 ca = modecfg_attribute_create(XAUTH_USER_NAME, chunk_empty);
907 ca_list->insert_last(ca_list, ca);
908 ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, chunk_empty);
909 ca_list->insert_last(ca_list, ca);
910
911 plog("sending XAUTH request");
912 st->st_state = STATE_XAUTH_R1;
913 stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, ca_list);
914 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
915 if (stat == STF_OK)
916 {
917 st->st_xauth.started = TRUE;
918 }
919 return stat;
920 }
921
922 /**
923 * Used on the XAUTH client (initiator)
924 * called in demux.c from STATE_XAUTH_I0
925 * client <- CFG_REQUEST
926 * client -> CFG_REPLY
927 * STF_OK transitions to STATE_XAUTH_I1
928 */
929 stf_status xauth_inI0(struct msg_digest *md)
930 {
931 struct state *const st = md->st;
932 u_int16_t isama_id;
933 stf_status stat, stat_build;
934 modecfg_attribute_t *ca;
935 bool xauth_user_name = FALSE;
936 bool xauth_user_password = FALSE;
937 bool xauth_type_present = FALSE;
938 xauth_t xauth_secret;
939 linked_list_t *ca_list = linked_list_create();
940
941 plog("parsing XAUTH request");
942
943 stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, ca_list);
944 if (stat != STF_OK)
945 {
946 return stat;
947 }
948
949 while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
950 {
951 switch (ca->type)
952 {
953 case XAUTH_TYPE:
954 if (ca->value.len != XAUTH_TYPE_GENERIC)
955 {
956 plog("xauth type %s is not supported",
957 enum_name(&xauth_type_names, ca->value.len));
958 stat = STF_FAIL;
959 }
960 else
961 {
962 xauth_type_present = TRUE;
963 }
964 break;
965 case XAUTH_USER_NAME:
966 xauth_user_name = TRUE;
967 break;
968 case XAUTH_USER_PASSWORD:
969 xauth_user_password = TRUE;
970 break;
971 case XAUTH_MESSAGE:
972 if (ca->value.len)
973 {
974 DBG(DBG_PARSING | DBG_CONTROLMORE,
975 DBG_log(" '%.*s'", ca->value.len, ca->value.ptr)
976 )
977 }
978 break;
979 default:
980 break;
981 }
982 modecfg_attribute_destroy(ca);
983 }
984
985 if (!xauth_user_name)
986 {
987 plog("user name attribute is missing in XAUTH request");
988 stat = STF_FAIL;
989 }
990 if (!xauth_user_password)
991 {
992 plog("user password attribute is missing in XAUTH request");
993 stat = STF_FAIL;
994 }
995
996 /* prepare XAUTH reply */
997 if (stat == STF_OK)
998 {
999 /* get user credentials using a plugin function */
1000 if (!xauth_module.get_secret(&xauth_secret))
1001 {
1002 plog("xauth user credentials not found");
1003 stat = STF_FAIL;
1004 }
1005 }
1006 if (stat == STF_OK)
1007 {
1008 if (xauth_type_present)
1009 {
1010 ca = modecfg_attribute_create_tv(XAUTH_TYPE, XAUTH_TYPE_GENERIC);
1011 ca_list->insert_last(ca_list, ca);
1012 }
1013 DBG(DBG_CONTROL,
1014 DBG_log("my xauth user name is '%.*s'", xauth_secret.user_name.len,
1015 xauth_secret.user_name.ptr)
1016 )
1017 ca = modecfg_attribute_create(XAUTH_USER_NAME, xauth_secret.user_name);
1018 ca_list->insert_last(ca_list, ca);
1019 DBG(DBG_PRIVATE,
1020 DBG_log("my xauth user password is '%.*s'", xauth_secret.user_password.len,
1021 xauth_secret.user_password.ptr)
1022 )
1023 ca = modecfg_attribute_create(XAUTH_USER_PASSWORD, xauth_secret.user_password);
1024 ca_list->insert_last(ca_list, ca);
1025 }
1026 else
1027 {
1028 ca = modecfg_attribute_create_tv(XAUTH_STATUS, XAUTH_STATUS_FAIL);
1029 ca_list->insert_last(ca_list, ca);
1030 }
1031
1032 plog("sending XAUTH reply");
1033 stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY,
1034 ca_list, isama_id);
1035 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
1036 if (stat_build != STF_OK)
1037 {
1038 return stat_build;
1039 }
1040 if (stat == STF_OK)
1041 {
1042 st->st_xauth.started = TRUE;
1043 st->st_msgid = 0;
1044 return STF_OK;
1045 }
1046 else
1047 {
1048 /* send XAUTH reply msg and then delete ISAKMP SA */
1049 free(st->st_tpacket.ptr);
1050 st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply));
1051 st->st_tpacket = chunk_clone(st->st_tpacket);
1052 send_packet(st, "XAUTH reply msg");
1053 delete_state(st);
1054 return STF_IGNORE;
1055 }
1056 }
1057
1058 /**
1059 * Used on the XAUTH server (responder)
1060 * called in demux.c from STATE_XAUTH_R1
1061 server <- CFG_REPLY
1062 server -> CFG_SET
1063 STF_OK transitions to STATE_XAUTH_R2
1064 */
1065 stf_status xauth_inR1(struct msg_digest *md)
1066 {
1067 struct state *const st = md->st;
1068 u_int16_t isama_id;
1069 stf_status stat, stat_build;
1070 xauth_t xauth_secret;
1071 int xauth_status = XAUTH_STATUS_OK;
1072 modecfg_attribute_t *ca;
1073 linked_list_t *ca_list = linked_list_create();
1074
1075 plog("parsing XAUTH reply");
1076
1077 stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, ca_list);
1078 if (stat != STF_OK)
1079 {
1080 return stat;
1081 }
1082
1083 /* initialize xauth_secret */
1084 xauth_secret.user_name = chunk_empty;
1085 xauth_secret.user_password = chunk_empty;
1086
1087 while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
1088 {
1089 switch (ca->type)
1090 {
1091 case XAUTH_STATUS:
1092 xauth_status = ca->value.len;
1093 break;
1094 case XAUTH_USER_NAME:
1095 xauth_secret.user_name = chunk_clone(ca->value);
1096 break;
1097 case XAUTH_USER_PASSWORD:
1098 xauth_secret.user_password = chunk_clone(ca->value);
1099 break;
1100 default:
1101 break;
1102 }
1103 modecfg_attribute_destroy(ca);
1104 }
1105 /* did the client return an XAUTH FAIL status? */
1106 if (xauth_status == XAUTH_STATUS_FAIL)
1107 {
1108 plog("received FAIL status in XAUTH reply");
1109
1110 /* client is not able to do XAUTH, delete ISAKMP SA */
1111 delete_state(st);
1112 ca_list->destroy(ca_list);
1113 return STF_IGNORE;
1114 }
1115
1116 /* check XAUTH reply */
1117 if (xauth_secret.user_name.ptr == NULL)
1118 {
1119 plog("user name attribute is missing in XAUTH reply");
1120 st->st_xauth.status = FALSE;
1121 }
1122 else if (xauth_secret.user_password.ptr == NULL)
1123 {
1124 plog("user password attribute is missing in XAUTH reply");
1125 st->st_xauth.status = FALSE;
1126 }
1127 else
1128 {
1129 xauth_peer_t peer;
1130
1131 peer.conn_name = st->st_connection->name;
1132 addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address));
1133 snprintf(peer.id, sizeof(peer.id), "%Y", md->st->st_connection->spd.that.id);
1134
1135 DBG(DBG_CONTROL,
1136 DBG_log("peer xauth user name is '%.*s'", xauth_secret.user_name.len,
1137 xauth_secret.user_name.ptr)
1138 )
1139 DBG(DBG_PRIVATE,
1140 DBG_log("peer xauth user password is '%.*s'", xauth_secret.user_password.len,
1141 xauth_secret.user_password.ptr)
1142 )
1143 /* verify the user credentials using a plugin function */
1144 st->st_xauth.status = xauth_module.verify_secret(&peer, &xauth_secret);
1145 plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
1146 }
1147 chunk_clear(&xauth_secret.user_name);
1148 chunk_clear(&xauth_secret.user_password);
1149
1150 plog("sending XAUTH status");
1151 xauth_status = (st->st_xauth.status) ? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL;
1152 ca = modecfg_attribute_create_tv(XAUTH_STATUS, xauth_status);
1153 ca_list->insert_last(ca_list, ca);
1154 stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, ca_list);
1155 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
1156 if (stat_build != STF_OK)
1157 {
1158 return stat_build;
1159 }
1160 return STF_OK;
1161 }
1162
1163 /**
1164 * Used on the XAUTH client (initiator)
1165 * called in demux.c from STATE_XAUTH_I1
1166 * client <- CFG_SET
1167 * client -> CFG_ACK
1168 * STF_OK transitions to STATE_XAUTH_I2
1169 */
1170 stf_status xauth_inI1(struct msg_digest *md)
1171 {
1172 struct state *const st = md->st;
1173 u_int16_t isama_id;
1174 stf_status stat, stat_build;
1175 modecfg_attribute_t *ca;
1176 linked_list_t *ca_list = linked_list_create();
1177
1178 plog("parsing XAUTH status");
1179 stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, ca_list);
1180 if (stat != STF_OK)
1181 {
1182 /* notification payload - not exactly the right choice, but okay */
1183 md->note = ISAKMP_ATTRIBUTES_NOT_SUPPORTED;
1184 return stat;
1185 }
1186
1187 st->st_xauth.status = FALSE;
1188 while (ca_list->remove_last(ca_list, (void **)&ca) == SUCCESS)
1189 {
1190 if (ca->type == XAUTH_STATUS)
1191 {
1192 st->st_xauth.status = (ca->value.len == XAUTH_STATUS_OK);
1193 }
1194 modecfg_attribute_destroy(ca);
1195 }
1196 plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
1197
1198 plog("sending XAUTH ack");
1199 stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK, ca_list, isama_id);
1200 ca_list->destroy(ca_list);
1201
1202 if (stat_build != STF_OK)
1203 {
1204 return stat_build;
1205 }
1206 if (st->st_xauth.status)
1207 {
1208 st->st_msgid = 0;
1209 return STF_OK;
1210 }
1211 else
1212 {
1213 /* send XAUTH ack msg and then delete ISAKMP SA */
1214 free(st->st_tpacket.ptr);
1215 st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply));
1216 st->st_tpacket = chunk_clone(st->st_tpacket);
1217 send_packet(st, "XAUTH ack msg");
1218 delete_state(st);
1219 return STF_IGNORE;
1220 }
1221 }
1222
1223 /**
1224 * Used on the XAUTH server (responder)
1225 * called in demux.c from STATE_XAUTH_R2
1226 * server <- CFG_ACK
1227 * STF_OK transitions to STATE_XAUTH_R3
1228 */
1229 stf_status xauth_inR2(struct msg_digest *md)
1230 {
1231 struct state *const st = md->st;
1232 u_int16_t isama_id;
1233 stf_status stat;
1234 linked_list_t *ca_list = linked_list_create();
1235
1236 plog("parsing XAUTH ack");
1237
1238 stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, ca_list);
1239 if (stat != STF_OK)
1240 {
1241 return stat;
1242 }
1243 ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
1244 st->st_msgid = 0;
1245 if (st->st_xauth.status)
1246 {
1247 return STF_OK;
1248 }
1249 else
1250 {
1251 delete_state(st);
1252 return STF_IGNORE;
1253 }
1254
1255 }