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