]> git.ipfire.org Git - thirdparty/strongswan.git/blob - programs/pluto/modecfg.c
- import of strongswan-2.7.0
[thirdparty/strongswan.git] / programs / 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 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * RCSID $Id: modecfg.c,v 1.6 2006/04/24 20:44:57 as Exp $
17 *
18 * This code originally written by Colubris Networks, Inc.
19 * Extraction of patch and porting to 1.99 codebases by Xelerance Corporation
20 * Porting to 2.x by Sean Mathews
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <freeswan.h>
28
29 #include "constants.h"
30 #include "defs.h"
31 #include "state.h"
32 #include "demux.h"
33 #include "timer.h"
34 #include "ipsec_doi.h"
35 #include "log.h"
36 #include "md5.h"
37 #include "sha1.h"
38 #include "crypto.h"
39 #include "modecfg.h"
40 #include "whack.h"
41
42 /*
43 * Addresses assigned (usually via MODE_CONFIG) to the Initiator
44 */
45 struct internal_addr
46 {
47 ip_address ipaddr;
48 ip_address dns[2];
49 ip_address wins[2];
50 };
51
52 /*
53 * Get inside IP address for a connection
54 */
55 static void
56 get_internal_addresses(struct connection *c, struct internal_addr *ia)
57 {
58 zero(ia);
59
60 if (isanyaddr(&c->spd.that.host_srcip))
61 {
62 /* not defined in connection - fetch it from LDAP */
63 }
64 else
65 {
66 ia->ipaddr = c->spd.that.host_srcip;
67 }
68 }
69
70 /*
71 * Compute HASH of Mode Config.
72 */
73 static size_t
74 mode_cfg_hash(u_char *dest, const u_char *start, const u_char *roof
75 , const struct state *st)
76 {
77 struct hmac_ctx ctx;
78
79 hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);
80 hmac_update(&ctx, (const u_char *) &st->st_msgid, sizeof(st->st_msgid));
81 hmac_update(&ctx, start, roof-start);
82 hmac_final(dest, &ctx);
83
84 DBG(DBG_CRYPT,
85 DBG_log("MODE CFG: HASH computed:");
86 DBG_dump("", dest, ctx.hmac_digest_size)
87 )
88 return ctx.hmac_digest_size;
89 }
90
91
92 /* Mode Config Reply
93 * Generates a reply stream containing Mode Config information (eg: IP, DNS, WINS)
94 */
95 stf_status modecfg_resp(struct state *st
96 , u_int resp
97 , pb_stream *rbody
98 , u_int16_t replytype
99 , bool hackthat
100 , u_int16_t ap_id)
101 {
102 u_char *r_hash_start,*r_hashval;
103
104 /* START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_ATTR); */
105
106 {
107 pb_stream hash_pbs;
108 int np = ISAKMP_NEXT_ATTR;
109
110 if (!out_generic(np, &isakmp_hash_desc, rbody, &hash_pbs))
111 return STF_INTERNAL_ERROR;
112 r_hashval = hash_pbs.cur; /* remember where to plant value */
113 if (!out_zero(st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH"))
114 return STF_INTERNAL_ERROR;
115 close_output_pbs(&hash_pbs);
116 r_hash_start = (rbody)->cur; /* hash from after HASH payload */
117 }
118
119 /* ATTR out */
120 {
121 struct isakmp_mode_attr attrh;
122 struct isakmp_attribute attr;
123 pb_stream strattr,attrval;
124 int attr_type;
125 struct internal_addr ia;
126 int dns_idx, wins_idx;
127 bool dont_advance;
128
129 attrh.isama_np = ISAKMP_NEXT_NONE;
130 attrh.isama_type = replytype;
131
132 attrh.isama_identifier = ap_id;
133 if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
134 return STF_INTERNAL_ERROR;
135
136 get_internal_addresses(st->st_connection, &ia);
137
138 if (!isanyaddr(&ia.dns[0])) /* We got DNS addresses, answer with those */
139 resp |= LELEM(INTERNAL_IP4_DNS);
140 else
141 resp &= ~LELEM(INTERNAL_IP4_DNS);
142
143 if (!isanyaddr(&ia.wins[0])) /* We got WINS addresses, answer with those */
144 resp |= LELEM(INTERNAL_IP4_NBNS);
145 else
146 resp &= ~LELEM(INTERNAL_IP4_NBNS);
147
148 if (hackthat)
149 {
150 if (memcmp(&st->st_connection->spd.that.client.addr
151 ,&ia.ipaddr
152 ,sizeof(ia.ipaddr)) != 0)
153 {
154 /* Make the Internal IP address and Netmask
155 * as that client address
156 */
157 st->st_connection->spd.that.client.addr = ia.ipaddr;
158 st->st_connection->spd.that.client.maskbits = 32;
159 st->st_connection->spd.that.has_client = TRUE;
160 }
161 }
162
163 attr_type = 0;
164 dns_idx = 0;
165 wins_idx = 0;
166
167 while (resp != 0)
168 {
169 dont_advance = FALSE;
170 if (resp & 1)
171 {
172 const u_char *byte_ptr;
173 u_int len;
174
175 /* ISAKMP attr out */
176 attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
177 out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
178
179 switch (attr_type)
180 {
181 case INTERNAL_IP4_ADDRESS:
182 {
183 char srcip[ADDRTOT_BUF];
184
185 addrtot(&ia.ipaddr, 0, srcip, sizeof(srcip));
186 plog("assigning virtual IP source address %s", srcip);
187 len = addrbytesptr(&ia.ipaddr, &byte_ptr);
188 out_raw(byte_ptr,len,&attrval,"IP4_addr");
189 }
190 break;
191 case INTERNAL_IP4_NETMASK:
192 {
193 u_int mask;
194 #if 0
195 char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
196 int t,m=st->st_connection->that.host_addr.maskbit;
197 for (t=0; t<4; t++)
198 {
199 if (m < 8)
200 mask[t] = bits[m];
201 else
202 mask[t] = 0xff;
203 m -= 8;
204 }
205 #endif
206 if (st->st_connection->spd.this.client.maskbits == 0)
207 mask = 0;
208 else
209 mask = 0xffffffff * 1;
210 out_raw(&mask,4,&attrval,"IP4_mask");
211 }
212 break;
213 case INTERNAL_IP4_SUBNET:
214 {
215 char mask[4];
216 char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};
217 int t;
218 int m = st->st_connection->spd.this.client.maskbits;
219
220 for (t = 0; t < 4; t++)
221 {
222 if (m < 8)
223 mask[t] = bits[m];
224 else
225 mask[t] = 0xff;
226 m -= 8;
227 if (m < 0)
228 m = 0;
229 }
230 len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr);
231 out_raw(byte_ptr,len,&attrval,"IP4_subnet");
232 out_raw(mask,sizeof(mask),&attrval,"IP4_submsk");
233 }
234 break;
235 case INTERNAL_IP4_DNS:
236 len = addrbytesptr(&ia.dns[dns_idx++], &byte_ptr);
237 out_raw(byte_ptr,len,&attrval,"IP4_dns");
238 if (dns_idx < 2 && !isanyaddr(&ia.dns[dns_idx]))
239 {
240 dont_advance = TRUE;
241 }
242 break;
243 case INTERNAL_IP4_NBNS:
244 len = addrbytesptr(&ia.wins[wins_idx++], &byte_ptr);
245 out_raw(byte_ptr,len,&attrval,"IP4_wins");
246 if (wins_idx < 2 && !isanyaddr(&ia.wins[wins_idx]))
247 {
248 dont_advance = TRUE;
249 }
250 break;
251 default:
252 plog("attempt to send unsupported mode cfg attribute %s."
253 , enum_show(&modecfg_attr_names, attr_type));
254 break;
255 }
256 close_output_pbs(&attrval);
257
258 }
259 if (!dont_advance)
260 {
261 attr_type++;
262 resp >>= 1;
263 }
264 }
265 close_message(&strattr);
266 }
267
268 mode_cfg_hash(r_hashval,r_hash_start,rbody->cur,st);
269 close_message(rbody);
270 encrypt_message(rbody, st);
271 return STF_OK;
272 }
273
274 /* Set MODE_CONFIG data to client.
275 * Pack IP Addresses, DNS, etc... and ship
276 */
277 stf_status modecfg_send_set(struct state *st)
278 {
279 pb_stream reply,rbody;
280 char buf[256];
281
282 /* set up reply */
283 init_pbs(&reply, buf, sizeof(buf), "ModecfgR1");
284
285 st->st_state = STATE_MODE_CFG_R1;
286 /* HDR out */
287 {
288 struct isakmp_hdr hdr;
289
290 zero(&hdr); /* default to 0 */
291 hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
292 hdr.isa_np = ISAKMP_NEXT_HASH;
293 hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;
294 hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
295 memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
296 memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
297 hdr.isa_msgid = st->st_msgid;
298
299 if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
300 {
301 return STF_INTERNAL_ERROR;
302 }
303 }
304
305 #define MODECFG_SET_ITEM ( LELEM(INTERNAL_IP4_ADDRESS) | LELEM(INTERNAL_IP4_SUBNET) | LELEM(INTERNAL_IP4_NBNS) | LELEM(INTERNAL_IP4_DNS) )
306
307 modecfg_resp(st, MODECFG_SET_ITEM
308 , &rbody
309 , ISAKMP_CFG_SET
310 , TRUE
311 , 0/* XXX ID */);
312 #undef MODECFG_SET_ITEM
313
314 clonetochunk(st->st_tpacket, reply.start
315 , pbs_offset(&reply), "ModeCfg set");
316
317 /* Transmit */
318 send_packet(st, "ModeCfg set");
319
320 /* RETRANSMIT if Main, SA_REPLACE if Aggressive */
321 if (st->st_event->ev_type != EVENT_RETRANSMIT
322 && st->st_event->ev_type != EVENT_NULL)
323 {
324 delete_event(st);
325 event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
326 }
327
328 return STF_OK;
329 }
330
331 /* Set MODE_CONFIG data to client.
332 * Pack IP Addresses, DNS, etc... and ship
333 */
334 stf_status
335 modecfg_start_set(struct state *st)
336 {
337 if (st->st_msgid == 0)
338 {
339 /* pick a new message id */
340 st->st_msgid = generate_msgid(st);
341 }
342 st->st_modecfg.vars_set = TRUE;
343
344 return modecfg_send_set(st);
345 }
346
347 /*
348 * Send modecfg IP address request (IP4 address)
349 */
350 stf_status
351 modecfg_send_request(struct state *st)
352 {
353 pb_stream reply;
354 pb_stream rbody;
355 char buf[256];
356 u_char *r_hash_start,*r_hashval;
357
358 /* set up reply */
359 init_pbs(&reply, buf, sizeof(buf), "modecfg_buf");
360
361 plog("sending ModeCfg request");
362
363 /* this is the beginning of a new exchange */
364 st->st_msgid = generate_msgid(st);
365 st->st_state = STATE_MODE_CFG_I1;
366
367 /* HDR out */
368 {
369 struct isakmp_hdr hdr;
370
371 zero(&hdr); /* default to 0 */
372 hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
373 hdr.isa_np = ISAKMP_NEXT_HASH;
374 hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;
375 hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;
376 memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
377 memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);
378 hdr.isa_msgid = st->st_msgid;
379
380 if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))
381 {
382 return STF_INTERNAL_ERROR;
383 }
384 }
385
386 START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_ATTR);
387
388 /* ATTR out */
389 {
390 struct isakmp_mode_attr attrh;
391 struct isakmp_attribute attr;
392 pb_stream strattr;
393
394 attrh.isama_np = ISAKMP_NEXT_NONE;
395 attrh.isama_type = ISAKMP_CFG_REQUEST;
396 attrh.isama_identifier = 0;
397 if (!out_struct(&attrh, &isakmp_attr_desc, &rbody, &strattr))
398 return STF_INTERNAL_ERROR;
399 /* ISAKMP attr out (ipv4) */
400 attr.isaat_af_type = INTERNAL_IP4_ADDRESS;
401 attr.isaat_lv = 0;
402 out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, NULL);
403
404 /* ISAKMP attr out (netmask) */
405 attr.isaat_af_type = INTERNAL_IP4_NETMASK;
406 attr.isaat_lv = 0;
407 out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, NULL);
408
409 close_message(&strattr);
410 }
411
412 mode_cfg_hash(r_hashval,r_hash_start,rbody.cur,st);
413
414 close_message(&rbody);
415 close_output_pbs(&reply);
416
417 init_phase2_iv(st, &st->st_msgid);
418 encrypt_message(&rbody, st);
419
420 clonetochunk(st->st_tpacket, reply.start, pbs_offset(&reply)
421 , "modecfg: req");
422
423 /* Transmit */
424 send_packet(st, "modecfg: req");
425
426 /* RETRANSMIT if Main, SA_REPLACE if Aggressive */
427 if (st->st_event->ev_type != EVENT_RETRANSMIT)
428 {
429 delete_event(st);
430 event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0 * 3, st);
431 }
432 st->st_modecfg.started = TRUE;
433
434 return STF_OK;
435 }
436
437 /*
438 * parse a modecfg attribute payload
439 */
440 static stf_status
441 modecfg_parse_attributes(pb_stream *attrs, u_int *set)
442 {
443 struct isakmp_attribute attr;
444 pb_stream strattr;
445
446 while (pbs_left(attrs) > sizeof(struct isakmp_attribute))
447 {
448 if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr))
449 {
450 int len = (attr.isaat_af_type & 0x8000)? 4 : attr.isaat_lv;
451
452 if (len < 4)
453 {
454 plog("Attribute was too short: %d", len);
455 return STF_FAIL;
456 }
457
458 attrs->cur += len;
459 }
460
461 switch (attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK )
462 {
463 case INTERNAL_IP4_ADDRESS:
464 case INTERNAL_IP4_NETMASK:
465 case INTERNAL_IP4_DNS:
466 case INTERNAL_IP4_SUBNET:
467 case INTERNAL_IP4_NBNS:
468 *set |= LELEM(attr.isaat_af_type);
469 break;
470 default:
471 plog("unsupported mode cfg attribute %s received."
472 , enum_show(&modecfg_attr_names
473 , attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK ));
474 break;
475 }
476 }
477 return STF_OK;
478 }
479
480 /* STATE_MODE_CFG_R0:
481 * HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP)
482 *
483 * This state occurs both in the responder and in the initiator.
484 *
485 * In the responding server, it occurs when the client *asks* for an IP
486 * address or other information.
487 *
488 * Otherwise, it occurs in the initiator when the server sends a challenge
489 * a set, or has a reply to our request.
490 */
491 stf_status
492 modecfg_inR0(struct msg_digest *md)
493 {
494 struct state *const st = md->st;
495 struct payload_digest *p;
496 stf_status stat;
497
498 plog("received ModeCfg request");
499
500 st->st_msgid = md->hdr.isa_msgid;
501 CHECK_QUICK_HASH(md, mode_cfg_hash(hash_val
502 ,hash_pbs->roof
503 , md->message_pbs.roof, st)
504 , "MODECFG-HASH", "MODE R0");
505
506 /* process the MODECFG payloads therein */
507 for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
508 {
509 u_int set_modecfg_attrs = LEMPTY;
510
511 switch (p->payload.attribute.isama_type)
512 {
513 default:
514 plog("Expecting ISAKMP_CFG_REQUEST, got %s instead (ignored)."
515 , enum_name(&attr_msg_type_names
516 , p->payload.attribute.isama_type));
517
518 stat = modecfg_parse_attributes(&p->pbs, &set_modecfg_attrs);
519 if (stat != STF_OK)
520 return stat;
521 break;
522
523 case ISAKMP_CFG_REQUEST:
524 stat = modecfg_parse_attributes(&p->pbs, &set_modecfg_attrs);
525 if (stat != STF_OK)
526 return stat;
527
528 stat = modecfg_resp(st, set_modecfg_attrs
529 ,&md->rbody
530 ,ISAKMP_CFG_REPLY
531 ,TRUE
532 ,p->payload.attribute.isama_identifier);
533
534 if (stat != STF_OK)
535 {
536 /* notification payload - not exactly the right choice, but okay */
537 md->note = CERTIFICATE_UNAVAILABLE;
538 return stat;
539 }
540
541 /* they asked us, we responded, msgid is done */
542 st->st_msgid = 0;
543 }
544 }
545 return STF_OK;
546 }
547
548 /* STATE_MODE_CFG_R2:
549 * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
550 *
551 * used in server push mode, on the client (initiator).
552 */
553 static stf_status
554 modecfg_inI2(struct msg_digest *md)
555 {
556 struct state *const st = md->st;
557 pb_stream *attrs = &md->chain[ISAKMP_NEXT_ATTR]->pbs;
558 int resp = LEMPTY;
559 stf_status stat;
560 struct payload_digest *p;
561 u_int16_t isama_id = 0;
562
563 st->st_msgid = md->hdr.isa_msgid;
564 CHECK_QUICK_HASH(md
565 , mode_cfg_hash(hash_val
566 ,hash_pbs->roof
567 , md->message_pbs.roof
568 , st)
569 , "MODECFG-HASH", "MODE R1");
570
571 for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
572 {
573 struct isakmp_attribute attr;
574 pb_stream strattr;
575
576 isama_id = p->payload.attribute.isama_identifier;
577
578 if (p->payload.attribute.isama_type != ISAKMP_CFG_SET)
579 {
580 plog("Expecting MODE_CFG_SET, got %x instead."
581 ,md->chain[ISAKMP_NEXT_ATTR]->payload.attribute.isama_type);
582 return STF_IGNORE;
583 }
584
585 /* CHECK that SET has been received. */
586
587 while (pbs_left(attrs) > sizeof(struct isakmp_attribute))
588 {
589 if (!in_struct(&attr, &isakmp_modecfg_attribute_desc
590 , attrs, &strattr))
591 {
592 int len;
593
594 /* Skip unknown */
595 if (attr.isaat_af_type & 0x8000)
596 len = 4;
597 else
598 len = attr.isaat_lv;
599
600 if (len < 4)
601 {
602 plog("Attribute was too short: %d", len);
603 return STF_FAIL;
604 }
605
606 attrs->cur += len;
607 }
608
609 switch (attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK )
610 {
611 case INTERNAL_IP4_ADDRESS:
612 {
613 struct connection *c = st->st_connection;
614 ip_address a;
615 u_int32_t *ap = (u_int32_t *)(strattr.cur);
616 a.u.v4.sin_family = AF_INET;
617
618 memcpy(&a.u.v4.sin_addr.s_addr, ap
619 , sizeof(a.u.v4.sin_addr.s_addr));
620
621 if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0
622 || isanyaddr(&c->spd.this.host_srcip))
623 {
624 char srcip[ADDRTOT_BUF];
625
626 c->spd.this.host_srcip = a;
627 addrtot(&a, 0, srcip, sizeof(srcip));
628 plog("setting virtual IP source address to %s", srcip);
629 }
630
631 /* setting client subnet as srcip/32 */
632 addrtosubnet(&a, &c->spd.this.client);
633 c->spd.this.has_client = TRUE;
634 }
635 resp |= LELEM(attr.isaat_af_type);
636 break;
637 case INTERNAL_IP4_NETMASK:
638 case INTERNAL_IP4_DNS:
639 case INTERNAL_IP4_SUBNET:
640 case INTERNAL_IP4_NBNS:
641 resp |= LELEM(attr.isaat_af_type);
642 break;
643 default:
644 plog("unsupported mode cfg attribute %s received."
645 , enum_show(&modecfg_attr_names, (attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK )));
646 break;
647 }
648 }
649 }
650
651 /* ack things */
652 stat = modecfg_resp(st, resp
653 ,&md->rbody
654 ,ISAKMP_CFG_ACK
655 ,FALSE
656 ,isama_id);
657
658 if (stat != STF_OK)
659 {
660 /* notification payload - not exactly the right choice, but okay */
661 md->note = CERTIFICATE_UNAVAILABLE;
662 return stat;
663 }
664
665 /*
666 * we are done with this exchange, clear things so
667 * that we can start phase 2 properly
668 */
669 st->st_msgid = 0;
670
671 if (resp)
672 {
673 st->st_modecfg.vars_set = TRUE;
674 }
675 return STF_OK;
676 }
677
678 /* STATE_MODE_CFG_R1:
679 * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
680 */
681 stf_status
682 modecfg_inR1(struct msg_digest *md)
683 {
684 struct state *const st = md->st;
685 pb_stream *attrs = &md->chain[ISAKMP_NEXT_ATTR]->pbs;
686 int set_modecfg_attrs = LEMPTY;
687 stf_status stat;
688 struct payload_digest *p;
689
690 plog("parsing ModeCfg reply");
691
692 st->st_msgid = md->hdr.isa_msgid;
693 CHECK_QUICK_HASH(md, mode_cfg_hash(hash_val,hash_pbs->roof, md->message_pbs.roof, st)
694 , "MODECFG-HASH", "MODE R1");
695
696
697 /* process the MODECFG payloads therein */
698 for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next)
699 {
700 struct isakmp_attribute attr;
701 pb_stream strattr;
702
703 attrs = &p->pbs;
704
705 switch (p->payload.attribute.isama_type)
706 {
707 default:
708 {
709 plog("Expecting MODE_CFG_ACK, got %x instead."
710 ,md->chain[ISAKMP_NEXT_ATTR]->payload.attribute.isama_type);
711 return STF_IGNORE;
712 }
713 break;
714
715 case ISAKMP_CFG_ACK:
716 /* CHECK that ACK has been received. */
717 stat = modecfg_parse_attributes(attrs, &set_modecfg_attrs);
718 if (stat != STF_OK)
719 return stat;
720 break;
721
722 case ISAKMP_CFG_REPLY:
723 while (pbs_left(attrs) > sizeof(struct isakmp_attribute))
724 {
725 if (!in_struct(&attr, &isakmp_modecfg_attribute_desc
726 , attrs, &strattr))
727 {
728 /* Skip unknown */
729 int len;
730 if (attr.isaat_af_type & 0x8000)
731 len = 4;
732 else
733 len = attr.isaat_lv;
734
735 if (len < 4)
736 {
737 plog("Attribute was too short: %d", len);
738 return STF_FAIL;
739 }
740
741 attrs->cur += len;
742 }
743
744 switch (attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK )
745 {
746 case INTERNAL_IP4_ADDRESS:
747 {
748 struct connection *c = st->st_connection;
749 ip_address a;
750 u_int32_t *ap = (u_int32_t *)(strattr.cur);
751 a.u.v4.sin_family = AF_INET;
752
753 memcpy(&a.u.v4.sin_addr.s_addr, ap
754 , sizeof(a.u.v4.sin_addr.s_addr));
755
756 if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0
757 || isanyaddr(&c->spd.this.host_srcip))
758 {
759 char srcip[ADDRTOT_BUF];
760
761 c->spd.this.host_srcip = a;
762 addrtot(&a, 0, srcip, sizeof(srcip));
763 plog("setting virtual IP source address to %s", srcip);
764 }
765
766 /* setting client subnet as srcip/32 */
767 addrtosubnet(&a, &c->spd.this.client);
768 setportof(0, &c->spd.this.client.addr);
769 c->spd.this.has_client = TRUE;
770 }
771 /* fall through to set attribute flage */
772
773 case INTERNAL_IP4_NETMASK:
774 case INTERNAL_IP4_DNS:
775 case INTERNAL_IP4_SUBNET:
776 case INTERNAL_IP4_NBNS:
777 set_modecfg_attrs |= LELEM(attr.isaat_af_type);
778 break;
779 default:
780 plog("unsupported mode cfg attribute %s received."
781 , enum_show(&modecfg_attr_names
782 , (attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK )));
783 break;
784 }
785 }
786 break;
787 }
788 }
789
790 /* we are done with this exchange, clear things so that we can start phase 2 properly */
791 st->st_msgid = 0;
792
793 if (set_modecfg_attrs)
794 {
795 st->st_modecfg.vars_set = TRUE;
796 }
797 return STF_OK;
798 }