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