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