Mode Config refactoring
[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-2007 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 * RCSID $Id: modecfg.c,v 1.6 2006/04/24 20:44:57 as Exp $
18 *
19 * This code originally written by Colubris Networks, Inc.
20 * Extraction of patch and porting to 1.99 codebases by Xelerance Corporation
21 * Porting to 2.x by Sean Mathews
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <freeswan.h>
29
30 #include "constants.h"
31 #include "defs.h"
32 #include "state.h"
33 #include "demux.h"
34 #include "timer.h"
35 #include "ipsec_doi.h"
36 #include "log.h"
37 #include "md5.h"
38 #include "sha1.h"
39 #include "crypto.h"
40 #include "modecfg.h"
41 #include "whack.h"
42 #include "xauth.h"
43
44 #define MAX_XAUTH_TRIES 3
45
46 #define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
47 | LELEM(INTERNAL_IP4_NETMASK) \
48 | LELEM(INTERNAL_IP4_DNS) \
49 | LELEM(INTERNAL_IP4_NBNS) \
50 | LELEM(APPLICATION_VERSION) \
51 )
52
53 #define SUPPORTED_UNITY_ATTR_SET ( LELEM(UNITY_BANNER - UNITY_BASE) )
54
55 #define UNITY_BANNER_STR "Welcome to strongSwan - the Linux VPN Solution!\n"
56
57 /*
58 * Addresses assigned (usually via ModeCfg) to the Initiator
59 */
60 typedef struct internal_addr internal_addr_t;
61
62 struct internal_addr
63 {
64 lset_t attr_set;
65 lset_t xauth_attr_set;
66 lset_t unity_attr_set;
67
68 /* ModeCfg variables */
69 ip_address ipaddr;
70 ip_address dns[2];
71 ip_address wins[2];
72
73 char *unity_banner;
74
75 /* XAUTH variables */
76 u_int16_t xauth_type;
77 xauth_t xauth_secret;
78 bool xauth_status;
79 };
80
81 /*
82 * Initialize an internal_addr struct
83 */
84 static void
85 init_internal_addr(internal_addr_t *ia)
86 {
87 ia->attr_set = LEMPTY;
88 ia->xauth_attr_set = LEMPTY;
89 ia->xauth_secret.user_name = empty_chunk;
90 ia->xauth_secret.user_password = empty_chunk;
91 ia->xauth_status = FALSE;
92 ia->unity_attr_set = LEMPTY;
93 ia->unity_banner = NULL;
94
95 anyaddr(AF_INET, &ia->ipaddr);
96 anyaddr(AF_INET, &ia->dns[0]);
97 anyaddr(AF_INET, &ia->dns[1]);
98 anyaddr(AF_INET, &ia->wins[0]);
99 anyaddr(AF_INET, &ia->wins[1]);
100 }
101
102 /*
103 * get internal IP address for a connection
104 */
105 static void
106 get_internal_addr(struct connection *c, internal_addr_t *ia)
107 {
108 if (isanyaddr(&c->spd.that.host_srcip))
109 {
110 /* not defined in connection - fetch it from LDAP */
111 }
112 else
113 {
114 char srcip[ADDRTOT_BUF];
115
116 ia->ipaddr = c->spd.that.host_srcip;
117
118 addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip));
119 plog("assigning virtual IP source address %s", srcip);
120 }
121
122 if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */
123 {
124 c->spd.that.client.addr = ia->ipaddr;
125 c->spd.that.client.maskbits = 32;
126 c->spd.that.has_client = TRUE;
127
128 ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS)
129 | LELEM(INTERNAL_IP4_NETMASK);
130 }
131
132 if (!isanyaddr(&ia->dns[0])) /* We got DNS addresses, send them */
133 ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
134
135 if (!isanyaddr(&ia->wins[0])) /* We got WINS addresses, send them */
136 ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
137 }
138
139 /*
140 * Set srcip and client subnet to internal IP address
141 */
142 static bool
143 set_internal_addr(struct connection *c, internal_addr_t *ia)
144 {
145 if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS)
146 && !isanyaddr(&ia->ipaddr))
147 {
148 if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0
149 || isanyaddr(&c->spd.this.host_srcip)
150 || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr))
151 {
152 char srcip[ADDRTOT_BUF];
153
154 addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip));
155 plog("setting virtual IP source address to %s", srcip);
156 }
157 else
158 {
159 char old_srcip[ADDRTOT_BUF];
160 char new_srcip[ADDRTOT_BUF];
161
162 addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip));
163 addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip));
164 plog("replacing virtual IP source address %s by %s"
165 , old_srcip, new_srcip);
166 }
167
168 /* setting srcip */
169 c->spd.this.host_srcip = ia->ipaddr;
170
171 /* setting client subnet to srcip/32 */
172 addrtosubnet(&ia->ipaddr, &c->spd.this.client);
173 setportof(0, &c->spd.this.client.addr);
174 c->spd.this.has_client = TRUE;
175 return TRUE;
176 }
177 return FALSE;
178 }
179
180 /*
181 * Compute HASH of Mode Config.
182 */
183 static size_t
184 modecfg_hash(u_char *dest, const u_char *start, const u_char *roof
185 , const struct state *st)
186 {
187 struct hmac_ctx ctx;
188
189 hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
190 hmac_update(&ctx, (const u_char *) &st->st_msgid, sizeof(st->st_msgid));
191 hmac_update(&ctx, start, roof-start);
192 hmac_final(dest, &ctx);
193
194 DBG(DBG_CRYPT,
195 DBG_log("ModeCfg HASH computed:");
196 DBG_dump("", dest, ctx.hmac_digest_size)
197 )
198 return ctx.hmac_digest_size;
199 }
200
201
202 /*
203 * Generate an IKE message containing ModeCfg information (eg: IP, DNS, WINS)
204 */
205 static stf_status
206 modecfg_build_msg(struct state *st, pb_stream *rbody
207 , u_int16_t msg_type
208 , internal_addr_t *ia
209 , u_int16_t ap_id)
210 {
211 u_char *r_hash_start, *r_hashval;
212
213 START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR);
214
215 /* ATTR out */
216 {
217 struct isakmp_mode_attr attrh;
218 struct isakmp_attribute attr;
219 pb_stream strattr,attrval;
220 int attr_type;
221 int dns_idx, wins_idx;
222 bool dont_advance;
223 bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY;
224 bool is_unity_attr_set = ia->unity_attr_set != LEMPTY;
225 lset_t attr_set = ia->attr_set;
226
227 attrh.isama_np = ISAKMP_NEXT_NONE;
228 attrh.isama_type = msg_type;
229 attrh.isama_identifier = ap_id;
230
231 if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
232 return STF_INTERNAL_ERROR;
233
234 attr_type = 0;
235 dns_idx = 0;
236 wins_idx = 0;
237
238 while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set)
239 {
240 if (attr_set == LEMPTY)
241 {
242 if (is_xauth_attr_set)
243 {
244 attr_set = ia->xauth_attr_set;
245 attr_type = XAUTH_BASE;
246 is_xauth_attr_set = FALSE;
247 }
248 else
249 {
250 attr_set = ia->unity_attr_set;
251 attr_type = UNITY_BASE;
252 is_unity_attr_set = FALSE;
253 }
254 }
255
256 dont_advance = FALSE;
257
258 if (attr_set & 1)
259 {
260 const u_char *byte_ptr;
261 u_int len;
262
263 /* ISAKMP attr out */
264 if (attr_type == XAUTH_TYPE)
265 {
266 attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
267 attr.isaat_lv = ia->xauth_type;
268 }
269 else if (attr_type == XAUTH_STATUS)
270 {
271 attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
272 attr.isaat_lv = ia->xauth_status;
273 }
274 else
275 {
276 attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
277 }
278 out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
279
280 switch (attr_type)
281 {
282 case INTERNAL_IP4_ADDRESS:
283 if (!isanyaddr(&ia->ipaddr))
284 {
285 len = addrbytesptr(&ia->ipaddr, &byte_ptr);
286 out_raw(byte_ptr, len, &attrval, "IP4_addr");
287 }
288 break;
289 case INTERNAL_IP4_NETMASK:
290 {
291 u_int mask;
292 #if 0
293 char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
294 int t,m=st->st_connection->that.host_addr.maskbit;
295 for (t=0; t<4; t++)
296 {
297 if (m < 8)
298 mask[t] = bits[m];
299 else
300 mask[t] = 0xff;
301 m -= 8;
302 }
303 #endif
304 if (st->st_connection->spd.this.client.maskbits == 0)
305 mask = 0;
306 else
307 mask = 0xffffffff * 1;
308 out_raw(&mask, 4, &attrval, "IP4_mask");
309 }
310 break;
311 case INTERNAL_IP4_SUBNET:
312 {
313 char mask[4];
314 char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
315 int t;
316 int m = st->st_connection->spd.this.client.maskbits;
317
318 for (t = 0; t < 4; t++)
319 {
320 if (m < 8)
321 mask[t] = bits[m];
322 else
323 mask[t] = 0xff;
324 m -= 8;
325 if (m < 0)
326 m = 0;
327 }
328 len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr);
329 out_raw(byte_ptr, len, &attrval, "IP4_subnet");
330 out_raw(mask, sizeof(mask), &attrval, "IP4_submsk");
331 }
332 break;
333 case INTERNAL_IP4_DNS:
334 if (!isanyaddr(&ia->dns[dns_idx]))
335 {
336 len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr);
337 out_raw(byte_ptr, len, &attrval, "IP4_dns");
338 }
339 if (dns_idx < 2 && !isanyaddr(&ia->dns[dns_idx]))
340 {
341 dont_advance = TRUE;
342 }
343 break;
344 case INTERNAL_IP4_NBNS:
345 if (!isanyaddr(&ia->wins[wins_idx]))
346 {
347 len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr);
348 out_raw(byte_ptr, len, &attrval, "IP4_wins");
349 }
350 if (wins_idx < 2 && !isanyaddr(&ia->wins[wins_idx]))
351 {
352 dont_advance = TRUE;
353 }
354 break;
355 case XAUTH_TYPE:
356 break;
357 case XAUTH_USER_NAME:
358 if (ia->xauth_secret.user_name.ptr != NULL)
359 {
360 out_raw(ia->xauth_secret.user_name.ptr
361 , ia->xauth_secret.user_name.len
362 , &attrval, "xauth_user_name");
363 }
364 break;
365 case XAUTH_USER_PASSWORD:
366 if (ia->xauth_secret.user_password.ptr != NULL)
367 {
368 out_raw(ia->xauth_secret.user_password.ptr
369 , ia->xauth_secret.user_password.len
370 , &attrval, "xauth_user_password");
371 }
372 break;
373 case XAUTH_STATUS:
374 break;
375 case UNITY_BANNER:
376 if (ia->unity_banner != NULL)
377 {
378 out_raw(ia->unity_banner
379 , strlen(ia->unity_banner)
380 , &attrval, "UNITY_BANNER");
381 }
382 break;
383 default:
384 plog("attempt to send unsupported mode cfg attribute %s."
385 , enum_show(&modecfg_attr_names, attr_type));
386 break;
387 }
388 close_output_pbs(&attrval);
389 }
390 if (!dont_advance)
391 {
392 attr_type++;
393 attr_set >>= 1;
394 }
395 }
396 close_message(&strattr);
397 }
398
399 modecfg_hash(r_hashval, r_hash_start, rbody->cur, st);
400 close_message(rbody);
401 encrypt_message(rbody, st);
402 return STF_OK;
403 }
404
405 /*
406 * Send ModeCfg message
407 */
408 static stf_status
409 modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
410 {
411 pb_stream msg;
412 pb_stream rbody;
413 char buf[BUF_LEN];
414
415 /* set up attr */
416 init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer");
417
418 /* this is the beginning of a new exchange */
419 st->st_msgid = generate_msgid(st);
420 init_phase2_iv(st, &st->st_msgid);
421
422 /* HDR out */
423 {
424 struct isakmp_hdr hdr;
425
426 zero(&hdr); /* default to 0 */
427 hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
428 hdr.isa_np = ISAKMP_NEXT_HASH;
429 hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;
430 hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
431 memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
432 memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
433 hdr.isa_msgid = st->st_msgid;
434
435 if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody))
436 {
437 return STF_INTERNAL_ERROR;
438 }
439 }
440
441 /* ATTR out */
442 modecfg_build_msg(st, &rbody
443 , isama_type
444 , ia
445 , 0 /* XXX isama_id */
446 );
447
448 freeanychunk(st->st_tpacket);
449 clonetochunk(st->st_tpacket, msg.start, pbs_offset(&msg), "ModeCfg msg");
450
451 /* Transmit */
452 send_packet(st, "ModeCfg msg");
453
454 if (st->st_event->ev_type != EVENT_RETRANSMIT)
455 {
456 delete_event(st);
457 event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
458 }
459 return STF_OK;
460 }
461
462 /*
463 * Parse a ModeCfg attribute payload
464 */
465 static stf_status
466 modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
467 {
468 struct isakmp_attribute attr;
469 pb_stream strattr;
470
471 while (pbs_left(attrs) >= sizeof(struct isakmp_attribute))
472 {
473 u_int16_t attr_type;
474 u_int16_t attr_len;
475
476 if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr))
477 {
478 return STF_FAIL;
479 }
480 attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK;
481 attr_len = attr.isaat_lv;
482
483 switch (attr_type)
484 {
485 case INTERNAL_IP4_ADDRESS:
486 if (attr_len == 4)
487 {
488 initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr);
489 }
490 /* fall through to set attribute flag */
491 case INTERNAL_IP4_NETMASK:
492 case INTERNAL_IP4_DNS:
493 case INTERNAL_IP4_SUBNET:
494 case INTERNAL_IP4_NBNS:
495 ia->attr_set |= LELEM(attr_type);
496 break;
497 case APPLICATION_VERSION:
498 if (attr_len > 0)
499 {
500 DBG(DBG_PARSING,
501 DBG_log(" '%.*s'", attr_len, strattr.cur)
502 )
503 }
504 ia->attr_set |= LELEM(attr_type);
505 break;
506 case XAUTH_TYPE:
507 ia->xauth_type = attr.isaat_lv;
508 ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
509 break;
510 case XAUTH_USER_NAME:
511 setchunk(ia->xauth_secret.user_name, strattr.cur, attr_len);
512 ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
513 break;
514 case XAUTH_USER_PASSWORD:
515 setchunk(ia->xauth_secret.user_password, strattr.cur, attr_len);
516 ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
517 break;
518 case XAUTH_STATUS:
519 ia->xauth_status = attr.isaat_lv;
520 ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
521 break;
522 case XAUTH_PASSCODE:
523 case XAUTH_MESSAGE:
524 case XAUTH_CHALLENGE:
525 case XAUTH_DOMAIN:
526 case XAUTH_NEXT_PIN:
527 case XAUTH_ANSWER:
528 ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE);
529 break;
530 case UNITY_DDNS_HOSTNAME:
531 if (attr_len > 0)
532 {
533 DBG(DBG_PARSING,
534 DBG_log(" '%.*s'", attr_len, strattr.cur)
535 )
536 }
537 /* fall through to set attribute flag */
538 case UNITY_BANNER:
539 case UNITY_SAVE_PASSWD:
540 case UNITY_DEF_DOMAIN:
541 case UNITY_SPLITDNS_NAME:
542 case UNITY_SPLIT_INCLUDE:
543 case UNITY_NATT_PORT:
544 case UNITY_LOCAL_LAN:
545 case UNITY_PFS:
546 case UNITY_FW_TYPE:
547 case UNITY_BACKUP_SERVERS:
548 ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE);
549 break;
550 default:
551 plog("unsupported ModeCfg attribute %s received."
552 , enum_show(&modecfg_attr_names, attr_type));
553 break;
554 }
555 }
556 return STF_OK;
557 }
558
559 /*
560 * Parse a ModeCfg message
561 */
562 static stf_status
563 modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
564 , internal_addr_t *ia)
565 {
566 struct state *const st = md->st;
567 struct payload_digest *p;
568 stf_status stat;
569
570 st->st_msgid = md->hdr.isa_msgid;
571
572 CHECK_QUICK_HASH(md, modecfg_hash(hash_val
573 , hash_pbs->roof
574 , md->message_pbs.roof, st)
575 , "MODECFG-HASH", "ISAKMP_CFG_MSG");
576
577 /* process the ModeCfg payloads received */
578 for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
579 {
580 internal_addr_t ia_candidate;
581
582 init_internal_addr(&ia_candidate);
583
584 if (p->payload.attribute.isama_type == isama_type)
585 {
586 *isama_id = p->payload.attribute.isama_identifier;
587
588 stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
589 if (stat == STF_OK)
590 {
591 /* return with a valid set of attributes */
592 *ia = ia_candidate;
593 return STF_OK;
594 }
595 }
596 else
597 {
598 plog("expected %s, got %s instead (ignored)"
599 , enum_name(&attr_msg_type_names, isama_type)
600 , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type));
601
602 stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
603 }
604 if (stat != STF_OK)
605 return stat;
606 }
607 return STF_IGNORE;
608 }
609
610 /*
611 * Send ModeCfg request message from client to server in pull mode
612 */
613 stf_status
614 modecfg_send_request(struct state *st)
615 {
616 stf_status stat;
617 internal_addr_t ia;
618
619 init_internal_addr(&ia);
620
621 ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
622 | LELEM(INTERNAL_IP4_NETMASK);
623
624 plog("sending ModeCfg request");
625 st->st_state = STATE_MODE_CFG_I1;
626 stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
627 if (stat == STF_OK)
628 st->st_modecfg.started = TRUE;
629 return stat;
630 }
631
632 /* STATE_MODE_CFG_R0:
633 * HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP)
634 *
635 * used in ModeCfg pull mode, on the server (responder)
636 */
637 stf_status
638 modecfg_inR0(struct msg_digest *md)
639 {
640 struct state *const st = md->st;
641 u_int16_t isama_id;
642 internal_addr_t ia;
643 bool want_unity_banner;
644 stf_status stat, stat_build;
645
646 stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
647 if (stat != STF_OK)
648 return stat;
649
650 want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
651
652 init_internal_addr(&ia);
653 get_internal_addr(st->st_connection, &ia);
654
655 if (want_unity_banner)
656 {
657 ia.unity_banner = UNITY_BANNER_STR;
658 ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE);
659 }
660
661 plog("sending ModeCfg reply");
662
663 stat_build = modecfg_build_msg(st, &md->rbody
664 , ISAKMP_CFG_REPLY
665 , &ia
666 , isama_id);
667 if (stat_build != STF_OK)
668 return stat_build;
669
670 st->st_msgid = 0;
671 return STF_OK;
672 }
673
674 /* STATE_MODE_CFG_I1:
675 * HDR*, HASH, ATTR(REPLY=IP)
676 *
677 * used in ModeCfg pull mode, on the client (initiator)
678 */
679 stf_status
680 modecfg_inI1(struct msg_digest *md)
681 {
682 struct state *const st = md->st;
683 u_int16_t isama_id;
684 internal_addr_t ia;
685 stf_status stat;
686
687 plog("parsing ModeCfg reply");
688
689 stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
690 if (stat != STF_OK)
691 return stat;
692
693 st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
694 st->st_msgid = 0;
695 return STF_OK;
696 }
697
698
699 /*
700 * Send ModeCfg set message from server to client in push mode
701 */
702 stf_status
703 modecfg_send_set(struct state *st)
704 {
705 stf_status stat;
706 internal_addr_t ia;
707
708 init_internal_addr(&ia);
709 get_internal_addr(st->st_connection, &ia);
710
711 #ifdef CISCO_QUIRKS
712 ia.unity_banner = UNITY_BANNER_STR;
713 ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE);
714 #endif
715
716 plog("sending ModeCfg set");
717 st->st_state = STATE_MODE_CFG_R3;
718 stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
719 if (stat == STF_OK)
720 st->st_modecfg.started = TRUE;
721 return stat;
722 }
723
724 /* STATE_MODE_CFG_I0:
725 * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
726 *
727 * used in ModeCfg push mode, on the client (initiator).
728 */
729 stf_status
730 modecfg_inI0(struct msg_digest *md)
731 {
732 struct state *const st = md->st;
733 u_int16_t isama_id;
734 internal_addr_t ia;
735 lset_t attr_set, unity_attr_set;
736 stf_status stat, stat_build;
737
738 plog("parsing ModeCfg set");
739
740 stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
741 if (stat != STF_OK)
742 return stat;
743
744 st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
745
746 /* prepare ModeCfg ack which sends zero length attributes */
747 attr_set = ia.attr_set;
748 unity_attr_set = ia.unity_attr_set;
749 init_internal_addr(&ia);
750 ia.attr_set = attr_set & SUPPORTED_ATTR_SET;
751 ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET;
752
753 plog("sending ModeCfg ack");
754
755 stat_build = modecfg_build_msg(st, &md->rbody
756 , ISAKMP_CFG_ACK
757 , &ia
758 , isama_id);
759 if (stat_build != STF_OK)
760 return stat_build;
761
762 st->st_msgid = 0;
763 return STF_OK;
764 }
765
766 /* STATE_MODE_CFG_R3:
767 * HDR*, HASH, ATTR(ACK,OK)
768 *
769 * used in ModeCfg push mode, on the server (responder)
770 */
771 stf_status
772 modecfg_inR3(struct msg_digest *md)
773 {
774 struct state *const st = md->st;
775 u_int16_t isama_id;
776 internal_addr_t ia;
777 stf_status stat;
778
779 plog("parsing ModeCfg ack");
780
781 stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
782 if (stat != STF_OK)
783 return stat;
784
785 st->st_msgid = 0;
786 return STF_OK;
787 }
788
789 /*
790 * Send XAUTH credentials request (username + password)
791 */
792 stf_status
793 xauth_send_request(struct state *st)
794 {
795 stf_status stat;
796 internal_addr_t ia;
797
798 init_internal_addr(&ia);
799 ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
800 | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
801
802 plog("sending XAUTH request");
803 st->st_state = STATE_XAUTH_R1;
804 stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
805 if (stat == STF_OK)
806 st->st_xauth.started = TRUE;
807 return stat;
808 }
809
810 /* STATE_XAUTH_I0:
811 * HDR*, HASH, ATTR(REQ) --> HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD)
812 *
813 * used on the XAUTH client (initiator)
814 */
815 stf_status
816 xauth_inI0(struct msg_digest *md)
817 {
818 struct state *const st = md->st;
819 u_int16_t isama_id;
820 internal_addr_t ia;
821 stf_status stat, stat_build;
822
823 plog("parsing XAUTH request");
824
825 stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
826 if (stat != STF_OK)
827 return stat;
828
829 /* check XAUTH attributes */
830 if ((ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY
831 && ia.xauth_type != XAUTH_TYPE_GENERIC)
832 {
833 plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type));
834 stat = STF_FAIL;
835 }
836 else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY)
837 {
838 plog("user name attribute is missing in XAUTH request");
839 stat = STF_FAIL;
840 }
841 else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY)
842 {
843 plog("user password attribute is missing in XAUTH request");
844 stat = STF_FAIL;
845 }
846
847 /* prepare XAUTH reply */
848 init_internal_addr(&ia);
849
850 if (stat == STF_OK)
851 {
852 /* get user credentials using a plugin function */
853 if (!xauth_module.get_secret(&ia.xauth_secret))
854 {
855 plog("xauth user credentials not found");
856 stat = STF_FAIL;
857 }
858 }
859 if (stat == STF_OK)
860 {
861 DBG(DBG_CONTROL,
862 DBG_log("my xauth user name is '%.*s'"
863 , ia.xauth_secret.user_name.len
864 , ia.xauth_secret.user_name.ptr)
865 )
866 DBG(DBG_PRIVATE,
867 DBG_log("my xauth user password is '%.*s'"
868 , ia.xauth_secret.user_password.len
869 , ia.xauth_secret.user_password.ptr)
870 )
871 ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
872 | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
873 }
874 else
875 {
876 ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
877 ia.xauth_status = XAUTH_STATUS_FAIL;
878 }
879
880 plog("sending XAUTH reply");
881
882 stat_build = modecfg_build_msg(st, &md->rbody
883 , ISAKMP_CFG_REPLY
884 , &ia
885 , isama_id);
886 if (stat_build != STF_OK)
887 return stat_build;
888
889 if (stat == STF_OK)
890 {
891 st->st_xauth.started = TRUE;
892 return STF_OK;
893 }
894 else
895 {
896 /* send XAUTH reply msg and then delete ISAKMP SA */
897 freeanychunk(st->st_tpacket);
898 clonetochunk(st->st_tpacket, md->reply.start
899 , pbs_offset(&md->reply), "XAUTH reply msg");
900 send_packet(st, "XAUTH reply msg");
901 delete_state(st);
902 return STF_IGNORE;
903 }
904 }
905
906 /* STATE_XAUTH_R1:
907 * HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS)
908 *
909 * used on the XAUTH server (responder)
910 */
911 stf_status
912 xauth_inR1(struct msg_digest *md)
913 {
914 struct state *const st = md->st;
915 u_int16_t isama_id;
916 internal_addr_t ia;
917 stf_status stat, stat_build;
918
919 plog("parsing XAUTH reply");
920
921 stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
922 if (stat != STF_OK)
923 return stat;
924
925 /* did the client return an XAUTH FAIL status? */
926 if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY)
927 {
928 plog("received FAIL status in XAUTH reply");
929
930 /* client is not able to do XAUTH, delete ISAKMP SA */
931 delete_state(st);
932 return STF_IGNORE;
933 }
934
935 /* check XAUTH reply */
936 if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY)
937 {
938 plog("user name attribute is missing in XAUTH reply");
939 st->st_xauth.status = FALSE;
940 }
941 else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY)
942 {
943 plog("user password attribute is missing in XAUTH reply");
944 st->st_xauth.status = FALSE;
945 }
946 else
947 {
948 DBG(DBG_CONTROL,
949 DBG_log("peer xauth user name is '%.*s'"
950 , ia.xauth_secret.user_name.len
951 , ia.xauth_secret.user_name.ptr)
952 )
953 DBG(DBG_PRIVATE,
954 DBG_log("peer xauth user password is '%.*s'"
955 , ia.xauth_secret.user_password.len
956 , ia.xauth_secret.user_password.ptr)
957 )
958 /* verify the user credentials using a plugn function */
959 st->st_xauth.status = xauth_module.verify_secret(&ia.xauth_secret);
960 plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
961 }
962
963 /* prepare XAUTH set which sends the authentication status */
964 init_internal_addr(&ia);
965 ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
966 ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL;
967
968 plog("sending XAUTH status:");
969
970 stat_build = modecfg_build_msg(st, &md->rbody
971 , ISAKMP_CFG_SET
972 , &ia
973 , isama_id);
974 if (stat_build != STF_OK)
975 return stat_build;
976 return STF_OK;
977 }
978
979 /* STATE_XAUTH_I1:
980 * HDR*, HASH, ATTR(STATUS) --> HDR*, HASH, ATTR(ACK)
981 *
982 * used on the XAUTH client (initiator)
983 */
984 stf_status
985 xauth_inI1(struct msg_digest *md)
986 {
987 struct state *const st = md->st;
988 u_int16_t isama_id;
989 internal_addr_t ia;
990 stf_status stat, stat_build;
991
992 plog("parsing XAUTH status");
993 stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
994 if (stat != STF_OK)
995 {
996 /* notification payload - not exactly the right choice, but okay */
997 md->note = ATTRIBUTES_NOT_SUPPORTED;
998 return stat;
999 }
1000
1001 st->st_xauth.status = ia.xauth_status;
1002 plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
1003
1004 plog("sending XAUTH ack");
1005 init_internal_addr(&ia);
1006 stat_build = modecfg_build_msg(st, &md->rbody
1007 , ISAKMP_CFG_ACK
1008 , &ia
1009 , isama_id);
1010 if (stat_build != STF_OK)
1011 return stat_build;
1012
1013 if (st->st_xauth.status)
1014 {
1015 st->st_msgid = 0;
1016 return STF_OK;
1017 }
1018 else
1019 {
1020 /* send XAUTH ack msg and then delete ISAKMP SA */
1021 freeanychunk(st->st_tpacket);
1022 clonetochunk(st->st_tpacket, md->reply.start
1023 , pbs_offset(&md->reply), "XAUTH ack msg");
1024 send_packet(st, "XAUTH ack msg");
1025 delete_state(st);
1026 return STF_IGNORE;
1027 }
1028 }
1029
1030 /* STATE_XAUTH_R2:
1031 * HDR*, ATTR(STATUS), HASH --> Done
1032 *
1033 * used on the XAUTH server (responder)
1034 */
1035 stf_status
1036 xauth_inR2(struct msg_digest *md)
1037 {
1038 struct state *const st = md->st;
1039 u_int16_t isama_id;
1040 internal_addr_t ia;
1041 stf_status stat;
1042
1043 plog("parsing XAUTH ack");
1044
1045 stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
1046 if (stat != STF_OK)
1047 return stat;
1048
1049 st->st_msgid = 0;
1050 if (st->st_xauth.status)
1051 {
1052 return STF_OK;
1053 }
1054 else
1055 {
1056 delete_state(st);
1057 return STF_IGNORE;
1058 }
1059 }