Bug Summary

File:src/sbin/isakmpd/isakmp_cfg.c
Warning:line 126, column 2
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name isakmp_cfg.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/isakmpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/isakmpd -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/isakmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/isakmpd/isakmp_cfg.c
1/* $OpenBSD: isakmp_cfg.c,v 1.41 2018/01/15 09:54:48 mpi Exp $ */
2
3/*
4 * Copyright (c) 2001 Niklas Hallqvist. All rights reserved.
5 * Copyright (c) 2002 Håkan Olsson. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * This code was written under funding by Gatespace
30 * (http://www.gatespace.com/).
31 */
32
33#include <sys/types.h>
34#include <stdlib.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37#include <string.h>
38#include <bitstring.h>
39
40#include "attribute.h"
41#include "conf.h"
42#include "exchange.h"
43#include "hash.h"
44#include "ipsec.h"
45#include "isakmp_fld.h"
46#include "isakmp_num.h"
47#include "log.h"
48#include "message.h"
49#include "prf.h"
50#include "sa.h"
51#include "transport.h"
52#include "util.h"
53
54/*
55 * Validation script used to test messages for correct content of
56 * payloads depending on the exchange type.
57 */
58int16_t script_transaction[] = {
59 ISAKMP_PAYLOAD_ATTRIBUTE14, /* Initiator -> responder. */
60 EXCHANGE_SCRIPT_SWITCH-3,
61 ISAKMP_PAYLOAD_ATTRIBUTE14, /* Responder -> initiator. */
62 EXCHANGE_SCRIPT_END-4
63};
64
65static int cfg_decode_attribute(u_int16_t, u_int8_t *, u_int16_t, void *);
66static int cfg_encode_attributes(struct isakmp_cfg_attr_head *, u_int32_t,
67 u_int32_t, char *, u_int8_t **, u_int16_t *);
68static int cfg_initiator_send_ATTR(struct message *);
69static int cfg_initiator_recv_ATTR(struct message *);
70static int cfg_responder_recv_ATTR(struct message *);
71static int cfg_responder_send_ATTR(struct message *);
72
73u_int8_t *cfg_add_hash(struct message *);
74int cfg_finalize_hash(struct message *, u_int8_t *, u_int8_t *,
75 u_int16_t);
76int cfg_verify_hash(struct message *);
77
78/* Server: SET/ACK Client; REQ/REPLY */
79int (*isakmp_cfg_initiator[]) (struct message *) = {
80 cfg_initiator_send_ATTR,
81 cfg_initiator_recv_ATTR
82};
83
84/* Server: REQ/REPLY Client: SET/ACK */
85int (*isakmp_cfg_responder[]) (struct message *) = {
86 cfg_responder_recv_ATTR,
87 cfg_responder_send_ATTR
88};
89
90/*
91 * When we are "the server", this starts SET/ACK mode
92 * When we are "the client", this starts REQ/REPLY mode
93 */
94static int
95cfg_initiator_send_ATTR(struct message *msg)
96{
97 struct sa *isakmp_sa = msg->isakmp_sa;
98 struct ipsec_exch *ie = msg->exchange->data;
99 u_int8_t *hashp = 0, *attrp, *attr;
100 size_t attrlen, off;
101 char *id_string, *cfg_mode, *field;
102 struct sockaddr *sa;
103#define CFG_ATTR_BIT_MAX16 ISAKMP_CFG_ATTR_FUTURE_MIN16 /* XXX */
104 bitstr_t bit_decl(attrbits, CFG_ATTR_BIT_MAX)((attrbits)[(((16) + 7) >> 3)]);
105 u_int16_t bit, length;
106 u_int32_t life;
107
108 if (msg->exchange->phase == 2) {
1
Assuming field 'phase' is not equal to 2
2
Taking false branch
109 hashp = cfg_add_hash(msg);
110 if (!hashp)
111 return -1;
112 }
113 /* We initiated this exchange, check isakmp_sa for other side. */
114 if (isakmp_sa->initiator)
3
Assuming field 'initiator' is 0
4
Taking false branch
115 id_string = ipsec_id_string(isakmp_sa->id_r,
116 isakmp_sa->id_r_len);
117 else
118 id_string = ipsec_id_string(isakmp_sa->id_i,
119 isakmp_sa->id_i_len);
120 if (!id_string) {
5
Assuming 'id_string' is non-null
6
Taking false branch
121 log_print("cfg_initiator_send_ATTR: cannot parse ID");
122 goto fail;
123 }
124 /* Check for attribute list to send to the other side */
125 attrlen = 0;
126 bit_nclear(attrbits, 0, CFG_ATTR_BIT_MAX - 1)do { register bitstr_t *__name = (attrbits); register int __start
= (0), __stop = (16 - 1); while (__start <= __stop) { ((__name
)[((__start) >> 3)] &= ~(1 << ((__start)&
0x7))); __start++; } } while(0)
;
7
Loop condition is true. Entering loop body
8
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage
127
128 cfg_mode = conf_get_str(id_string, "Mode");
129 if (!cfg_mode || strcmp(cfg_mode, "SET") == 0) {
130 /* SET/ACK mode */
131 ie->cfg_type = ISAKMP_CFG_SET3;
132
133 LOG_DBG((LOG_NEGOTIATION, 10,log_debug (LOG_NEGOTIATION, 10, "cfg_initiator_send_ATTR: SET/ACK mode"
)
134 "cfg_initiator_send_ATTR: SET/ACK mode"))log_debug (LOG_NEGOTIATION, 10, "cfg_initiator_send_ATTR: SET/ACK mode"
)
;
135
136#define ATTRFIND(STR,ATTR4,LEN4,ATTR6,LEN6) do \
137 { \
138 if ((sa = conf_get_address (id_string, STR)) != NULL((void *)0)) \
139 switch (sa->sa_family) { \
140 case AF_INET2: \
141 bit_set (attrbits, ATTR4)((attrbits)[((ATTR4) >> 3)] |= (1 << ((ATTR4)&
0x7)))
; \
142 attrlen += ISAKMP_ATTR_SZ4 + LEN4; \
143 break; \
144 case AF_INET624: \
145 bit_set (attrbits, ATTR6)((attrbits)[((ATTR6) >> 3)] |= (1 << ((ATTR6)&
0x7)))
; \
146 attrlen += ISAKMP_ATTR_SZ4 + LEN6; \
147 break; \
148 default: \
149 break; \
150 } \
151 free (sa); \
152 } while (0)
153
154 /*
155 * XXX We don't simultaneously support IPv4 and IPv6
156 * addresses.
157 */
158 ATTRFIND("Address", ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS1, 4,
159 ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS8, 16);
160 ATTRFIND("Netmask", ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK2, 4,
161 ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK9, 16);
162 ATTRFIND("Nameserver", ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS3, 4,
163 ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS10, 16);
164 ATTRFIND("WINS-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS4, 4,
165 ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS11, 16);
166 ATTRFIND("DHCP-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP6, 4,
167 ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP12, 16);
168#ifdef notyet
169 ATTRFIND("Network", ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET13, 8,
170 ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET15, 17);
171#endif
172#undef ATTRFIND
173
174 if (conf_get_str(id_string, "Lifetime")) {
175 bit_set(attrbits,((attrbits)[((5) >> 3)] |= (1 << ((5)&0x7)))
176 ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY)((attrbits)[((5) >> 3)] |= (1 << ((5)&0x7)));
177 attrlen += ISAKMP_ATTR_SZ4 + 4;
178 }
179 } else {
180 struct conf_list *alist;
181 struct conf_list_node *anode;
182
183 ie->cfg_type = ISAKMP_CFG_REQUEST1;
184
185 LOG_DBG((LOG_NEGOTIATION, 10,log_debug (LOG_NEGOTIATION, 10, "cfg_initiator_send_ATTR: REQ/REPLY mode"
)
186 "cfg_initiator_send_ATTR: REQ/REPLY mode"))log_debug (LOG_NEGOTIATION, 10, "cfg_initiator_send_ATTR: REQ/REPLY mode"
)
;
187
188 alist = conf_get_list(id_string, "Attributes");
189 if (alist) {
190 for (anode = TAILQ_FIRST(&alist->fields)((&alist->fields)->tqh_first); anode;
191 anode = TAILQ_NEXT(anode, link)((anode)->link.tqe_next)) {
192 if (strcasecmp(anode->field, "Address") == 0) {
193 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS)((attrbits)[((1) >> 3)] |= (1 << ((1)&0x7)));
194 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS)((attrbits)[((8) >> 3)] |= (1 << ((8)&0x7)));
195 attrlen += ISAKMP_ATTR_SZ4 * 2;
196 } else if (strcasecmp(anode->field, "Netmask")
197 == 0) {
198 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK)((attrbits)[((2) >> 3)] |= (1 << ((2)&0x7)));
199 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK)((attrbits)[((9) >> 3)] |= (1 << ((9)&0x7)));
200 attrlen += ISAKMP_ATTR_SZ4 * 2;
201 } else if (strcasecmp(anode->field,
202 "Nameserver") == 0) {
203 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS)((attrbits)[((3) >> 3)] |= (1 << ((3)&0x7)));
204 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS)((attrbits)[((10) >> 3)] |= (1 << ((10)&0x7))
)
;
205 attrlen += ISAKMP_ATTR_SZ4 * 2;
206 } else if (strcasecmp(anode->field,
207 "WINS-server") == 0) {
208 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS)((attrbits)[((4) >> 3)] |= (1 << ((4)&0x7)));
209 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS)((attrbits)[((11) >> 3)] |= (1 << ((11)&0x7))
)
;
210 attrlen += ISAKMP_ATTR_SZ4 * 2;
211 } else if (strcasecmp(anode->field,
212 "DHCP-server") == 0) {
213 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP)((attrbits)[((6) >> 3)] |= (1 << ((6)&0x7)));
214 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP)((attrbits)[((12) >> 3)] |= (1 << ((12)&0x7))
)
;
215 attrlen += ISAKMP_ATTR_SZ4 * 2;
216 } else if (strcasecmp(anode->field,
217 "Lifetime") == 0) {
218 bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY)((attrbits)[((5) >> 3)] |= (1 << ((5)&0x7)));
219 attrlen += ISAKMP_ATTR_SZ4;
220 } else {
221 log_print("cfg_initiator_send_ATTR: "
222 "unknown attribute %.20s in "
223 "section [%s]", anode->field,
224 id_string);
225 }
226 }
227
228 conf_free_list(alist);
229 }
230 }
231
232 if (attrlen == 0) {
233 /* No data found. */
234 log_print("cfg_initiator_send_ATTR: no IKECFG attributes "
235 "found for [%s]", id_string);
236
237 /*
238 * We can continue, but this indicates a configuration error
239 * that the user probably will want to correct.
240 */
241 free(id_string);
242 return 0;
243 }
244 attrlen += ISAKMP_ATTRIBUTE_SZ8;
245 attrp = calloc(1, attrlen);
246 if (!attrp) {
247 log_error("cfg_initiator_send_ATTR: calloc (1, %lu) failed",
248 (unsigned long)attrlen);
249 goto fail;
250 }
251 if (message_add_payload(msg, ISAKMP_PAYLOAD_ATTRIBUTE14, attrp, attrlen,
252 1)) {
253 free(attrp);
254 goto fail;
255 }
256 SET_ISAKMP_ATTRIBUTE_TYPE(attrp, ie->cfg_type)field_set_num (isakmp_attribute_fld + 0, attrp, ie->cfg_type
)
;
257 arc4random_buf((u_int8_t *) & ie->cfg_id, sizeof ie->cfg_id);
258 SET_ISAKMP_ATTRIBUTE_ID(attrp, ie->cfg_id)field_set_num (isakmp_attribute_fld + 2, attrp, ie->cfg_id
)
;
259
260 off = ISAKMP_ATTRIBUTE_SZ8;
261
262 /*
263 * Use the bitstring built previously to collect the right
264 * parameters for attrp.
265 */
266 for (bit = 0; bit < CFG_ATTR_BIT_MAX16; bit++)
267 if (bit_test(attrbits, bit)((attrbits)[((bit) >> 3)] & (1 << ((bit)&
0x7)))
) {
268 attr = attrp + off;
269 SET_ISAKMP_ATTR_TYPE(attr, bit)field_set_num (isakmp_attr_fld + 0, attr, bit);
270
271 if (ie->cfg_type == ISAKMP_CFG_REQUEST1) {
272 off += ISAKMP_ATTR_SZ4;
273 continue;
274 }
275 /* All the other are similar, this is the odd one. */
276 if (bit == ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY5) {
277 life = conf_get_num(id_string, "Lifetime",
278 1200);
279 SET_ISAKMP_ATTR_LENGTH_VALUE(attr, 4)field_set_num (isakmp_attr_fld + 1, attr, 4);
280 encode_32(attr + ISAKMP_ATTR_VALUE_OFF4, life);
281 off += ISAKMP_ATTR_SZ4 + 4;
282 continue;
283 }
284 switch (bit) {
285 case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS1:
286 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK2:
287 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS3:
288 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP6:
289 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS4:
290 length = 4;
291 break;
292
293 case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS8:
294 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK9:
295 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS10:
296 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP12:
297 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS11:
298 length = 16;
299 break;
300
301 default:
302 length = 0; /* Silence gcc. */
303 }
304
305 switch (bit) {
306 case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS1:
307 case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS8:
308 field = "Address";
309 break;
310 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK2:
311 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK9:
312 field = "Netmask";
313 break;
314 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS3:
315 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS10:
316 field = "Nameserver";
317 break;
318 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP6:
319 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP12:
320 field = "DHCP-server";
321 break;
322 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS4:
323 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS11:
324 field = "WINS-server";
325 break;
326 default:
327 field = 0; /* Silence gcc. */
328 }
329
330 sa = conf_get_address(id_string, field);
331
332 SET_ISAKMP_ATTR_LENGTH_VALUE(attr, length)field_set_num (isakmp_attr_fld + 1, attr, length);
333 memcpy(attr + ISAKMP_ATTR_VALUE_OFF4,
334 sockaddr_addrdata(sa), length);
335
336 free(sa);
337
338 off += ISAKMP_ATTR_SZ4 + length;
339 }
340 if (msg->exchange->phase == 2)
341 if (cfg_finalize_hash(msg, hashp, attrp, attrlen))
342 goto fail;
343
344 return 0;
345
346fail:
347 free(id_string);
348 return -1;
349}
350
351/*
352 * As "the server", this ends SET/ACK.
353 * As "the client", this ends REQ/REPLY.
354 */
355static int
356cfg_initiator_recv_ATTR(struct message *msg)
357{
358 struct payload *attrp = payload_first(msg, ISAKMP_PAYLOAD_ATTRIBUTE14);
359 struct ipsec_exch *ie = msg->exchange->data;
360 struct sa *isakmp_sa = msg->isakmp_sa;
361 struct isakmp_cfg_attr *attr;
362 struct sockaddr *sa;
363 const char *uk_addr = "<unknown>";
364 char *addr;
365
366 if (msg->exchange->phase == 2)
367 if (cfg_verify_hash(msg))
368 return -1;
369
370 /* Sanity. */
371 if (ie->cfg_id != GET_ISAKMP_ATTRIBUTE_ID(attrp->p)field_get_num (isakmp_attribute_fld + 2, attrp->p)) {
372 log_print("cfg_initiator_recv_ATTR: "
373 "cfg packet ID does not match!");
374 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 0);
375 return -1;
376 }
377 switch (attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF4]) {
378 case ISAKMP_CFG_ACK4:
379 if (ie->cfg_type != ISAKMP_CFG_SET3) {
380 log_print("cfg_initiator_recv_ATTR: "
381 "bad packet type ACK");
382 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16,
383 0, 1, 0);
384 return -1;
385 }
386 break;
387 case ISAKMP_CFG_REPLY2:
388 if (ie->cfg_type != ISAKMP_CFG_REQUEST1) {
389 log_print("cfg_initiator_recv_ATTR: "
390 "bad packet type REPLY");
391 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16,
392 0, 1, 0);
393 return -1;
394 }
395 break;
396
397 default:
398 log_print("cfg_initiator_recv_ATTR: unexpected configuration "
399 "message type %d", attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF4]);
400 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 0);
401 return -1;
402 }
403
404 attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF8,
405 GET_ISAKMP_GEN_LENGTH(attrp->p)field_get_num (isakmp_gen_fld + 2, attrp->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF8,
406 cfg_decode_attribute, ie);
407
408 switch (ie->cfg_type) {
409 case ISAKMP_CFG_ACK4: {
410 /* SET/ACK -- Server side (ACK from client) */
411 msg->transport->vtbl->get_src(isakmp_sa->transport,
412 &sa);
413 if (sockaddr2text(sa, &addr, 0) < 0)
414 addr = (char *) uk_addr;
415
416 for (attr = LIST_FIRST(&ie->attrs)((&ie->attrs)->lh_first); attr;
417 attr = LIST_NEXT(attr, link)((attr)->link.le_next))
418 LOG_DBG((LOG_NEGOTIATION, 50,log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "client %s ACKs attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
419 "cfg_initiator_recv_ATTR: "log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "client %s ACKs attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
420 "client %s ACKs attribute %s", addr,log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "client %s ACKs attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
421 constant_name(isakmp_cfg_attr_cst,log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "client %s ACKs attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
422 attr->type)))log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "client %s ACKs attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
;
423
424 if (addr != uk_addr)
425 free(addr);
426 }
427 break;
428
429 case ISAKMP_CFG_REPLY2: {
430 /*
431 * REQ/REPLY: effect attributes we've gotten
432 * responses on.
433 */
434 msg->transport->vtbl->get_src(isakmp_sa->transport,
435 &sa);
436 if (sockaddr2text(sa, &addr, 0) < 0)
437 addr = (char *) uk_addr;
438
439 for (attr = LIST_FIRST(&ie->attrs)((&ie->attrs)->lh_first); attr;
440 attr = LIST_NEXT(attr, link)((attr)->link.le_next))
441 LOG_DBG((LOG_NEGOTIATION, 50,log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "server %s replied with attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
442 "cfg_initiator_recv_ATTR: "log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "server %s replied with attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
443 "server %s replied with attribute %s",log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "server %s replied with attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
444 addr, constant_name(isakmp_cfg_attr_cst,log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "server %s replied with attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
445 attr->type)))log_debug (LOG_NEGOTIATION, 50, "cfg_initiator_recv_ATTR: " "server %s replied with attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
;
446
447 if (addr != uk_addr)
448 free(addr);
449 }
450 break;
451
452 default:
453 break;
454 }
455
456 attrp->flags |= PL_MARK1;
457 return 0;
458}
459
460/*
461 * As "the server", this starts REQ/REPLY (initiated by the client).
462 * As "the client", this starts SET/ACK (initiated by the server).
463 */
464static int
465cfg_responder_recv_ATTR(struct message *msg)
466{
467 struct payload *attrp = payload_first(msg, ISAKMP_PAYLOAD_ATTRIBUTE14);
468 struct ipsec_exch *ie = msg->exchange->data;
469 struct sa *isakmp_sa = msg->isakmp_sa;
470 struct isakmp_cfg_attr *attr;
471 struct sockaddr *sa;
472 char *addr;
473
474 if (msg->exchange->phase == 2)
475 if (cfg_verify_hash(msg))
476 return -1;
477
478 ie->cfg_id = GET_ISAKMP_ATTRIBUTE_ID(attrp->p)field_get_num (isakmp_attribute_fld + 2, attrp->p);
479 ie->cfg_type = attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF4];
480
481 switch (ie->cfg_type) {
482 case ISAKMP_CFG_REQUEST1:
483 case ISAKMP_CFG_SET3:
484 break;
485
486 default:
487 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 0);
488 log_print("cfg_responder_recv_ATTR: "
489 "unexpected configuration message type %d", ie->cfg_type);
490 return -1;
491 }
492
493 attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF8,
494 GET_ISAKMP_GEN_LENGTH(attrp->p)field_get_num (isakmp_gen_fld + 2, attrp->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF8,
495 cfg_decode_attribute, ie);
496
497 switch (ie->cfg_type) {
498 case ISAKMP_CFG_REQUEST1:
499 /* We're done. */
500 break;
501
502 case ISAKMP_CFG_SET3: {
503 /* SET/ACK -- Client side (SET from server) */
504 const char *uk_addr = "<unknown>";
505
506 msg->transport->vtbl->get_dst(isakmp_sa->transport,
507 &sa);
508 if (sockaddr2text(sa, &addr, 0) < 0)
509 addr = (char *) uk_addr;
510
511 for (attr = LIST_FIRST(&ie->attrs)((&ie->attrs)->lh_first); attr;
512 attr = LIST_NEXT(attr, link)((attr)->link.le_next))
513 LOG_DBG((LOG_NEGOTIATION, 50,log_debug (LOG_NEGOTIATION, 50, "cfg_responder_recv_ATTR: " "server %s asks us to SET attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
514 "cfg_responder_recv_ATTR: "log_debug (LOG_NEGOTIATION, 50, "cfg_responder_recv_ATTR: " "server %s asks us to SET attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
515 "server %s asks us to SET attribute %s",log_debug (LOG_NEGOTIATION, 50, "cfg_responder_recv_ATTR: " "server %s asks us to SET attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
516 addr, constant_name(isakmp_cfg_attr_cst,log_debug (LOG_NEGOTIATION, 50, "cfg_responder_recv_ATTR: " "server %s asks us to SET attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
517 attr->type)))log_debug (LOG_NEGOTIATION, 50, "cfg_responder_recv_ATTR: " "server %s asks us to SET attribute %s"
, addr, constant_name(isakmp_cfg_attr_cst, attr->type))
;
518
519 /*
520 * XXX Here's the place to add code to walk through
521 * XXX each attribute and send them along to dhclient
522 * XXX or whatever. Each attribute that we act upon
523 * XXX (such as setting a netmask), should be marked
524 * XXX like this for us to send the proper ACK
525 * XXX response: attr->attr_used++;
526 */
527
528 if (addr != uk_addr)
529 free(addr);
530 }
531 break;
532
533 default:
534 break;
535 }
536
537 attrp->flags |= PL_MARK1;
538 return 0;
539}
540
541/*
542 * As "the server", this ends REQ/REPLY mode.
543 * As "the client", this ends SET/ACK mode.
544 */
545static int
546cfg_responder_send_ATTR(struct message *msg)
547{
548 struct ipsec_exch *ie = msg->exchange->data;
549 struct sa *isakmp_sa = msg->isakmp_sa;
550 u_int8_t *hashp = 0, *attrp;
551 u_int16_t attrlen;
552 char *id_string;
553
554 if (msg->exchange->phase == 2) {
555 hashp = cfg_add_hash(msg);
556 if (!hashp)
557 return -1;
558 }
559 /* We are responder, check isakmp_sa for other side. */
560 if (isakmp_sa->initiator ^ (ie->cfg_type == ISAKMP_CFG_REQUEST1))
561 id_string = ipsec_id_string(isakmp_sa->id_i,
562 isakmp_sa->id_i_len);
563 else
564 id_string = ipsec_id_string(isakmp_sa->id_r,
565 isakmp_sa->id_r_len);
566 if (!id_string) {
567 log_print("cfg_responder_send_ATTR: cannot parse client's ID");
568 return -1;
569 }
570 if (cfg_encode_attributes(&ie->attrs, (ie->cfg_type == ISAKMP_CFG_SET3 ?
571 ISAKMP_CFG_ACK4 : ISAKMP_CFG_REPLY2), ie->cfg_id, id_string, &attrp,
572 &attrlen)) {
573 free(id_string);
574 return -1;
575 }
576 free(id_string);
577
578 if (message_add_payload(msg, ISAKMP_PAYLOAD_ATTRIBUTE14, attrp, attrlen,
579 1)) {
580 free(attrp);
581 return -1;
582 }
583 if (msg->exchange->phase == 2)
584 if (cfg_finalize_hash(msg, hashp, attrp, attrlen))
585 return -1;
586
587 return 0;
588}
589
590u_int8_t *
591cfg_add_hash(struct message *msg)
592{
593 struct ipsec_sa *isa = msg->isakmp_sa->data;
594 struct hash *hash = hash_get(isa->hash);
595 u_int8_t *hashp;
596
597 hashp = malloc(ISAKMP_HASH_SZ4 + hash->hashsize);
598 if (!hashp) {
599 log_error("cfg_add_hash: malloc (%lu) failed",
600 ISAKMP_HASH_SZ4 + (unsigned long)hash->hashsize);
601 return 0;
602 }
603 if (message_add_payload(msg, ISAKMP_PAYLOAD_HASH8, hashp,
604 ISAKMP_HASH_SZ4 + hash->hashsize, 1)) {
605 free(hashp);
606 return 0;
607 }
608 return hashp;
609}
610
611int
612cfg_finalize_hash(struct message *msg, u_int8_t *hashp, u_int8_t *data,
613 u_int16_t length)
614{
615 struct ipsec_sa *isa = msg->isakmp_sa->data;
616 struct prf *prf;
617
618 prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a,
619 isa->skeyid_len);
620 if (!prf)
621 return -1;
622
623 prf->Init(prf->prfctx);
624 prf->Update(prf->prfctx, msg->exchange->message_id,
625 ISAKMP_HDR_MESSAGE_ID_LEN4);
626 prf->Update(prf->prfctx, data, length);
627 prf->Final(hashp + ISAKMP_GEN_SZ4, prf->prfctx);
628 prf_free(prf);
629 return 0;
630}
631
632int
633cfg_verify_hash(struct message *msg)
634{
635 struct payload *hashp = payload_first(msg, ISAKMP_PAYLOAD_HASH8);
636 struct ipsec_sa *isa = msg->isakmp_sa->data;
637 struct prf *prf;
638 u_int8_t *hash, *comp_hash;
639 size_t hash_len;
640
641 if (!hashp) {
642 log_print("cfg_verify_hash: phase 2 message missing HASH");
643 message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION23,
644 0, 1, 0);
645 return -1;
646 }
647 hash = hashp->p;
648 hash_len = GET_ISAKMP_GEN_LENGTH(hash)field_get_num (isakmp_gen_fld + 2, hash);
649 comp_hash = malloc(hash_len - ISAKMP_GEN_SZ4);
650 if (!comp_hash) {
651 log_error("cfg_verify_hash: malloc (%lu) failed",
652 (unsigned long)hash_len - ISAKMP_GEN_SZ4);
653 return -1;
654 }
655 /* Verify hash. */
656 prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a,
657 isa->skeyid_len);
658 if (!prf) {
659 free(comp_hash);
660 return -1;
661 }
662 prf->Init(prf->prfctx);
663 prf->Update(prf->prfctx, msg->exchange->message_id,
664 ISAKMP_HDR_MESSAGE_ID_LEN4);
665 prf->Update(prf->prfctx, hash + hash_len,
666 msg->iov[0].iov_len - ISAKMP_HDR_SZ28 - hash_len);
667 prf->Final(comp_hash, prf->prfctx);
668 prf_free(prf);
669
670 if (memcmp(hash + ISAKMP_GEN_SZ4, comp_hash, hash_len - ISAKMP_GEN_SZ4)
671 != 0) {
672 message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION23,
673 0, 1, 0);
674 free(comp_hash);
675 return -1;
676 }
677 free(comp_hash);
678
679 /* Mark the HASH as handled. */
680 hashp->flags |= PL_MARK1;
681
682 /* Mark message authenticated. */
683 msg->flags |= MSG_AUTHENTICATED0x10;
684
685 return 0;
686}
687
688/*
689 * Decode the attribute of type TYPE with a LEN length value pointed to by
690 * VALUE. VIE is a pointer to the IPsec exchange context holding the
691 * attributes indexed by type for easy retrieval.
692 */
693static int
694cfg_decode_attribute(u_int16_t type, u_int8_t * value, u_int16_t len,
695 void *vie)
696{
697 struct ipsec_exch *ie = vie;
698 struct isakmp_cfg_attr *attr;
699
700 if (type >= ISAKMP_CFG_ATTR_PRIVATE_MIN16384 &&
701 type <= ISAKMP_CFG_ATTR_PRIVATE_MAX32767)
702 return 0;
703 if (type == 0 || type >= ISAKMP_CFG_ATTR_FUTURE_MIN16) {
704 LOG_DBG((LOG_NEGOTIATION, 30,log_debug (LOG_NEGOTIATION, 30, "cfg_decode_attribute: invalid attr type %u"
, type)
705 "cfg_decode_attribute: invalid attr type %u", type))log_debug (LOG_NEGOTIATION, 30, "cfg_decode_attribute: invalid attr type %u"
, type)
;
706 return -1;
707 }
708 attr = calloc(1, sizeof *attr);
709 if (!attr) {
710 log_error("cfg_decode_attribute: calloc (1, %lu) failed",
711 (unsigned long)sizeof *attr);
712 return -1;
713 }
714 attr->type = type;
715 attr->length = len;
716 if (len) {
717 attr->value = malloc(len);
718 if (!attr->value) {
719 log_error("cfg_decode_attribute: malloc (%d) failed",
720 len);
721 free(attr);
722 /* Should we also deallocate all other values? */
723 return -1;
724 }
725 memcpy(attr->value, value, len);
726 }
727 LIST_INSERT_HEAD(&ie->attrs, attr, link)do { if (((attr)->link.le_next = (&ie->attrs)->lh_first
) != ((void *)0)) (&ie->attrs)->lh_first->link.le_prev
= &(attr)->link.le_next; (&ie->attrs)->lh_first
= (attr); (attr)->link.le_prev = &(&ie->attrs)
->lh_first; } while (0)
;
728 return 0;
729}
730
731/*
732 * Encode list of attributes from ie->attrs into a attribute payload.
733 */
734static int
735cfg_encode_attributes(struct isakmp_cfg_attr_head *attrs, u_int32_t type,
736 u_int32_t cfg_id, char *id_string, u_int8_t **attrp, u_int16_t *len)
737{
738 struct isakmp_cfg_attr *attr;
739 struct sockaddr *sa;
740 sa_family_t family;
741 u_int32_t value;
742 u_int16_t off;
743 char *field;
744
745 /* Compute length */
746 *len = ISAKMP_ATTRIBUTE_SZ8;
747 for (attr = LIST_FIRST(attrs)((attrs)->lh_first); attr; attr = LIST_NEXT(attr, link)((attr)->link.le_next)) {
748 /* With ACK we only include the attrs we've actually used. */
749 if (type == ISAKMP_CFG_ACK4 && attr->attr_used == 0)
750 continue;
751
752 switch (attr->type) {
753 case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS1:
754 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK2:
755 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP6:
756 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS3:
757 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS4:
758 case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY5:
759 attr->length = 4;
760 break;
761
762 case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET13:
763 attr->length = 8;
764 break;
765
766 case ISAKMP_CFG_ATTR_APPLICATION_VERSION7:
767 /* XXX So far no version identifier of isakmpd here. */
768 attr->length = 0;
769 break;
770
771 case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES14:
772 attr->length = 2 * 15;
773 break;
774
775 case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS8:
776 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK9:
777 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP12:
778 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS10:
779 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS11:
780 attr->length = 16;
781 break;
782
783 case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET15:
784 attr->length = 17;
785 break;
786
787 default:
788 attr->ignore++;
789 /* XXX Log! */
790 }
791 *len += ISAKMP_ATTR_SZ4 + attr->length;
792 }
793
794 /* Allocate enough space for the payload */
795 *attrp = calloc(1, *len);
796 if (!*attrp) {
797 log_error("cfg_encode_attributes: calloc (1, %lu) failed",
798 (unsigned long)*len);
799 return -1;
800 }
801 SET_ISAKMP_ATTRIBUTE_TYPE(*attrp, type)field_set_num (isakmp_attribute_fld + 0, *attrp, type);
802 SET_ISAKMP_ATTRIBUTE_ID(*attrp, cfg_id)field_set_num (isakmp_attribute_fld + 2, *attrp, cfg_id);
803
804 off = ISAKMP_ATTRIBUTE_SZ8;
805 for (attr = LIST_FIRST(attrs)((attrs)->lh_first); attr; attr = LIST_NEXT(attr, link)((attr)->link.le_next)) {
806 /* With ACK we only include the attrs we've actually used. */
807 if (type == ISAKMP_CFG_ACK4 && attr->attr_used == 0)
808 continue;
809
810 switch (attr->type) {
811 case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS1:
812 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK2:
813 case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET13:
814 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP6:
815 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS3:
816 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS4:
817 family = AF_INET2;
818 break;
819
820 case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS8:
821 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK9:
822 case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET15:
823 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP12:
824 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS10:
825 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS11:
826 family = AF_INET624;
827 break;
828
829 default:
830 family = 0;
831 break;
832 }
833
834 switch (attr->type) {
835 case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS1:
836 case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS8:
837 field = "Address";
838 break;
839
840 case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET13:
841 case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET15:
842 field = "Network"; /* XXX or just "Address" */
843 break;
844
845 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK2:
846 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK9:
847 field = "Netmask";
848 break;
849
850 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP6:
851 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP12:
852 field = "DHCP-server";
853 break;
854
855 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS3:
856 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS10:
857 field = "Nameserver";
858 break;
859
860 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS4:
861 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS11:
862 field = "WINS-server";
863 break;
864
865 default:
866 field = 0;
867 }
868
869 switch (attr->type) {
870 case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS1:
871 case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS8:
872 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK2:
873 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK9:
874 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP6:
875 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP12:
876 case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS3:
877 case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS10:
878 case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS4:
879 case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS11:
880 sa = conf_get_address(id_string, field);
881 if (!sa) {
882 LOG_DBG((LOG_NEGOTIATION, 10,log_debug (LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " "attribute not found: %s"
, field)
883 "cfg_responder_send_ATTR: "log_debug (LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " "attribute not found: %s"
, field)
884 "attribute not found: %s", field))log_debug (LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " "attribute not found: %s"
, field)
;
885 attr->length = 0;
886 break;
887 }
888 if (sa->sa_family != family) {
889 log_print("cfg_responder_send_ATTR: "
890 "attribute %s - expected %s got %s data",
891 field,
892 (family == AF_INET2 ? "IPv4" : "IPv6"),
893 (sa->sa_family ==
894 AF_INET2 ? "IPv4" : "IPv6"));
895 free(sa);
896 attr->length = 0;
897 break;
898 }
899 /* Temporary limit length for the _SUBNET types. */
900 if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET13)
901 attr->length = 4;
902 else if (attr->type ==
903 ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET15)
904 attr->length = 16;
905
906 memcpy(*attrp + off + ISAKMP_ATTR_VALUE_OFF4,
907 sockaddr_addrdata(sa), attr->length);
908 free(sa);
909
910 /* _SUBNET types need some extra work. */
911 if (attr->type ==
912 ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET13) {
913 sa = conf_get_address(id_string, "Netmask");
914 if (!sa) {
915 LOG_DBG((LOG_NEGOTIATION, 10,log_debug (LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " "attribute not found: Netmask"
)
916 "cfg_responder_send_ATTR: "log_debug (LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " "attribute not found: Netmask"
)
917 "attribute not found: Netmask"))log_debug (LOG_NEGOTIATION, 10, "cfg_responder_send_ATTR: " "attribute not found: Netmask"
)
;
918 attr->length = 0;
919 break;
920 }
921 if (sa->sa_family != AF_INET2) {
922 log_print("cfg_responder_send_ATTR: "
923 "attribute Netmask - expected "
924 "IPv4 got IPv6 data");
925 free(sa);
926 attr->length = 0;
927 break;
928 }
929 memcpy(*attrp + off + ISAKMP_ATTR_VALUE_OFF4 +
930 attr->length, sockaddr_addrdata(sa),
931 attr->length);
932 attr->length = 8;
933 free(sa);
934 } else if (attr->type ==
935 ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET15) {
936 int prefix = conf_get_num(id_string, "Prefix",
937 -1);
938
939 if (prefix == -1) {
940 log_print("cfg_responder_send_ATTR: "
941 "attribute not found: Prefix");
942 attr->length = 0;
943 break;
944 } else if (prefix < -1 || prefix > 128) {
945 log_print("cfg_responder_send_ATTR: "
946 "attribute Prefix - invalid "
947 "value %d", prefix);
948 attr->length = 0;
949 break;
950 }
951 *(*attrp + off + ISAKMP_ATTR_VALUE_OFF4 + 16) =
952 (u_int8_t)prefix;
953 attr->length = 17;
954 }
955 break;
956
957 case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY5:
958 value = conf_get_num(id_string, "Lifetime", 1200);
959 encode_32(*attrp + off + ISAKMP_ATTR_VALUE_OFF4, value);
960 break;
961
962 case ISAKMP_CFG_ATTR_APPLICATION_VERSION7:
963 /* XXX So far no version identifier of isakmpd here. */
964 break;
965
966 case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES14:
967 break;
968
969 default:
970 break;
971 }
972
973 SET_ISAKMP_ATTR_TYPE(*attrp + off, attr->type)field_set_num (isakmp_attr_fld + 0, *attrp + off, attr->type
)
;
974 SET_ISAKMP_ATTR_LENGTH_VALUE(*attrp + off, attr->length)field_set_num (isakmp_attr_fld + 1, *attrp + off, attr->length
)
;
975 off += ISAKMP_ATTR_VALUE_OFF4 + attr->length;
976 }
977
978 return 0;
979}