added Cisco Unity ModeCfg attributes
[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 XAUTH_TYPE:
469 ia->xauth_type = attr.isaat_lv;
470 ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
471 break;
472 case XAUTH_USER_NAME:
473 setchunk(ia->xauth_secret.user_name, strattr.cur, attr_len);
474 ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
475 break;
476 case XAUTH_USER_PASSWORD:
477 setchunk(ia->xauth_secret.user_password, strattr.cur, attr_len);
478 ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
479 break;
480 case XAUTH_STATUS:
481 ia->xauth_status = attr.isaat_lv;
482 ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
483 break;
484 default:
485 plog("unsupported ModeCfg attribute %s received."
486 , enum_show(&modecfg_attr_names, attr_type));
487 break;
488 }
489 }
490 return STF_OK;
491 }
492
493 /*
494 * Parse a ModeCfg message
495 */
496 static stf_status
497 modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
498 , internal_addr_t *ia)
499 {
500 struct state *const st = md->st;
501 struct payload_digest *p;
502 stf_status stat;
503
504 st->st_msgid = md->hdr.isa_msgid;
505
506 CHECK_QUICK_HASH(md, modecfg_hash(hash_val
507 , hash_pbs->roof
508 , md->message_pbs.roof, st)
509 , "MODECFG-HASH", "ISAKMP_CFG_MSG");
510
511 /* process the ModeCfg payloads received */
512 for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
513 {
514 internal_addr_t ia_candidate;
515
516 init_internal_addr(&ia_candidate);
517
518 if (p->payload.attribute.isama_type == isama_type)
519 {
520 *isama_id = p->payload.attribute.isama_identifier;
521
522 stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
523 if (stat == STF_OK)
524 {
525 /* return with a valid set of attributes */
526 *ia = ia_candidate;
527 return STF_OK;
528 }
529 }
530 else
531 {
532 plog("expected %s, got %s instead (ignored)"
533 , enum_name(&attr_msg_type_names, isama_type)
534 , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type));
535
536 stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
537 }
538 if (stat != STF_OK)
539 return stat;
540 }
541 return STF_IGNORE;
542 }
543
544 /*
545 * Send ModeCfg request message from client to server in pull mode
546 */
547 stf_status
548 modecfg_send_request(struct state *st)
549 {
550 stf_status stat;
551 internal_addr_t ia;
552
553 init_internal_addr(&ia);
554 ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
555 | LELEM(INTERNAL_IP4_NETMASK);
556
557 plog("sending ModeCfg request");
558 st->st_state = STATE_MODE_CFG_I1;
559 stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
560 if (stat == STF_OK)
561 st->st_modecfg.started = TRUE;
562 return stat;
563 }
564
565 /* STATE_MODE_CFG_R0:
566 * HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP)
567 *
568 * used in ModeCfg pull mode, on the server (responder)
569 */
570 stf_status
571 modecfg_inR0(struct msg_digest *md)
572 {
573 struct state *const st = md->st;
574 u_int16_t isama_id;
575 internal_addr_t ia;
576 stf_status stat, stat_build;
577
578 stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
579 if (stat != STF_OK)
580 return stat;
581
582 get_internal_addr(st->st_connection, &ia);
583
584 plog("sending ModeCfg reply");
585
586 stat_build = modecfg_build_msg(st, &md->rbody
587 , ISAKMP_CFG_REPLY
588 , &ia
589 , isama_id);
590 if (stat_build != STF_OK)
591 return stat_build;
592
593 st->st_msgid = 0;
594 return STF_OK;
595 }
596
597 /* STATE_MODE_CFG_I1:
598 * HDR*, HASH, ATTR(REPLY=IP)
599 *
600 * used in ModeCfg pull mode, on the client (initiator)
601 */
602 stf_status
603 modecfg_inI1(struct msg_digest *md)
604 {
605 struct state *const st = md->st;
606 u_int16_t isama_id;
607 internal_addr_t ia;
608 stf_status stat;
609
610 plog("parsing ModeCfg reply");
611
612 stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
613 if (stat != STF_OK)
614 return stat;
615
616 st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
617 st->st_msgid = 0;
618 return STF_OK;
619 }
620
621
622 /*
623 * Send ModeCfg set message from server to client in push mode
624 */
625 stf_status
626 modecfg_send_set(struct state *st)
627 {
628 stf_status stat;
629 internal_addr_t ia;
630
631 get_internal_addr(st->st_connection, &ia);
632
633 plog("sending ModeCfg set");
634 st->st_state = STATE_MODE_CFG_R3;
635 stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
636 if (stat == STF_OK)
637 st->st_modecfg.started = TRUE;
638 return stat;
639 }
640
641 /* STATE_MODE_CFG_I0:
642 * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
643 *
644 * used in ModeCfg push mode, on the client (initiator).
645 */
646 stf_status
647 modecfg_inI0(struct msg_digest *md)
648 {
649 struct state *const st = md->st;
650 u_int16_t isama_id;
651 internal_addr_t ia;
652 lset_t attr_set;
653 stf_status stat, stat_build;
654
655 plog("parsing ModeCfg set");
656
657 stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
658 if (stat != STF_OK)
659 return stat;
660
661 st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
662
663 /* prepare ModeCfg ack which sends zero length attributes */
664 attr_set = ia.attr_set;
665 init_internal_addr(&ia);
666 ia.attr_set = attr_set & SUPPORTED_ATTR_SET;
667
668 plog("sending ModeCfg ack");
669
670 stat_build = modecfg_build_msg(st, &md->rbody
671 , ISAKMP_CFG_ACK
672 , &ia
673 , isama_id);
674 if (stat_build != STF_OK)
675 return stat_build;
676
677 st->st_msgid = 0;
678 return STF_OK;
679 }
680
681 /* STATE_MODE_CFG_R3:
682 * HDR*, HASH, ATTR(ACK,OK)
683 *
684 * used in ModeCfg push mode, on the server (responder)
685 */
686 stf_status
687 modecfg_inR3(struct msg_digest *md)
688 {
689 struct state *const st = md->st;
690 u_int16_t isama_id;
691 internal_addr_t ia;
692 stf_status stat;
693
694 plog("parsing ModeCfg ack");
695
696 stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
697 if (stat != STF_OK)
698 return stat;
699
700 st->st_msgid = 0;
701 return STF_OK;
702 }
703
704 /*
705 * Send XAUTH credentials request (username + password)
706 */
707 stf_status
708 xauth_send_request(struct state *st)
709 {
710 stf_status stat;
711 internal_addr_t ia;
712
713 init_internal_addr(&ia);
714 ia.attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)
715 | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF);
716
717 plog("sending XAUTH request");
718 st->st_state = STATE_XAUTH_R1;
719 stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
720 if (stat == STF_OK)
721 st->st_xauth.started = TRUE;
722 return stat;
723 }
724
725 /* STATE_XAUTH_I0:
726 * HDR*, HASH, ATTR(REQ) --> HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD)
727 *
728 * used on the XAUTH client (initiator)
729 */
730 stf_status
731 xauth_inI0(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, stat_build;
737
738 plog("parsing XAUTH request");
739
740 stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
741 if (stat != STF_OK)
742 return stat;
743
744 /* check XAUTH attributes */
745 if ((ia.attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY
746 && ia.xauth_type != XAUTH_TYPE_GENERIC)
747 {
748 plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type));
749 stat = STF_FAIL;
750 }
751 else if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
752 {
753 plog("user name attribute is missing in XAUTH request");
754 stat = STF_FAIL;
755 }
756 else if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
757 {
758 plog("user password attribute is missing in XAUTH request");
759 stat = STF_FAIL;
760 }
761
762 /* prepare XAUTH reply */
763 init_internal_addr(&ia);
764
765 if (stat == STF_OK)
766 {
767 /* get user credentials using a plugin function */
768 if (!xauth_module.get_secret(&ia.xauth_secret))
769 {
770 plog("xauth user credentials not found");
771 stat = STF_FAIL;
772 }
773 }
774 if (stat == STF_OK)
775 {
776 DBG(DBG_CONTROL,
777 DBG_log("my xauth user name is '%.*s'"
778 , ia.xauth_secret.user_name.len
779 , ia.xauth_secret.user_name.ptr)
780 )
781 DBG(DBG_PRIVATE,
782 DBG_log("my xauth user password is '%.*s'"
783 , ia.xauth_secret.user_password.len
784 , ia.xauth_secret.user_password.ptr)
785 )
786 ia.attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)
787 | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF);
788 }
789 else
790 {
791 ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
792 ia.xauth_status = FALSE;
793 }
794
795 plog("sending XAUTH reply");
796
797 stat_build = modecfg_build_msg(st, &md->rbody
798 , ISAKMP_CFG_REPLY
799 , &ia
800 , isama_id);
801 if (stat_build != STF_OK)
802 return stat_build;
803
804 if (stat == STF_OK)
805 {
806 st->st_xauth.started = TRUE;
807 return STF_OK;
808 }
809 else
810 {
811 /* send XAUTH reply msg and then delete ISAKMP SA */
812 freeanychunk(st->st_tpacket);
813 clonetochunk(st->st_tpacket, md->reply.start
814 , pbs_offset(&md->reply), "XAUTH reply msg");
815 send_packet(st, "XAUTH reply msg");
816 delete_state(st);
817 return STF_IGNORE;
818 }
819 }
820
821 /* STATE_XAUTH_R1:
822 * HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS)
823 *
824 * used on the XAUTH server (responder)
825 */
826 stf_status
827 xauth_inR1(struct msg_digest *md)
828 {
829 struct state *const st = md->st;
830 u_int16_t isama_id;
831 internal_addr_t ia;
832 stf_status stat, stat_build;
833
834 plog("parsing XAUTH reply");
835
836 stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
837 if (stat != STF_OK)
838 return stat;
839
840 /* did the client return an XAUTH FAIL status? */
841 if ((ia.attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY)
842 {
843 plog("received FAIL status in XAUTH reply");
844
845 /* client is not able to do XAUTH, delete ISAKMP SA */
846 delete_state(st);
847 return STF_IGNORE;
848 }
849
850 /* check XAUTH reply */
851 if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
852 {
853 plog("user name attribute is missing in XAUTH reply");
854 st->st_xauth.status = FALSE;
855 }
856 else if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
857 {
858 plog("user password attribute is missing in XAUTH reply");
859 st->st_xauth.status = FALSE;
860 }
861 else
862 {
863 DBG(DBG_CONTROL,
864 DBG_log("peer xauth user name is '%.*s'"
865 , ia.xauth_secret.user_name.len
866 , ia.xauth_secret.user_name.ptr)
867 )
868 DBG(DBG_PRIVATE,
869 DBG_log("peer xauth user password is '%.*s'"
870 , ia.xauth_secret.user_password.len
871 , ia.xauth_secret.user_password.ptr)
872 )
873 /* verify the user credentials using a plugn function */
874 st->st_xauth.status = xauth_module.verify_secret(&ia.xauth_secret);
875 plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
876 }
877
878 /* prepare XAUTH set which sends the authentication status */
879 init_internal_addr(&ia);
880 ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
881 ia.xauth_status = st->st_xauth.status;
882
883 plog("sending XAUTH status:");
884
885 stat_build = modecfg_build_msg(st, &md->rbody
886 , ISAKMP_CFG_SET
887 , &ia
888 , isama_id);
889 if (stat_build != STF_OK)
890 return stat_build;
891 return STF_OK;
892 }
893
894 /* STATE_XAUTH_I1:
895 * HDR*, HASH, ATTR(STATUS) --> HDR*, HASH, ATTR(ACK)
896 *
897 * used on the XAUTH client (initiator)
898 */
899 stf_status
900 xauth_inI1(struct msg_digest *md)
901 {
902 struct state *const st = md->st;
903 u_int16_t isama_id;
904 internal_addr_t ia;
905 stf_status stat, stat_build;
906
907 plog("parsing XAUTH status");
908 stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
909 if (stat != STF_OK)
910 {
911 /* notification payload - not exactly the right choice, but okay */
912 md->note = ATTRIBUTES_NOT_SUPPORTED;
913 return stat;
914 }
915
916 st->st_xauth.status = ia.xauth_status;
917 plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
918
919 plog("sending XAUTH ack");
920 init_internal_addr(&ia);
921 stat_build = modecfg_build_msg(st, &md->rbody
922 , ISAKMP_CFG_ACK
923 , &ia
924 , isama_id);
925 if (stat_build != STF_OK)
926 return stat_build;
927
928 if (st->st_xauth.status)
929 {
930 st->st_msgid = 0;
931 return STF_OK;
932 }
933 else
934 {
935 /* send XAUTH ack msg and then delete ISAKMP SA */
936 freeanychunk(st->st_tpacket);
937 clonetochunk(st->st_tpacket, md->reply.start
938 , pbs_offset(&md->reply), "XAUTH ack msg");
939 send_packet(st, "XAUTH ack msg");
940 delete_state(st);
941 return STF_IGNORE;
942 }
943 }
944
945 /* STATE_XAUTH_R2:
946 * HDR*, ATTR(STATUS), HASH --> Done
947 *
948 * used on the XAUTH server (responder)
949 */
950 stf_status
951 xauth_inR2(struct msg_digest *md)
952 {
953 struct state *const st = md->st;
954 u_int16_t isama_id;
955 internal_addr_t ia;
956 stf_status stat;
957
958 plog("parsing XAUTH ack");
959
960 stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
961 if (stat != STF_OK)
962 return stat;
963
964 st->st_msgid = 0;
965 if (st->st_xauth.status)
966 {
967 return STF_OK;
968 }
969 else
970 {
971 delete_state(st);
972 return STF_IGNORE;
973 }
974 }