Bug Summary

File:src/sbin/isakmpd/message.c
Warning:line 2159, column 16
Assigned value is garbage or undefined

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 message.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/message.c
1/* $OpenBSD: message.c,v 1.129 2016/04/04 17:35:07 yasuoka Exp $ */
2/* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */
3
4/*
5 * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved.
6 * Copyright (c) 1999 Angelos D. Keromytis. All rights reserved.
7 * Copyright (c) 1999, 2000, 2001, 2004 Håkan Olsson. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * This code was written under funding by Ericsson Radio Systems.
32 */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <stdlib.h>
39#include <string.h>
40
41#include "attribute.h"
42#include "cert.h"
43#include "constants.h"
44#include "crypto.h"
45#include "doi.h"
46#include "dpd.h"
47#include "exchange.h"
48#include "field.h"
49#include "hash.h"
50#include "ipsec.h"
51#include "ipsec_num.h"
52#include "isakmp.h"
53#include "log.h"
54#include "message.h"
55#include "nat_traversal.h"
56#include "prf.h"
57#include "sa.h"
58#include "timer.h"
59#include "transport.h"
60#include "util.h"
61#include "vendor.h"
62#include "virtual.h"
63
64/* A local set datatype, coincidentally fd_set suits our purpose fine. */
65typedef fd_set set;
66#define ISSETFD_ISSET FD_ISSET
67#define SETFD_SET FD_SET
68#define ZEROFD_ZERO FD_ZERO
69
70static int message_check_duplicate(struct message *);
71static int message_encrypt(struct message *);
72static int message_index_payload(struct message *, struct payload *,
73 u_int8_t ,u_int8_t *);
74static int message_parse_transform(struct message *, struct payload *,
75 u_int8_t, u_int8_t *);
76static struct field *message_get_field(u_int8_t);
77static int message_validate_payload(struct message *, struct payload *,
78 u_int8_t);
79static u_int16_t message_payload_sz(u_int8_t);
80static int message_validate_attribute(struct message *, struct payload *);
81static int message_validate_cert(struct message *, struct payload *);
82static int message_validate_cert_req(struct message *, struct payload *);
83static int message_validate_delete(struct message *, struct payload *);
84static int message_validate_hash(struct message *, struct payload *);
85static int message_validate_id(struct message *, struct payload *);
86static int message_validate_key_exch(struct message *, struct payload *);
87static int message_validate_nat_d(struct message *, struct payload *);
88static int message_validate_nat_oa(struct message *, struct payload *);
89static int message_validate_nonce(struct message *, struct payload *);
90static int message_validate_notify(struct message *, struct payload *);
91static int message_validate_proposal(struct message *, struct payload *);
92static int message_validate_sa(struct message *, struct payload *);
93static int message_validate_sig(struct message *, struct payload *);
94static int message_validate_transform(struct message *, struct payload *);
95static int message_validate_vendor(struct message *, struct payload *);
96
97static void message_packet_log(struct message *);
98
99/*
100 * Fields used for checking monotonic increasing of proposal and transform
101 * numbers.
102 */
103static u_int8_t *last_sa = 0;
104static u_int32_t last_prop_no;
105static u_int8_t *last_prop = 0;
106static u_int32_t last_xf_no;
107
108/*
109 * Allocate a message structure bound to transport T, and with a first
110 * segment buffer sized SZ, copied from BUF if given.
111 */
112struct message *
113message_alloc(struct transport *t, u_int8_t *buf, size_t sz)
114{
115 struct message *msg;
116 int i;
117
118 /*
119 * We use calloc(3) because it zeroes the structure which we rely on in
120 * message_free when determining what sub-allocations to free.
121 */
122 msg = calloc(1, sizeof *msg);
123 if (!msg)
124 return 0;
125 msg->iov = calloc(1, sizeof *msg->iov);
126 if (!msg->iov) {
127 message_free(msg);
128 return 0;
129 }
130 msg->iov[0].iov_len = sz;
131 msg->iov[0].iov_base = malloc(sz);
132 if (!msg->iov[0].iov_base) {
133 message_free(msg);
134 return 0;
135 }
136 msg->iovlen = 1;
137 if (buf)
138 memcpy(msg->iov[0].iov_base, buf, sz);
139 msg->nextp = (u_int8_t *)msg->iov[0].iov_base +
140 ISAKMP_HDR_NEXT_PAYLOAD_OFF16;
141 msg->transport = t;
142 transport_reference(t);
143 msg->payload = calloc(ISAKMP_PAYLOAD_MAX255, sizeof *msg->payload);
144 if (!msg->payload) {
145 message_free(msg);
146 return 0;
147 }
148 for (i = 0; i < ISAKMP_PAYLOAD_MAX255; i++)
149 TAILQ_INIT(&msg->payload[i])do { (&msg->payload[i])->tqh_first = ((void*)0); (&
msg->payload[i])->tqh_last = &(&msg->payload
[i])->tqh_first; } while (0)
;
150 TAILQ_INIT(&msg->post_send)do { (&msg->post_send)->tqh_first = ((void*)0); (&
msg->post_send)->tqh_last = &(&msg->post_send
)->tqh_first; } while (0)
;
151 LOG_DBG((LOG_MESSAGE, 90, "message_alloc: allocated %p", msg))log_debug (LOG_MESSAGE, 90, "message_alloc: allocated %p", msg
)
;
152 return msg;
153}
154
155/*
156 * Allocate a message suitable for a reply to MSG. Just allocate an empty
157 * ISAKMP header as the first segment.
158 */
159struct message *
160message_alloc_reply(struct message *msg)
161{
162 struct message *reply;
163
164 reply = message_alloc(msg->transport, 0, ISAKMP_HDR_SZ28);
165 reply->exchange = msg->exchange;
166 reply->isakmp_sa = msg->isakmp_sa;
167 reply->flags = msg->flags;
168 if (msg->isakmp_sa)
169 sa_reference(msg->isakmp_sa);
170 return reply;
171}
172
173/* Free up all resources used by the MSG message. */
174void
175message_free(struct message *msg)
176{
177 u_int32_t i;
178 struct payload *payload;
179 struct post_send *node;
180
181 LOG_DBG((LOG_MESSAGE, 20, "message_free: freeing %p", msg))log_debug (LOG_MESSAGE, 20, "message_free: freeing %p", msg);
182 if (!msg)
183 return;
184 if (msg->iov) {
185 if (msg->orig && msg->orig != (u_int8_t *)msg->iov[0].iov_base)
186 free(msg->orig);
187 for (i = 0; i < msg->iovlen; i++)
188 free(msg->iov[i].iov_base);
189 free(msg->iov);
190 }
191 if (msg->retrans)
192 timer_remove_event(msg->retrans);
193 if (msg->payload) {
194 for (i = 0; i < ISAKMP_PAYLOAD_MAX255; i++)
195 while ((payload = TAILQ_FIRST(&msg->payload[i])((&msg->payload[i])->tqh_first))) {
196 TAILQ_REMOVE(&msg->payload[i], payload, link)do { if (((payload)->link.tqe_next) != ((void*)0)) (payload
)->link.tqe_next->link.tqe_prev = (payload)->link.tqe_prev
; else (&msg->payload[i])->tqh_last = (payload)->
link.tqe_prev; *(payload)->link.tqe_prev = (payload)->link
.tqe_next; ; ; } while (0)
;
197 free(payload);
198 }
199 free(msg->payload);
200 }
201 while ((node = TAILQ_FIRST(&msg->post_send)((&msg->post_send)->tqh_first)))
202 TAILQ_REMOVE(&msg->post_send, node, link)do { if (((node)->link.tqe_next) != ((void*)0)) (node)->
link.tqe_next->link.tqe_prev = (node)->link.tqe_prev; else
(&msg->post_send)->tqh_last = (node)->link.tqe_prev
; *(node)->link.tqe_prev = (node)->link.tqe_next; ; ; }
while (0)
;
203 if (msg->transport) {
204 /* If we are on the send queue, remove us from there. */
205 if (msg->flags & MSG_IN_TRANSIT0x04)
206 TAILQ_REMOVE(msg->transport->vtbl->get_queue(msg),do { if (((msg)->link.tqe_next) != ((void*)0)) (msg)->link
.tqe_next->link.tqe_prev = (msg)->link.tqe_prev; else (
msg->transport->vtbl->get_queue(msg))->tqh_last =
(msg)->link.tqe_prev; *(msg)->link.tqe_prev = (msg)->
link.tqe_next; ; ; } while (0)
207 msg, link)do { if (((msg)->link.tqe_next) != ((void*)0)) (msg)->link
.tqe_next->link.tqe_prev = (msg)->link.tqe_prev; else (
msg->transport->vtbl->get_queue(msg))->tqh_last =
(msg)->link.tqe_prev; *(msg)->link.tqe_prev = (msg)->
link.tqe_next; ; ; } while (0)
;
208
209 transport_release(msg->transport);
210 }
211
212 if (msg->isakmp_sa)
213 sa_release(msg->isakmp_sa);
214
215 free(msg);
216}
217
218/*
219 * Generic ISAKMP parser.
220 * MSG is the ISAKMP message to be parsed. NEXT is the type of the first
221 * payload to be parsed, and it's pointed to by BUF. ACCEPTED_PAYLOADS
222 * tells what payloads are accepted and FUNC is a pointer to a function
223 * to be called for each payload found, which is also responsible for
224 * freeing the passed ISAKMP message in the failure case.
225 * Returns the total length of the parsed payloads.
226 */
227static int
228message_parse_payloads(struct message *msg, struct payload *p, u_int8_t next,
229 u_int8_t *buf, set *accepted_payloads, int (*func)(struct message *,
230 struct payload *, u_int8_t, u_int8_t *))
231{
232 u_int8_t payload;
233 u_int16_t len;
234 int sz = 0;
235
236 do {
237 LOG_DBG((LOG_MESSAGE, 50,log_debug (LOG_MESSAGE, 50, "message_parse_payloads: offset %ld payload %s"
, (long)(buf - (u_int8_t *) msg->iov[0].iov_base), constant_name
(isakmp_payload_cst, next))
238 "message_parse_payloads: offset %ld payload %s",log_debug (LOG_MESSAGE, 50, "message_parse_payloads: offset %ld payload %s"
, (long)(buf - (u_int8_t *) msg->iov[0].iov_base), constant_name
(isakmp_payload_cst, next))
239 (long)(buf - (u_int8_t *) msg->iov[0].iov_base),log_debug (LOG_MESSAGE, 50, "message_parse_payloads: offset %ld payload %s"
, (long)(buf - (u_int8_t *) msg->iov[0].iov_base), constant_name
(isakmp_payload_cst, next))
240 constant_name(isakmp_payload_cst, next)))log_debug (LOG_MESSAGE, 50, "message_parse_payloads: offset %ld payload %s"
, (long)(buf - (u_int8_t *) msg->iov[0].iov_base), constant_name
(isakmp_payload_cst, next))
;
241
242 /* Does this payload's header fit? */
243 if (buf + ISAKMP_GEN_SZ4 > (u_int8_t *)msg->iov[0].iov_base +
244 msg->iov[0].iov_len) {
245 log_print("message_parse_payloads: short message");
246 message_drop(msg,
247 ISAKMP_NOTIFY_UNEQUAL_PAYLOAD_LENGTHS30, 0, 1, 1);
248 return -1;
249 }
250 /* Ponder on the payload that is at BUF... */
251 payload = next;
252
253 /* Look at the next payload's type. */
254 next = GET_ISAKMP_GEN_NEXT_PAYLOAD(buf)field_get_num (isakmp_gen_fld + 0, buf);
255 if (next >= ISAKMP_PAYLOAD_RESERVED_MIN22 &&
256 next <= ISAKMP_PAYLOAD_RESERVED_MAX127) {
257 log_print("message_parse_payloads: invalid next "
258 "payload type %s in payload of type %d",
259 constant_name(isakmp_payload_cst, next), payload);
260 message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE1,
261 0, 1, 1);
262 return -1;
263 }
264 /* Reserved fields in ISAKMP messages should be zero. */
265 if (GET_ISAKMP_GEN_RESERVED(buf)field_get_num (isakmp_gen_fld + 1, buf) != 0) {
266 log_print("message_parse_payloads: reserved field "
267 "non-zero: %x", GET_ISAKMP_GEN_RESERVED(buf)field_get_num (isakmp_gen_fld + 1, buf));
268 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16,
269 0, 1, 1);
270 return -1;
271 }
272 /*
273 * Decode and validate the payload length field.
274 */
275 len = GET_ISAKMP_GEN_LENGTH(buf)field_get_num (isakmp_gen_fld + 2, buf);
276
277 if (message_payload_sz(payload) == 0) {
278 log_print("message_parse_payloads: unknown minimum "
279 "payload size for payload type %s",
280 constant_name(isakmp_payload_cst, payload));
281 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16,
282 0, 1, 1);
283 return -1;
284 }
285 if (len < message_payload_sz(payload)) {
286 log_print("message_parse_payloads: payload too "
287 "short: %u", len);
288 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16,
289 0, 1, 1);
290 return -1;
291 }
292 if (buf + len > (u_int8_t *)msg->iov[0].iov_base +
293 msg->iov[0].iov_len) {
294 log_print("message_parse_payloads: payload too "
295 "long: %u", len);
296 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16,
297 0, 1, 1);
298 return -1;
299 }
300 /* Ignore most private payloads. */
301 if (next >= ISAKMP_PAYLOAD_PRIVATE_MIN128 &&
302 next != ISAKMP_PAYLOAD_NAT_D_DRAFT130 &&
303 next != ISAKMP_PAYLOAD_NAT_OA_DRAFT131) {
304 LOG_DBG((LOG_MESSAGE, 30, "message_parse_payloads: "log_debug (LOG_MESSAGE, 30, "message_parse_payloads: " "private next payload type %s in payload of "
"type %d ignored", constant_name(isakmp_payload_cst, next), payload
)
305 "private next payload type %s in payload of "log_debug (LOG_MESSAGE, 30, "message_parse_payloads: " "private next payload type %s in payload of "
"type %d ignored", constant_name(isakmp_payload_cst, next), payload
)
306 "type %d ignored",log_debug (LOG_MESSAGE, 30, "message_parse_payloads: " "private next payload type %s in payload of "
"type %d ignored", constant_name(isakmp_payload_cst, next), payload
)
307 constant_name(isakmp_payload_cst, next), payload))log_debug (LOG_MESSAGE, 30, "message_parse_payloads: " "private next payload type %s in payload of "
"type %d ignored", constant_name(isakmp_payload_cst, next), payload
)
;
308 goto next_payload;
309 }
310 /*
311 * Check if the current payload is one of the accepted ones at
312 * this stage.
313 */
314 if (!ISSET(payload, accepted_payloads)__fd_isset((payload), (accepted_payloads))) {
315 log_print("message_parse_payloads: payload type %s "
316 "unexpected", constant_name(isakmp_payload_cst,
317 payload));
318 message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE1,
319 0, 1, 1);
320 return -1;
321 }
322 /* Call the payload handler specified by the caller. */
323 if (func(msg, p, payload, buf))
324 return -1;
325
326next_payload:
327 /* Advance to next payload. */
328 buf += len;
329 sz += len;
330 } while (next != ISAKMP_PAYLOAD_NONE0);
331 return sz;
332}
333
334/*
335 * Parse a proposal payload found in message MSG. PAYLOAD is always
336 * ISAKMP_PAYLOAD_PROPOSAL and ignored in here. It's needed as the API for
337 * message_parse_payloads requires it. BUF points to the proposal's
338 * generic payload header.
339 */
340static int
341message_parse_proposal(struct message *msg, struct payload *p,
342 u_int8_t payload, u_int8_t *buf)
343{
344 set payload_set;
345
346 /* Put the proposal into the proposal bucket. */
347 if (message_index_payload(msg, p, payload, buf) == -1)
348 return -1;
349
350 ZERO(&payload_set)do { fd_set *_p = (&payload_set); __size_t _n = (((1024) +
((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(
sizeof(__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[
--_n] = 0; } while (0)
;
351 SET(ISAKMP_PAYLOAD_TRANSFORM, &payload_set)__fd_set((3), (&payload_set));
352 if (message_parse_payloads(msg,
353 TAILQ_LAST(&msg->payload[ISAKMP_PAYLOAD_PROPOSAL], payload_head)(*(((struct payload_head *)((&msg->payload[2])->tqh_last
))->tqh_last))
,
354 ISAKMP_PAYLOAD_TRANSFORM3, buf + ISAKMP_PROP_SPI_OFF8 +
355 GET_ISAKMP_PROP_SPI_SZ(buf)field_get_num (isakmp_prop_fld + 2, buf), &payload_set, message_parse_transform)
356 == -1)
357 return -1;
358
359 return 0;
360}
361
362static int
363message_parse_transform(struct message *msg, struct payload *p,
364 u_int8_t payload, u_int8_t *buf)
365{
366 /* Put the transform into the transform bucket. */
367 if (message_index_payload(msg, p, payload, buf) == -1)
368 return -1;
369
370 LOG_DBG((LOG_MESSAGE, 50, "Transform %d's attributes",log_debug (LOG_MESSAGE, 50, "Transform %d's attributes", field_get_num
(isakmp_transform_fld + 0, buf))
371 GET_ISAKMP_TRANSFORM_NO(buf)))log_debug (LOG_MESSAGE, 50, "Transform %d's attributes", field_get_num
(isakmp_transform_fld + 0, buf))
;
372 attribute_map(buf + ISAKMP_TRANSFORM_SA_ATTRS_OFF8,
373 GET_ISAKMP_GEN_LENGTH(buf)field_get_num (isakmp_gen_fld + 2, buf) - ISAKMP_TRANSFORM_SA_ATTRS_OFF8,
374 msg->exchange->doi->debug_attribute, msg);
375
376 return 0;
377}
378
379static struct field *
380message_get_field(u_int8_t payload)
381{
382 switch (payload) {
383 case ISAKMP_PAYLOAD_SA1:
384 return isakmp_sa_fld;
385 case ISAKMP_PAYLOAD_PROPOSAL2:
386 return isakmp_prop_fld;
387 case ISAKMP_PAYLOAD_TRANSFORM3:
388 return isakmp_transform_fld;
389 case ISAKMP_PAYLOAD_KEY_EXCH4:
390 return isakmp_ke_fld;
391 case ISAKMP_PAYLOAD_ID5:
392 return isakmp_id_fld;
393 case ISAKMP_PAYLOAD_CERT6:
394 return isakmp_cert_fld;
395 case ISAKMP_PAYLOAD_CERT_REQ7:
396 return isakmp_certreq_fld;
397 case ISAKMP_PAYLOAD_HASH8:
398 return isakmp_hash_fld;
399 case ISAKMP_PAYLOAD_SIG9:
400 return isakmp_sig_fld;
401 case ISAKMP_PAYLOAD_NONCE10:
402 return isakmp_nonce_fld;
403 case ISAKMP_PAYLOAD_NOTIFY11:
404 return isakmp_notify_fld;
405 case ISAKMP_PAYLOAD_DELETE12:
406 return isakmp_delete_fld;
407 case ISAKMP_PAYLOAD_VENDOR13:
408 return isakmp_vendor_fld;
409 case ISAKMP_PAYLOAD_ATTRIBUTE14:
410 return isakmp_attribute_fld;
411 case ISAKMP_PAYLOAD_NAT_D20:
412 case ISAKMP_PAYLOAD_NAT_D_DRAFT130:
413 return isakmp_nat_d_fld;
414 case ISAKMP_PAYLOAD_NAT_OA21:
415 case ISAKMP_PAYLOAD_NAT_OA_DRAFT131:
416 return isakmp_nat_oa_fld;
417 /* Not yet supported and any other unknown payloads. */
418 case ISAKMP_PAYLOAD_SAK15:
419 case ISAKMP_PAYLOAD_SAT16:
420 case ISAKMP_PAYLOAD_KD17:
421 case ISAKMP_PAYLOAD_SEQ18:
422 case ISAKMP_PAYLOAD_POP19:
423 default:
424 break;
425 }
426 return NULL((void*)0);
427}
428
429static int
430message_validate_payload(struct message *m, struct payload *p, u_int8_t payload)
431{
432 switch (payload) {
433 case ISAKMP_PAYLOAD_SA1:
434 return message_validate_sa(m, p);
435 case ISAKMP_PAYLOAD_PROPOSAL2:
436 return message_validate_proposal(m, p);
437 case ISAKMP_PAYLOAD_TRANSFORM3:
438 return message_validate_transform(m, p);
439 case ISAKMP_PAYLOAD_KEY_EXCH4:
440 return message_validate_key_exch(m, p);
441 case ISAKMP_PAYLOAD_ID5:
442 return message_validate_id(m, p);
443 case ISAKMP_PAYLOAD_CERT6:
444 return message_validate_cert(m, p);
445 case ISAKMP_PAYLOAD_CERT_REQ7:
446 return message_validate_cert_req(m, p);
447 case ISAKMP_PAYLOAD_HASH8:
448 return message_validate_hash(m, p);
449 case ISAKMP_PAYLOAD_SIG9:
450 return message_validate_sig(m, p);
451 case ISAKMP_PAYLOAD_NONCE10:
452 return message_validate_nonce(m, p);
453 case ISAKMP_PAYLOAD_NOTIFY11:
454 return message_validate_notify(m, p);
455 case ISAKMP_PAYLOAD_DELETE12:
456 return message_validate_delete(m, p);
457 case ISAKMP_PAYLOAD_VENDOR13:
458 return message_validate_vendor(m, p);
459 case ISAKMP_PAYLOAD_ATTRIBUTE14:
460 return message_validate_attribute(m, p);
461 case ISAKMP_PAYLOAD_NAT_D20:
462 case ISAKMP_PAYLOAD_NAT_D_DRAFT130:
463 return message_validate_nat_d(m, p);
464 case ISAKMP_PAYLOAD_NAT_OA21:
465 case ISAKMP_PAYLOAD_NAT_OA_DRAFT131:
466 return message_validate_nat_oa(m, p);
467 /* Not yet supported and any other unknown payloads. */
468 case ISAKMP_PAYLOAD_SAK15:
469 case ISAKMP_PAYLOAD_SAT16:
470 case ISAKMP_PAYLOAD_KD17:
471 case ISAKMP_PAYLOAD_SEQ18:
472 case ISAKMP_PAYLOAD_POP19:
473 default:
474 break;
475 }
476 message_drop(m, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE1, 0, 1, 1);
477 return -1;
478}
479
480/* Check payloads for their required minimum size. */
481static u_int16_t
482message_payload_sz(u_int8_t payload)
483{
484 switch (payload) {
485 case ISAKMP_PAYLOAD_SA1:
486 return ISAKMP_SA_SZ8;
487 case ISAKMP_PAYLOAD_PROPOSAL2:
488 return ISAKMP_PROP_SZ8;
489 case ISAKMP_PAYLOAD_TRANSFORM3:
490 return ISAKMP_TRANSFORM_SZ8;
491 case ISAKMP_PAYLOAD_KEY_EXCH4:
492 return ISAKMP_KE_SZ4;
493 case ISAKMP_PAYLOAD_ID5:
494 return ISAKMP_ID_SZ8;
495 case ISAKMP_PAYLOAD_CERT6:
496 return ISAKMP_CERT_SZ5;
497 case ISAKMP_PAYLOAD_CERT_REQ7:
498 return ISAKMP_CERTREQ_SZ5;
499 case ISAKMP_PAYLOAD_HASH8:
500 return ISAKMP_HASH_SZ4;
501 case ISAKMP_PAYLOAD_SIG9:
502 return ISAKMP_SIG_SZ4;
503 case ISAKMP_PAYLOAD_NONCE10:
504 return ISAKMP_NONCE_SZ4;
505 case ISAKMP_PAYLOAD_NOTIFY11:
506 return ISAKMP_NOTIFY_SZ12;
507 case ISAKMP_PAYLOAD_DELETE12:
508 return ISAKMP_DELETE_SZ12;
509 case ISAKMP_PAYLOAD_VENDOR13:
510 return ISAKMP_VENDOR_SZ4;
511 case ISAKMP_PAYLOAD_ATTRIBUTE14:
512 return ISAKMP_ATTRIBUTE_SZ8;
513 case ISAKMP_PAYLOAD_NAT_D20:
514 case ISAKMP_PAYLOAD_NAT_D_DRAFT130:
515 return ISAKMP_NAT_D_SZ4;
516 case ISAKMP_PAYLOAD_NAT_OA21:
517 case ISAKMP_PAYLOAD_NAT_OA_DRAFT131:
518 return ISAKMP_NAT_OA_SZ8;
519 /* Not yet supported and any other unknown payloads. */
520 case ISAKMP_PAYLOAD_SAK15:
521 case ISAKMP_PAYLOAD_SAT16:
522 case ISAKMP_PAYLOAD_KD17:
523 case ISAKMP_PAYLOAD_SEQ18:
524 case ISAKMP_PAYLOAD_POP19:
525 default:
526 return 0;
527 }
528}
529
530/* Validate the attribute payload P in message MSG. */
531static int
532message_validate_attribute(struct message *msg, struct payload *p)
533{
534 /* If we don't have an exchange yet, create one. */
535 if (!msg->exchange) {
536 if (zero_test((u_int8_t *) msg->iov[0].iov_base +
537 ISAKMP_HDR_MESSAGE_ID_OFF20, ISAKMP_HDR_MESSAGE_ID_LEN4))
538 msg->exchange = exchange_setup_p1(msg,
539 IPSEC_DOI_IPSEC1);
540 else
541 msg->exchange = exchange_setup_p2(msg,
542 IPSEC_DOI_IPSEC1);
543 if (!msg->exchange) {
544 log_print("message_validate_attribute: can not "
545 "create exchange");
546 message_free(msg);
547 return -1;
548 }
549 }
550 return 0;
551}
552
553/* Validate the certificate payload P in message MSG. */
554static int
555message_validate_cert(struct message *msg, struct payload *p)
556{
557 if (GET_ISAKMP_CERT_ENCODING(p->p)field_get_num (isakmp_cert_fld + 0, p->p) >= ISAKMP_CERTENC_RESERVED_MIN14) {
558 message_drop(msg, ISAKMP_NOTIFY_INVALID_CERT_ENCODING19, 0, 1,
559 1);
560 return -1;
561 }
562 return 0;
563}
564
565/* Validate the certificate request payload P in message MSG. */
566static int
567message_validate_cert_req(struct message *msg, struct payload *p)
568{
569 struct cert_handler *cert;
570 size_t len =
571 GET_ISAKMP_GEN_LENGTH(p->p)field_get_num (isakmp_gen_fld + 2, p->p) - ISAKMP_CERTREQ_AUTHORITY_OFF5;
572
573 if (GET_ISAKMP_CERTREQ_TYPE(p->p)field_get_num (isakmp_certreq_fld + 0, p->p) >= ISAKMP_CERTENC_RESERVED_MIN14) {
574 message_drop(msg, ISAKMP_NOTIFY_INVALID_CERT_ENCODING19, 0, 1,
575 1);
576 return -1;
577 }
578 /*
579 * Check the certificate types we support and if an acceptable
580 * authority is included in the payload check if it can be decoded
581 */
582 cert = cert_get(GET_ISAKMP_CERTREQ_TYPE(p->p)field_get_num (isakmp_certreq_fld + 0, p->p));
583 if (!cert || (len && !cert->certreq_validate(p->p +
584 ISAKMP_CERTREQ_AUTHORITY_OFF5, len))) {
585 message_drop(msg, ISAKMP_NOTIFY_CERT_TYPE_UNSUPPORTED21, 0, 1,
586 1);
587 return -1;
588 }
589 return 0;
590}
591
592/*
593 * Validate the delete payload P in message MSG. As a side-effect, create
594 * an exchange if we do not have one already.
595 */
596static int
597message_validate_delete(struct message *msg, struct payload *p)
598{
599 u_int8_t proto = GET_ISAKMP_DELETE_PROTO(p->p)field_get_num (isakmp_delete_fld + 1, p->p);
600 struct doi *doi;
601 struct sa *sa, *isakmp_sa;
602 struct sockaddr *dst, *dst_isa;
603 u_int32_t nspis = GET_ISAKMP_DELETE_NSPIS(p->p)field_get_num (isakmp_delete_fld + 3, p->p);
604 u_int8_t *spis = (u_int8_t *)p->p + ISAKMP_DELETE_SPI_OFF12;
605 u_int32_t i;
606 char *addr;
607
608 /* Only accept authenticated DELETEs. */
609 if ((msg->flags & MSG_AUTHENTICATED0x10) == 0) {
610 log_print("message_validate_delete: "
611 "got unauthenticated DELETE");
612 message_free(msg);
613 return -1;
614 }
615
616 doi = doi_lookup(GET_ISAKMP_DELETE_DOI(p->p)field_get_num (isakmp_delete_fld + 0, p->p));
617 if (!doi) {
618 log_print("message_validate_delete: DOI not supported");
619 message_free(msg);
620 return -1;
621 }
622 /* If we don't have an exchange yet, create one. */
623 if (!msg->exchange) {
624 if (zero_test((u_int8_t *) msg->iov[0].iov_base
625 + ISAKMP_HDR_MESSAGE_ID_OFF20, ISAKMP_HDR_MESSAGE_ID_LEN4))
626 msg->exchange = exchange_setup_p1(msg, doi->id);
627 else
628 msg->exchange = exchange_setup_p2(msg, doi->id);
629 if (!msg->exchange) {
630 log_print("message_validate_delete: can not create "
631 "exchange");
632 message_free(msg);
633 return -1;
634 }
635 }
636 /* Only accept DELETE as part of an INFORMATIONAL exchange. */
637 if (msg->exchange->type != ISAKMP_EXCH_INFO5) {
638 log_print("message_validate_delete: delete in exchange other "
639 "than INFO: %s", constant_name(isakmp_exch_cst,
640 msg->exchange->type));
641 message_free(msg);
642 return -1;
643 }
644 if (proto != ISAKMP_PROTO_ISAKMP1 && doi->validate_proto(proto)) {
645 log_print("message_validate_delete: protocol not supported");
646 message_free(msg);
647 return -1;
648 }
649 /* Validate the SPIs. */
650 for (i = 0; i < nspis; i++) {
651 /* Get ISAKMP SA protecting this message. */
652 isakmp_sa = msg->isakmp_sa;
653 if (!isakmp_sa) {
654 /* XXX should not happen? */
655 log_print("message_validate_delete: invalid spi (no "
656 "valid ISAKMP SA found)");
657 message_free(msg);
658 return -1;
659 }
660 isakmp_sa->transport->vtbl->get_dst(isakmp_sa->transport,
661 &dst_isa);
662
663 /* Get SA to be deleted. */
664 msg->transport->vtbl->get_dst(msg->transport, &dst);
665 if (proto == ISAKMP_PROTO_ISAKMP1)
666 sa = sa_lookup_isakmp_sa(dst, spis + i
667 * ISAKMP_HDR_COOKIES_LEN(8 + 8));
668 else
669 sa = ipsec_sa_lookup(dst, ((u_int32_t *) spis)[i],
670 proto);
671 if (!sa) {
672 LOG_DBG((LOG_MESSAGE, 50, "message_validate_delete: "log_debug (LOG_MESSAGE, 50, "message_validate_delete: " "invalid spi (no valid SA found)"
)
673 "invalid spi (no valid SA found)"))log_debug (LOG_MESSAGE, 50, "message_validate_delete: " "invalid spi (no valid SA found)"
)
;
674 message_free(msg);
675 return -1;
676 }
677 sa->transport->vtbl->get_dst(sa->transport, &dst);
678
679 /* Destination addresses must match. */
680 if (dst->sa_family != dst_isa->sa_family ||
681 memcmp(sockaddr_addrdata(dst_isa), sockaddr_addrdata(dst),
682 sockaddr_addrlen(dst))) {
683 sockaddr2text(dst_isa, &addr, 0);
684
685 log_print("message_validate_delete: invalid spi "
686 "(illegal delete request from %s)", addr);
687 free(addr);
688 message_free(msg);
689 return -1;
690 }
691 }
692
693 return 0;
694}
695
696/*
697 * Validate the hash payload P in message MSG.
698 */
699static int
700message_validate_hash(struct message *msg, struct payload *p)
701{
702 struct sa *isakmp_sa = msg->isakmp_sa;
703 struct ipsec_sa *isa;
704 struct hash *hash;
705 struct payload *hashp = payload_first(msg, ISAKMP_PAYLOAD_HASH8);
706 struct prf *prf;
707 u_int8_t *rest;
708 u_int8_t message_id[ISAKMP_HDR_MESSAGE_ID_LEN4];
709 size_t rest_len;
710
711 /* active exchanges other than INFORMATIONAL validates hash payload. */
712 if (msg->exchange && (msg->exchange->type != ISAKMP_EXCH_INFO5))
713 return 0;
714
715 if (isakmp_sa == NULL((void*)0))
716 goto invalid;
717
718 isa = isakmp_sa->data;
719 hash = hash_get(isa->hash);
720 if (hash == NULL((void*)0))
721 goto invalid;
722
723 /* If no SKEYID_a, we can not do anything (should not happen). */
724 if (!isa->skeyid_a)
725 goto invalid;
726
727 /* Allocate the prf and start calculating our HASH(1). */
728 LOG_DBG_BUF((LOG_MISC, 90, "message_validate_hash: SKEYID_a",log_debug_buf (LOG_MISC, 90, "message_validate_hash: SKEYID_a"
, isa->skeyid_a, isa->skeyid_len)
729 isa->skeyid_a, isa->skeyid_len))log_debug_buf (LOG_MISC, 90, "message_validate_hash: SKEYID_a"
, isa->skeyid_a, isa->skeyid_len)
;
730 prf = prf_alloc(isa->prf_type, hash->type, isa->skeyid_a,
731 isa->skeyid_len);
732 if (!prf) {
733 message_free(msg);
734 return -1;
735 }
736 /* This is not an active exchange. */
737 GET_ISAKMP_HDR_MESSAGE_ID(msg->iov[0].iov_base, message_id)field_get_raw (isakmp_hdr_fld + 6, msg->iov[0].iov_base, message_id
)
;
738
739 prf->Init(prf->prfctx);
740 LOG_DBG_BUF((LOG_MISC, 90, "message_validate_hash: message_id",log_debug_buf (LOG_MISC, 90, "message_validate_hash: message_id"
, message_id, 4)
741 message_id, ISAKMP_HDR_MESSAGE_ID_LEN))log_debug_buf (LOG_MISC, 90, "message_validate_hash: message_id"
, message_id, 4)
;
742 prf->Update(prf->prfctx, message_id, ISAKMP_HDR_MESSAGE_ID_LEN4);
743 rest = hashp->p + GET_ISAKMP_GEN_LENGTH(hashp->p)field_get_num (isakmp_gen_fld + 2, hashp->p);
744 rest_len = (GET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base)field_get_num (isakmp_hdr_fld + 7, msg->iov[0].iov_base) - (rest -
745 (u_int8_t *)msg->iov[0].iov_base));
746 LOG_DBG_BUF((LOG_MISC, 90,log_debug_buf (LOG_MISC, 90, "message_validate_hash: payloads after HASH(1)"
, rest, rest_len)
747 "message_validate_hash: payloads after HASH(1)", rest, rest_len))log_debug_buf (LOG_MISC, 90, "message_validate_hash: payloads after HASH(1)"
, rest, rest_len)
;
748 prf->Update(prf->prfctx, rest, rest_len);
749 prf->Final(hash->digest, prf->prfctx);
750 prf_free(prf);
751
752 if (memcmp(hashp->p + ISAKMP_HASH_DATA_OFF4, hash->digest,
753 hash->hashsize))
754 goto invalid;
755
756 /* Mark the HASH as handled. */
757 hashp->flags |= PL_MARK1;
758
759 /* Mark message as authenticated. */
760 msg->flags |= MSG_AUTHENTICATED0x10;
761
762 return 0;
763
764 invalid:
765 log_print("message_validate_hash: invalid hash information");
766 message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION23, 0, 1, 1);
767 return -1;
768}
769
770/* Validate the identification payload P in message MSG. */
771static int
772message_validate_id(struct message *msg, struct payload *p)
773{
774 struct exchange *exchange = msg->exchange;
775 size_t len = GET_ISAKMP_GEN_LENGTH(p->p)field_get_num (isakmp_gen_fld + 2, p->p);
776
777 if (!exchange) {
778 /* We should have an exchange at this point. */
779 log_print("message_validate_id: payload out of sequence");
780 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
781 return -1;
782 }
783 if (exchange->doi &&
784 exchange->doi->validate_id_information(GET_ISAKMP_ID_TYPE(p->p)field_get_num (isakmp_id_fld + 0, p->p),
785 p->p + ISAKMP_ID_DOI_DATA_OFF5, p->p + ISAKMP_ID_DATA_OFF8,
786 len - ISAKMP_ID_DATA_OFF8, exchange)) {
787 message_drop(msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION18, 0, 1,
788 1);
789 return -1;
790 }
791 return 0;
792}
793
794/* Validate the key exchange payload P in message MSG. */
795static int
796message_validate_key_exch(struct message *msg, struct payload *p)
797{
798 struct exchange *exchange = msg->exchange;
799 size_t len = GET_ISAKMP_GEN_LENGTH(p->p)field_get_num (isakmp_gen_fld + 2, p->p);
800
801 if (!exchange) {
802 /* We should have an exchange at this point. */
803 log_print("message_validate_key_exch: "
804 "payload out of sequence");
805 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
806 return -1;
807 }
808 if (exchange->doi && exchange->doi->validate_key_information(p->p +
809 ISAKMP_KE_DATA_OFF4, len - ISAKMP_KE_DATA_OFF4)) {
810 message_drop(msg, ISAKMP_NOTIFY_INVALID_KEY_INFORMATION17,
811 0, 1, 1);
812 return -1;
813 }
814 return 0;
815}
816
817/* Validate the NAT-D payload P in message MSG. */
818static int
819message_validate_nat_d(struct message *msg, struct payload *p)
820{
821 struct exchange *exchange = msg->exchange;
822
823 if (!exchange) {
824 /* We should have an exchange at this point. */
825 log_print("message_validate_nat_d: payload out of sequence");
826 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
827 return -1;
828 }
829
830 if (exchange->phase != 1) {
831 log_print("message_validate_nat_d: "
832 "NAT-D payload must be in phase 1");
833 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
834 return -1;
835 }
836
837 /* Mark as handled. */
838 p->flags |= PL_MARK1;
839
840 return 0;
841}
842
843/* Validate the NAT-OA payload P in message MSG. */
844static int
845message_validate_nat_oa(struct message *msg, struct payload *p)
846{
847 struct exchange *exchange = msg->exchange;
848
849 if (!exchange) {
850 /* We should have an exchange at this point. */
851 log_print("message_validate_nat_d: payload out of sequence");
852 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
853 return -1;
854 }
855
856#ifdef notyet /* XXX Probably never, due to patent issues. */
857 /* Mark as handled. */
858 p->flags |= PL_MARK1;
859#endif
860
861 return 0;
862}
863
864/* Validate the nonce payload P in message MSG. */
865static int
866message_validate_nonce(struct message *msg, struct payload *p)
867{
868 if (!msg->exchange) {
869 /* We should have an exchange at this point. */
870 log_print("message_validate_nonce: payload out of sequence");
871 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
872 return -1;
873 }
874 /* Nonces require no specific validation. */
875 return 0;
876}
877
878/*
879 * Validate the notify payload P in message MSG. As a side-effect, create
880 * an exchange if we do not have one already.
881 */
882static int
883message_validate_notify(struct message *msg, struct payload *p)
884{
885 u_int8_t proto = GET_ISAKMP_NOTIFY_PROTO(p->p)field_get_num (isakmp_notify_fld + 1, p->p);
886 u_int16_t type = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p)field_get_num (isakmp_notify_fld + 3, p->p);
887 struct doi *doi;
888
889 doi = doi_lookup(GET_ISAKMP_NOTIFY_DOI(p->p)field_get_num (isakmp_notify_fld + 0, p->p));
890 if (!doi) {
891 log_print("message_validate_notify: DOI not supported");
892 message_free(msg);
893 return -1;
894 }
895 /* If we don't have an exchange yet, create one. */
896 if (!msg->exchange) {
897 if (zero_test((u_int8_t *) msg->iov[0].iov_base +
898 ISAKMP_HDR_MESSAGE_ID_OFF20, ISAKMP_HDR_MESSAGE_ID_LEN4))
899 msg->exchange = exchange_setup_p1(msg, doi->id);
900 else
901 msg->exchange = exchange_setup_p2(msg, doi->id);
902 if (!msg->exchange) {
903 log_print("message_validate_notify: can not create "
904 "exchange");
905 message_free(msg);
906 return -1;
907 }
908 }
909 if (proto != ISAKMP_PROTO_ISAKMP1 && doi->validate_proto(proto)) {
910 log_print("message_validate_notify: protocol not supported");
911 message_free(msg);
912 return -1;
913 }
914
915 /* Validate the SPI. XXX Just ISAKMP for now. */
916 if (proto == ISAKMP_PROTO_ISAKMP1 &&
917 GET_ISAKMP_NOTIFY_SPI_SZ(p->p)field_get_num (isakmp_notify_fld + 2, p->p) == ISAKMP_HDR_COOKIES_LEN(8 + 8) &&
918 msg->isakmp_sa &&
919 memcmp(p->p + ISAKMP_NOTIFY_SPI_OFF12, msg->isakmp_sa->cookies,
920 ISAKMP_HDR_COOKIES_LEN(8 + 8)) != 0) {
921 log_print("message_validate_notify: bad cookies");
922 message_drop(msg, ISAKMP_NOTIFY_INVALID_SPI11, 0, 1, 1);
923 return -1;
924 }
925
926 if (type < ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE1 ||
927 (type >= ISAKMP_NOTIFY_RESERVED_MIN31 &&
928 type < ISAKMP_NOTIFY_PRIVATE_MIN8192) ||
929 (type >= ISAKMP_NOTIFY_STATUS_RESERVED1_MIN16385 &&
930 type <= ISAKMP_NOTIFY_STATUS_RESERVED1_MAX24575) ||
931 (type >= ISAKMP_NOTIFY_STATUS_DOI_MIN24576 &&
932 type <= ISAKMP_NOTIFY_STATUS_DOI_MAX32767 &&
933 doi->validate_notification(type)) ||
934 type >= ISAKMP_NOTIFY_STATUS_RESERVED2_MIN40960) {
935 log_print("message_validate_notify: "
936 "message type not supported");
937 message_free(msg);
938 return -1;
939 }
940
941 return 0;
942}
943
944/* Validate the proposal payload P in message MSG. */
945static int
946message_validate_proposal(struct message *msg, struct payload *p)
947{
948 u_int8_t proto = GET_ISAKMP_PROP_PROTO(p->p)field_get_num (isakmp_prop_fld + 1, p->p);
949 u_int8_t *sa = p->context->p;
950
951 if (!msg->exchange) {
952 /* We should have an exchange at this point. */
953 log_print("message_validate_proposal: "
954 "payload out of sequence");
955 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
956 return -1;
957 }
958 if (proto != ISAKMP_PROTO_ISAKMP1 &&
959 msg->exchange->doi->validate_proto(proto)) {
960 message_drop(msg, ISAKMP_NOTIFY_INVALID_PROTOCOL_ID10, 0, 1, 1);
961 return -1;
962 }
963 /* Check that we get monotonically increasing proposal IDs per SA. */
964 if (sa != last_sa)
965 last_sa = sa;
966 else if (GET_ISAKMP_PROP_NO(p->p)field_get_num (isakmp_prop_fld + 0, p->p) < last_prop_no) {
967 message_drop(msg, ISAKMP_NOTIFY_BAD_PROPOSAL_SYNTAX15, 0, 1, 1);
968 return -1;
969 }
970 last_prop_no = GET_ISAKMP_PROP_NO(p->p)field_get_num (isakmp_prop_fld + 0, p->p);
971
972 /* XXX Validate the SPI, and other syntactic things. */
973
974 return 0;
975}
976
977/*
978 * Validate the SA payload P in message MSG.
979 * Aside from normal validation, note what DOI is in use for other
980 * validation routines to look at. Also index the proposal payloads
981 * on the fly.
982 * XXX This assumes PAYLOAD_SA is always the first payload
983 * to be validated, which is true for IKE, except for quick mode where
984 * a PAYLOAD_HASH comes first, but in that specific case it does not matter.
985 * XXX Make sure the above comment is relevant, isn't SA always checked
986 * first due to the IANA assigned payload number?
987 */
988static int
989message_validate_sa(struct message *msg, struct payload *p)
990{
991 set payload_set;
992 size_t len;
993 u_int32_t doi_id;
994 struct exchange *exchange = msg->exchange;
995 u_int8_t *pkt = msg->iov[0].iov_base;
996
997 doi_id = GET_ISAKMP_SA_DOI(p->p)field_get_num (isakmp_sa_fld + 0, p->p);
998 if (!doi_lookup(doi_id)) {
999 log_print("message_validate_sa: DOI not supported");
1000 message_drop(msg, ISAKMP_NOTIFY_DOI_NOT_SUPPORTED2, 0, 1, 1);
1001 return -1;
1002 }
1003 /*
1004 * It's time to figure out what SA this message is about. If it is
1005 * already set, then we are creating a new phase 1 SA. Otherwise,
1006 * lookup the SA using the cookies and the message ID. If we cannot
1007 * find it, and the phase 1 SA is ready, setup a phase 2 SA.
1008 */
1009 if (!exchange) {
1010 if (zero_test(pkt + ISAKMP_HDR_RCOOKIE_OFF8,
1011 ISAKMP_HDR_RCOOKIE_LEN8))
1012 exchange = exchange_setup_p1(msg, doi_id);
1013 else if (msg->isakmp_sa->flags & SA_FLAG_READY0x01)
1014 exchange = exchange_setup_p2(msg, doi_id);
1015 else {
1016 /* XXX What to do here? */
1017 message_free(msg);
1018 return -1;
1019 }
1020 if (!exchange) {
1021 /* XXX Log? */
1022 message_free(msg);
1023 return -1;
1024 }
1025 }
1026 msg->exchange = exchange;
1027
1028 /*
1029 * Create a struct sa for each SA payload handed to us unless we are
1030 * the initiator where we only will count them.
1031 */
1032 if (exchange->initiator) {
1033 /* XXX Count SA payloads. */
1034 } else if (sa_create(exchange, msg->transport)) {
1035 /* XXX Remove exchange if we just created it? */
1036 message_free(msg);
1037 return -1;
1038 }
1039 if (exchange->phase == 1) {
1040 msg->isakmp_sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first);
1041 if (msg->isakmp_sa)
1042 sa_reference(msg->isakmp_sa);
1043 }
1044 /*
1045 * Let the DOI validate the situation, at the same time it tells us
1046 * what the length of the situation field is.
1047 */
1048 if (exchange->doi->validate_situation(p->p + ISAKMP_SA_SIT_OFF8, &len,
1049 GET_ISAKMP_GEN_LENGTH(p->p)field_get_num (isakmp_gen_fld + 2, p->p) - ISAKMP_SA_SIT_OFF8)) {
1050 log_print("message_validate_sa: situation not supported");
1051 message_drop(msg, ISAKMP_NOTIFY_SITUATION_NOT_SUPPORTED3,
1052 0, 1, 1);
1053 return -1;
1054 }
1055 /*
1056 * Reset the fields we base our proposal & transform number checks
1057 * on.
1058 */
1059 last_sa = last_prop = 0;
1060 last_prop_no = last_xf_no = 0;
1061
1062 /* Go through the PROPOSAL payloads. */
1063 ZERO(&payload_set)do { fd_set *_p = (&payload_set); __size_t _n = (((1024) +
((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(
sizeof(__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[
--_n] = 0; } while (0)
;
1064 SET(ISAKMP_PAYLOAD_PROPOSAL, &payload_set)__fd_set((2), (&payload_set));
1065 if (message_parse_payloads(msg, p, ISAKMP_PAYLOAD_PROPOSAL2,
1066 p->p + ISAKMP_SA_SIT_OFF8 + len, &payload_set,
1067 message_parse_proposal) == -1)
1068 return -1;
1069
1070 return 0;
1071}
1072
1073/* Validate the signature payload P in message MSG. */
1074static int
1075message_validate_sig(struct message *msg, struct payload *p)
1076{
1077 if (!msg->exchange) {
1078 /* We should have an exchange at this point. */
1079 log_print("message_validate_sig: payload out of sequence");
1080 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
1081 return -1;
1082 }
1083 /* XXX Not implemented yet. */
1084 return 0;
1085}
1086
1087/* Validate the transform payload P in message MSG. */
1088static int
1089message_validate_transform(struct message *msg, struct payload *p)
1090{
1091 u_int8_t proto = GET_ISAKMP_PROP_PROTO(p->context->p)field_get_num (isakmp_prop_fld + 1, p->context->p);
1092 u_int8_t *prop = p->context->p;
1093
1094 if (!msg->exchange) {
1095 /* We should have an exchange at this point. */
1096 log_print("message_validate_transform: "
1097 "payload out of sequence");
1098 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
1099 return -1;
1100 }
1101 if (msg->exchange->doi
1102 ->validate_transform_id(proto, GET_ISAKMP_TRANSFORM_ID(p->p)field_get_num (isakmp_transform_fld + 1, p->p))) {
1103 message_drop(msg, ISAKMP_NOTIFY_INVALID_TRANSFORM_ID12, 0, 1, 1);
1104 return -1;
1105 }
1106 /* Check that the reserved field is zero. */
1107 if (!zero_test(p->p + ISAKMP_TRANSFORM_RESERVED_OFF6,
1108 ISAKMP_TRANSFORM_RESERVED_LEN2)) {
1109 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
1110 return -1;
1111 }
1112 /*
1113 * Check that we get monotonically increasing transform numbers per
1114 * proposal.
1115 */
1116 if (prop != last_prop)
1117 last_prop = prop;
1118 else if (GET_ISAKMP_TRANSFORM_NO(p->p)field_get_num (isakmp_transform_fld + 0, p->p) <= last_xf_no) {
1119 message_drop(msg, ISAKMP_NOTIFY_BAD_PROPOSAL_SYNTAX15, 0, 1, 1);
1120 return -1;
1121 }
1122 last_xf_no = GET_ISAKMP_TRANSFORM_NO(p->p)field_get_num (isakmp_transform_fld + 0, p->p);
1123
1124 /* Validate the attributes. */
1125 if (attribute_map(p->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF8,
1126 GET_ISAKMP_GEN_LENGTH(p->p)field_get_num (isakmp_gen_fld + 2, p->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF8,
1127 msg->exchange->doi->validate_attribute, msg)) {
1128 message_drop(msg, ISAKMP_NOTIFY_ATTRIBUTES_NOT_SUPPORTED13,
1129 0, 1, 1);
1130 return -1;
1131 }
1132 return 0;
1133}
1134
1135/* Validate the vendor payload P in message MSG. */
1136static int
1137message_validate_vendor(struct message *msg, struct payload *p)
1138{
1139 if (!msg->exchange) {
1140 /* We should have an exchange at this point. */
1141 log_print("message_validate_vendor: payload out of sequence");
1142 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
1143 return -1;
1144 }
1145 /* Vendor IDs are only allowed in phase 1. */
1146 if (msg->exchange->phase != 1) {
1147 message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE1, 0, 1, 1);
1148 return -1;
1149 }
1150 check_vendor_openbsd(msg, p);
1151 dpd_check_vendor_payload(msg, p);
1152 nat_t_check_vendor_payload(msg, p);
1153 if (!(p->flags & PL_MARK1))
1154 LOG_DBG((LOG_MESSAGE, 40, "message_validate_vendor: "log_debug (LOG_MESSAGE, 40, "message_validate_vendor: " "vendor ID seen"
)
1155 "vendor ID seen"))log_debug (LOG_MESSAGE, 40, "message_validate_vendor: " "vendor ID seen"
)
;
1156 return 0;
1157}
1158
1159/*
1160 * Add an index-record pointing to the payload at BUF in message MSG
1161 * to the PAYLOAD bucket of payloads. This allows us to quickly reference
1162 * payloads by type. Also stash the parent payload P link into the new
1163 * node so we can go from transforms -> payloads -> SAs.
1164 */
1165static int
1166message_index_payload(struct message *msg, struct payload *p, u_int8_t payload,
1167 u_int8_t *buf)
1168{
1169 struct payload *payload_node;
1170
1171 /* Put the payload pointer into the right bucket. */
1172 payload_node = malloc(sizeof *payload_node);
1173 if (!payload_node) {
1174 message_free(msg);
1175 return -1;
1176 }
1177 payload_node->p = buf;
1178 payload_node->context = p;
1179 payload_node->flags = 0;
1180 TAILQ_INSERT_TAIL(&msg->payload[payload], payload_node, link)do { (payload_node)->link.tqe_next = ((void*)0); (payload_node
)->link.tqe_prev = (&msg->payload[payload])->tqh_last
; *(&msg->payload[payload])->tqh_last = (payload_node
); (&msg->payload[payload])->tqh_last = &(payload_node
)->link.tqe_next; } while (0)
;
1181 return 0;
1182}
1183
1184/*
1185 * Group each payload found in MSG by type for easy reference later.
1186 * While doing this, validate the generic parts of the message structure too.
1187 * NEXT is the 1st payload's type. This routine will also register the
1188 * computed message length (i.e. without padding) in msg->iov[0].iov_len.
1189 */
1190static int
1191message_sort_payloads(struct message *msg, u_int8_t next)
1192{
1193 set payload_set;
1194 int i, sz;
1195
1196 ZERO(&payload_set)do { fd_set *_p = (&payload_set); __size_t _n = (((1024) +
((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(
sizeof(__fd_mask) * 8)))); while (_n > 0) _p->fds_bits[
--_n] = 0; } while (0)
;
1197 for (i = ISAKMP_PAYLOAD_SA1; i < ISAKMP_PAYLOAD_MAX255; i++)
1198 if (i != ISAKMP_PAYLOAD_PROPOSAL2 && i !=
1199 ISAKMP_PAYLOAD_TRANSFORM3)
1200 SET(i, &payload_set)__fd_set((i), (&payload_set));
1201 sz = message_parse_payloads(msg, 0, next,
1202 (u_int8_t *)msg->iov[0].iov_base + ISAKMP_HDR_SZ28, &payload_set,
1203 message_index_payload);
1204 if (sz == -1)
1205 return -1;
1206 msg->iov[0].iov_len = ISAKMP_HDR_SZ28 + sz;
1207 SET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base, ISAKMP_HDR_SZ + sz)field_set_num (isakmp_hdr_fld + 7, msg->iov[0].iov_base, 28
+ sz)
;
1208 return 0;
1209}
1210
1211/* Run all the generic payload tests that the drafts specify. */
1212static int
1213message_validate_payloads(struct message *msg)
1214{
1215 int i;
1216 struct payload *p;
1217 struct field *f;
1218
1219 for (i = ISAKMP_PAYLOAD_SA1; i < ISAKMP_PAYLOAD_MAX255; i++)
1220 TAILQ_FOREACH(p, &msg->payload[i], link)for((p) = ((&msg->payload[i])->tqh_first); (p) != (
(void*)0); (p) = ((p)->link.tqe_next))
{
1221 LOG_DBG((LOG_MESSAGE, 60, "message_validate_payloads: "log_debug (LOG_MESSAGE, 60, "message_validate_payloads: " "payload %s at %p of message %p"
, constant_name(isakmp_payload_cst, i), p->p, msg)
1222 "payload %s at %p of message %p",log_debug (LOG_MESSAGE, 60, "message_validate_payloads: " "payload %s at %p of message %p"
, constant_name(isakmp_payload_cst, i), p->p, msg)
1223 constant_name(isakmp_payload_cst, i), p->p, msg))log_debug (LOG_MESSAGE, 60, "message_validate_payloads: " "payload %s at %p of message %p"
, constant_name(isakmp_payload_cst, i), p->p, msg)
;
1224 if ((f = message_get_field(i)) != NULL((void*)0))
1225 field_dump_payload(f, p->p);
1226 if (message_validate_payload(msg, p, i))
1227 return -1;
1228 }
1229 return 0;
1230}
1231
1232/*
1233 * All incoming messages go through here. We do generic validity checks
1234 * and try to find or establish SAs. Last but not least we try to find
1235 * the exchange this message, MSG, is part of, and feed it there.
1236 */
1237int
1238message_recv(struct message *msg)
1239{
1240 u_int8_t *buf = msg->iov[0].iov_base;
1241 size_t sz = msg->iov[0].iov_len;
1242 u_int8_t exch_type;
1243 int setup_isakmp_sa, msgid_is_zero;
1244 u_int8_t flags;
1245 struct keystate *ks = 0;
1246 struct proto tmp_proto;
1247 struct sa tmp_sa;
1248 struct transport *t;
1249
1250 /* Messages shorter than an ISAKMP header are bad. */
1251 if (sz < ISAKMP_HDR_SZ28 || sz != GET_ISAKMP_HDR_LENGTH(buf)field_get_num (isakmp_hdr_fld + 7, buf)) {
1252 log_print("message_recv: bad message length");
1253 message_drop(msg, 0, 0, 1, 1);
1254 return -1;
1255 }
1256 /* Possibly dump a raw hex image of the message to the log channel. */
1257 message_dump_raw("message_recv", msg, LOG_MESSAGE);
1258
1259 /*
1260 * If the responder cookie is zero, this is a request to setup an
1261 * ISAKMP SA. Otherwise the cookies should refer to an existing
1262 * ISAKMP SA.
1263 *
1264 * XXX This is getting ugly, please reread later to see if it can be
1265 * made nicer.
1266 */
1267 setup_isakmp_sa = zero_test(buf + ISAKMP_HDR_RCOOKIE_OFF8,
1268 ISAKMP_HDR_RCOOKIE_LEN8);
1269 if (setup_isakmp_sa) {
1270 /*
1271 * This might be a retransmission of a former ISAKMP SA setup
1272 * message. If so, just drop it.
1273 * XXX Must we really look in both the SA and exchange pools?
1274 */
1275 if (exchange_lookup_from_icookie(buf + ISAKMP_HDR_ICOOKIE_OFF0) ||
1276 sa_lookup_from_icookie(buf + ISAKMP_HDR_ICOOKIE_OFF0)) {
1277 /*
1278 * XXX Later we should differentiate between
1279 * retransmissions and potential replay attacks.
1280 */
1281 LOG_DBG((LOG_MESSAGE, 90,log_debug (LOG_MESSAGE, 90, "message_recv: dropping setup for existing SA"
)
1282 "message_recv: dropping setup for existing SA"))log_debug (LOG_MESSAGE, 90, "message_recv: dropping setup for existing SA"
)
;
1283 message_free(msg);
1284 return -1;
1285 }
1286 } else {
1287 msg->isakmp_sa = sa_lookup_by_header(buf, 0);
1288 if (msg->isakmp_sa)
1289 sa_reference(msg->isakmp_sa);
1290
1291 /*
1292 * If we cannot find an ISAKMP SA out of the cookies, this is
1293 * either a responder's first reply, and we need to upgrade
1294 * our exchange, or it's just plain invalid cookies.
1295 */
1296 if (!msg->isakmp_sa) {
1297 msg->exchange = exchange_lookup_from_icookie(buf +
1298 ISAKMP_HDR_ICOOKIE_OFF0);
1299 if (msg->exchange && msg->exchange->phase == 1 &&
1300 zero_test(msg->exchange->cookies +
1301 ISAKMP_HDR_RCOOKIE_OFF8, ISAKMP_HDR_RCOOKIE_LEN8))
1302 exchange_upgrade_p1(msg);
1303 else {
1304 log_print("message_recv: invalid cookie(s) "
1305 "%08x%08x %08x%08x",
1306 decode_32(buf + ISAKMP_HDR_ICOOKIE_OFF0),
1307 decode_32(buf + ISAKMP_HDR_ICOOKIE_OFF0 + 4),
1308 decode_32(buf + ISAKMP_HDR_RCOOKIE_OFF8),
1309 decode_32(buf + ISAKMP_HDR_RCOOKIE_OFF8 + 4));
1310 tmp_proto.sa = &tmp_sa;
1311 tmp_sa.doi = doi_lookup(ISAKMP_DOI_ISAKMP0);
1312 tmp_proto.proto = ISAKMP_PROTO_ISAKMP1;
1313 tmp_proto.spi_sz[1] = ISAKMP_HDR_COOKIES_LEN(8 + 8);
1314 tmp_proto.spi[1] =
1315 buf + ISAKMP_HDR_COOKIES_OFF0;
1316 message_drop(msg, ISAKMP_NOTIFY_INVALID_COOKIE4,
1317 &tmp_proto, 1, 1);
1318 return -1;
1319 }
1320#if 0
1321 msg->isakmp_sa = sa_lookup_from_icookie(buf +
1322 ISAKMP_HDR_ICOOKIE_OFF0);
1323 if (msg->isakmp_sa)
1324 sa_isakmp_upgrade(msg);
1325#endif
1326 }
1327 msg->exchange = exchange_lookup(buf, 1);
1328 }
1329
1330 if (message_check_duplicate(msg))
1331 return -1;
1332
1333 if (GET_ISAKMP_HDR_NEXT_PAYLOAD(buf)field_get_num (isakmp_hdr_fld + 2, buf) >= ISAKMP_PAYLOAD_RESERVED_MIN22) {
1334 log_print("message_recv: invalid payload type %d in ISAKMP "
1335 "header (check passphrases, if applicable and in Phase 1)",
1336 GET_ISAKMP_HDR_NEXT_PAYLOAD(buf)field_get_num (isakmp_hdr_fld + 2, buf));
1337 message_drop(msg, ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE1, 0, 1, 1);
1338 return -1;
1339 }
1340 /* Validate that the message is of version 1.0. */
1341 if (ISAKMP_VERSION_MAJOR(GET_ISAKMP_HDR_VERSION(buf))((field_get_num (isakmp_hdr_fld + 3, buf)) >> 4) != 1) {
1342 log_print("message_recv: invalid version major %d",
1343 ISAKMP_VERSION_MAJOR(GET_ISAKMP_HDR_VERSION(buf))((field_get_num (isakmp_hdr_fld + 3, buf)) >> 4));
1344 message_drop(msg, ISAKMP_NOTIFY_INVALID_MAJOR_VERSION5, 0, 1,
1345 1);
1346 return -1;
1347 }
1348 if (ISAKMP_VERSION_MINOR(GET_ISAKMP_HDR_VERSION(buf))((field_get_num (isakmp_hdr_fld + 3, buf)) & 0xf) != 0) {
1349 log_print("message_recv: invalid version minor %d",
1350 ISAKMP_VERSION_MINOR(GET_ISAKMP_HDR_VERSION(buf))((field_get_num (isakmp_hdr_fld + 3, buf)) & 0xf));
1351 message_drop(msg, ISAKMP_NOTIFY_INVALID_MINOR_VERSION6, 0, 1,
1352 1);
1353 return -1;
1354 }
1355 /*
1356 * Validate the exchange type. If it's a DOI-specified exchange wait
1357 * until after all payloads have been seen for the validation as the
1358 * SA payload might not yet have been parsed, thus the DOI might be
1359 * unknown.
1360 */
1361 exch_type = GET_ISAKMP_HDR_EXCH_TYPE(buf)field_get_num (isakmp_hdr_fld + 4, buf);
1362 if (exch_type == ISAKMP_EXCH_NONE0 ||
1363 (exch_type >= ISAKMP_EXCH_FUTURE_MIN7 &&
1364 exch_type <= ISAKMP_EXCH_FUTURE_MAX31) ||
1365 (setup_isakmp_sa && exch_type >= ISAKMP_EXCH_DOI_MIN32)) {
1366 log_print("message_recv: invalid exchange type %s",
1367 constant_name(isakmp_exch_cst, exch_type));
1368 message_drop(msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE7, 0, 1,
1369 1);
1370 return -1;
1371 }
1372 /*
1373 * Check for unrecognized flags, or the encryption flag when we don't
1374 * have an ISAKMP SA to decrypt with.
1375 */
1376 flags = GET_ISAKMP_HDR_FLAGS(buf)field_get_num (isakmp_hdr_fld + 5, buf);
1377 if (flags & ~(ISAKMP_FLAGS_ENC1 | ISAKMP_FLAGS_COMMIT2 |
1378 ISAKMP_FLAGS_AUTH_ONLY4)) {
1379 log_print("message_recv: invalid flags 0x%x",
1380 GET_ISAKMP_HDR_FLAGS(buf)field_get_num (isakmp_hdr_fld + 5, buf));
1381 message_drop(msg, ISAKMP_NOTIFY_INVALID_FLAGS8, 0, 1, 1);
1382 return -1;
1383 }
1384 /*
1385 * If we are about to setup an ISAKMP SA, the message ID must be
1386 * zero.
1387 */
1388 msgid_is_zero = zero_test(buf + ISAKMP_HDR_MESSAGE_ID_OFF20,
1389 ISAKMP_HDR_MESSAGE_ID_LEN4);
1390 if (setup_isakmp_sa && !msgid_is_zero) {
1391 log_print("message_recv: invalid message id");
1392 message_drop(msg, ISAKMP_NOTIFY_INVALID_MESSAGE_ID9, 0, 1, 1);
1393 return -1;
1394 }
1395 if (!setup_isakmp_sa && msgid_is_zero) {
1396 /*
1397 * XXX Very likely redundant, look at the else clause of the
1398 * if (setup_isakmp_sa) statement above.
1399 */
1400 msg->exchange = exchange_lookup(buf, 0);
1401 if (!msg->exchange) {
1402 log_print("message_recv: phase 1 message after "
1403 "ISAKMP SA is ready");
1404 message_free(msg);
1405 return -1;
1406 } else if (msg->exchange->last_sent) {
1407 LOG_DBG((LOG_MESSAGE, 80, "message_recv: resending "log_debug (LOG_MESSAGE, 80, "message_recv: resending " "last message from phase 1"
)
1408 "last message from phase 1"))log_debug (LOG_MESSAGE, 80, "message_recv: resending " "last message from phase 1"
)
;
1409 message_send(msg->exchange->last_sent);
1410 }
1411 }
1412 if (flags & ISAKMP_FLAGS_ENC1) {
1413 if (!msg->isakmp_sa) {
1414 LOG_DBG((LOG_MISC, 10, "message_recv: no isakmp_sa "log_debug (LOG_MISC, 10, "message_recv: no isakmp_sa " "for encrypted message"
)
1415 "for encrypted message"))log_debug (LOG_MISC, 10, "message_recv: no isakmp_sa " "for encrypted message"
)
;
1416 message_free(msg);
1417 return -1;
1418 }
1419 /* Decrypt rest of message using a DOI-specified IV. */
1420 ks = msg->isakmp_sa->doi->get_keystate(msg);
1421 if (!ks) {
1422 message_free(msg);
1423 return -1;
1424 }
1425 msg->orig = malloc(sz);
1426 if (!msg->orig) {
1427 message_free(msg);
1428 free(ks);
1429 return -1;
1430 }
1431 memcpy(msg->orig, buf, sz);
1432 crypto_decrypt(ks, buf + ISAKMP_HDR_SZ28, sz - ISAKMP_HDR_SZ28);
1433 } else
1434 msg->orig = buf;
1435 msg->orig_sz = sz;
1436
1437 /* IKE packet capture */
1438 message_packet_log(msg);
1439
1440 /*
1441 * Check the overall payload structure at the same time as indexing
1442 * them by type.
1443 */
1444 if (GET_ISAKMP_HDR_NEXT_PAYLOAD(buf)field_get_num (isakmp_hdr_fld + 2, buf) != ISAKMP_PAYLOAD_NONE0 &&
1445 message_sort_payloads(msg, GET_ISAKMP_HDR_NEXT_PAYLOAD(buf)field_get_num (isakmp_hdr_fld + 2, buf))) {
1446 free(ks);
1447 return -1;
1448 }
1449 /*
1450 * Run generic payload tests now. If anything fails these checks, the
1451 * message needs either to be retained for later duplicate checks or
1452 * freed entirely.
1453 * XXX Should SAs and even transports be cleaned up then too?
1454 */
1455 if (message_validate_payloads(msg)) {
1456 free(ks);
1457 return -1;
1458 }
1459 /*
1460 * If we have not found an exchange by now something is definitely
1461 * wrong.
1462 */
1463 if (!msg->exchange) {
1464 log_print("message_recv: no exchange");
1465 message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED16, 0, 1, 1);
1466 free(ks);
1467 return -1;
1468 }
1469 /*
1470 * NAT-T may have switched ports for us. We need to replace the
1471 * old ISAKMP SA transport here with one that contains the proper
1472 * (i.e translated) ports.
1473 */
1474 if (msg->isakmp_sa && msg->exchange->phase == 1) {
1475 t = msg->isakmp_sa->transport;
1476 msg->isakmp_sa->transport = msg->transport;
1477 transport_reference(msg->transport);
1478 transport_release(t);
1479 }
1480
1481 /*
1482 * Now we can validate DOI-specific exchange types. If we have no SA
1483 * DOI-specific exchange types are definitely wrong.
1484 */
1485 if (exch_type >= ISAKMP_EXCH_DOI_MIN32 &&
1486 msg->exchange->doi->validate_exchange(exch_type)) {
1487 log_print("message_recv: invalid DOI exchange type %d",
1488 exch_type);
1489 message_drop(msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE7, 0, 1,
1490 1);
1491 free(ks);
1492 return -1;
1493 }
1494 /* Make sure the IV we used gets saved in the proper SA. */
1495 if (ks) {
1496 if (!msg->exchange->keystate) {
1497 msg->exchange->keystate = ks;
1498 msg->exchange->crypto = ks->xf;
1499 } else
1500 free(ks);
1501 }
1502 /* Handle the flags. */
1503 if (flags & ISAKMP_FLAGS_ENC1)
1504 msg->exchange->flags |= EXCHANGE_FLAG_ENCRYPT0x0004;
1505 if ((msg->exchange->flags & EXCHANGE_FLAG_COMMITTED(0x0001 | 0x0002)) == 0 &&
1506 (flags & ISAKMP_FLAGS_COMMIT2))
1507 msg->exchange->flags |= EXCHANGE_FLAG_HE_COMMITTED0x0002;
1508
1509 /*
1510 * Except for the 3rd Aggressive Mode message, require encryption
1511 * as soon as we have the keystate for it.
1512 */
1513 if ((flags & ISAKMP_FLAGS_ENC1) == 0 &&
1514 (msg->exchange->phase == 2 ||
1515 (msg->exchange->keystate &&
1516 msg->exchange->type != ISAKMP_EXCH_AGGRESSIVE4))) {
1517 log_print("message_recv: cleartext phase %d message",
1518 msg->exchange->phase);
1519 message_drop(msg, ISAKMP_NOTIFY_INVALID_FLAGS8, 0, 1, 1);
1520 return -1;
1521 }
1522
1523 /* OK let the exchange logic do the rest. */
1524 exchange_run(msg);
1525
1526 return 0;
1527}
1528
1529void
1530message_send_expire(struct message *msg)
1531{
1532 msg->retrans = 0;
1533
1534 message_send(msg);
1535}
1536
1537/* Queue up message MSG for transmittal. */
1538void
1539message_send(struct message *msg)
1540{
1541 struct exchange *exchange = msg->exchange;
1542 struct message *m;
1543 struct msg_head *q;
1544
1545 /* Remove retransmissions on this message */
1546 if (msg->retrans) {
1547 timer_remove_event(msg->retrans);
1548 msg->retrans = 0;
1549 }
1550 /* IKE packet capture */
1551 message_packet_log(msg);
1552
1553 /*
1554 * If the ISAKMP SA has set up encryption, encrypt the message.
1555 * However, in a retransmit, it is already encrypted.
1556 */
1557 if ((msg->flags & MSG_ENCRYPTED0x02) == 0 &&
1558 exchange->flags & EXCHANGE_FLAG_ENCRYPT0x0004) {
1559 if (!exchange->keystate) {
1560 exchange->keystate = exchange->doi->get_keystate(msg);
1561 if (!exchange->keystate)
1562 return;
1563 exchange->crypto = exchange->keystate->xf;
1564 exchange->flags |= EXCHANGE_FLAG_ENCRYPT0x0004;
1565 }
1566 if (message_encrypt(msg)) {
1567 /* XXX Log. */
1568 return;
1569 }
1570 }
1571 /* Keep the COMMIT bit on. */
1572 if (exchange->flags & EXCHANGE_FLAG_COMMITTED(0x0001 | 0x0002))
1573 SET_ISAKMP_HDR_FLAGS(msg->iov[0].iov_base,field_set_num (isakmp_hdr_fld + 5, msg->iov[0].iov_base, field_get_num
(isakmp_hdr_fld + 5, msg->iov[0].iov_base) | 2)
1574 GET_ISAKMP_HDR_FLAGS(msg->iov[0].iov_base)field_set_num (isakmp_hdr_fld + 5, msg->iov[0].iov_base, field_get_num
(isakmp_hdr_fld + 5, msg->iov[0].iov_base) | 2)
1575 | ISAKMP_FLAGS_COMMIT)field_set_num (isakmp_hdr_fld + 5, msg->iov[0].iov_base, field_get_num
(isakmp_hdr_fld + 5, msg->iov[0].iov_base) | 2)
;
1576
1577 message_dump_raw("message_send", msg, LOG_MESSAGE);
1578 msg->flags |= MSG_IN_TRANSIT0x04;
1579 exchange->in_transit = msg;
1580
1581 /*
1582 * If we get a retransmission of a message before our response
1583 * has left the queue, don't queue it again, as it will result
1584 * in a circular list.
1585 */
1586 q = msg->transport->vtbl->get_queue(msg);
1587 for (m = TAILQ_FIRST(q)((q)->tqh_first); m; m = TAILQ_NEXT(m, link)((m)->link.tqe_next))
1588 if (m == msg) {
1589 LOG_DBG((LOG_MESSAGE, 60,log_debug (LOG_MESSAGE, 60, "message_send: msg %p already on sendq %p"
, m, q)
1590 "message_send: msg %p already on sendq %p", m, q))log_debug (LOG_MESSAGE, 60, "message_send: msg %p already on sendq %p"
, m, q)
;
1591 return;
1592 }
1593 TAILQ_INSERT_TAIL(q, msg, link)do { (msg)->link.tqe_next = ((void*)0); (msg)->link.tqe_prev
= (q)->tqh_last; *(q)->tqh_last = (msg); (q)->tqh_last
= &(msg)->link.tqe_next; } while (0)
;
1594}
1595
1596/*
1597 * Setup the ISAKMP message header for message MSG. EXCHANGE is the exchange
1598 * type, FLAGS are the ISAKMP header flags and MSG_ID is message ID
1599 * identifying the exchange.
1600 */
1601void
1602message_setup_header(struct message *msg, u_int8_t exchange, u_int8_t flags,
1603 u_int8_t *msg_id)
1604{
1605 u_int8_t *buf = msg->iov[0].iov_base;
1606
1607 SET_ISAKMP_HDR_ICOOKIE(buf, msg->exchange->cookies)field_set_raw (isakmp_hdr_fld + 0, buf, msg->exchange->
cookies)
;
1608 SET_ISAKMP_HDR_RCOOKIE(buf, msg->exchange->cookies +field_set_raw (isakmp_hdr_fld + 1, buf, msg->exchange->
cookies + 8)
1609 ISAKMP_HDR_ICOOKIE_LEN)field_set_raw (isakmp_hdr_fld + 1, buf, msg->exchange->
cookies + 8)
;
1610 SET_ISAKMP_HDR_NEXT_PAYLOAD(buf, ISAKMP_PAYLOAD_NONE)field_set_num (isakmp_hdr_fld + 2, buf, 0);
1611 SET_ISAKMP_HDR_VERSION(buf, ISAKMP_VERSION_MAKE(1, 0))field_set_num (isakmp_hdr_fld + 3, buf, ((1) << 4 | (0)
))
;
1612 SET_ISAKMP_HDR_EXCH_TYPE(buf, exchange)field_set_num (isakmp_hdr_fld + 4, buf, exchange);
1613 SET_ISAKMP_HDR_FLAGS(buf, flags)field_set_num (isakmp_hdr_fld + 5, buf, flags);
1614 SET_ISAKMP_HDR_MESSAGE_ID(buf, msg_id)field_set_raw (isakmp_hdr_fld + 6, buf, msg_id);
1615 SET_ISAKMP_HDR_LENGTH(buf, msg->iov[0].iov_len)field_set_num (isakmp_hdr_fld + 7, buf, msg->iov[0].iov_len
)
;
1616}
1617
1618/*
1619 * Add the payload of type PAYLOAD in BUF sized SZ to the MSG message.
1620 * The caller thereby is released from the responsibility of freeing BUF,
1621 * unless we return a failure of course. If LINK is set the former
1622 * payload's "next payload" field to PAYLOAD.
1623 *
1624 * XXX We might want to resize the iov array several slots at a time.
1625 */
1626int
1627message_add_payload(struct message *msg, u_int8_t payload, u_int8_t *buf,
1628 size_t sz, int link)
1629{
1630 struct iovec *new_iov;
1631 struct payload *payload_node;
1632
1633 payload_node = calloc(1, sizeof *payload_node);
1634 if (!payload_node) {
1635 log_error("message_add_payload: calloc (1, %lu) failed",
1636 (unsigned long)sizeof *payload_node);
1637 return -1;
1638 }
1639 new_iov = reallocarray(msg->iov, msg->iovlen + 1,
1640 sizeof *msg->iov);
1641 if (!new_iov) {
1642 log_error("message_add_payload: realloc (%p, %lu) failed",
1643 msg->iov, (msg->iovlen + 1) *
1644 (unsigned long)sizeof *msg->iov);
1645 free(payload_node);
1646 return -1;
1647 }
1648 msg->iov = new_iov;
1649 new_iov[msg->iovlen].iov_base = buf;
1650 new_iov[msg->iovlen].iov_len = sz;
1651 msg->iovlen++;
1652 if (link)
1653 *msg->nextp = payload;
1654 msg->nextp = buf + ISAKMP_GEN_NEXT_PAYLOAD_OFF0;
1655 *msg->nextp = ISAKMP_PAYLOAD_NONE0;
1656 SET_ISAKMP_GEN_RESERVED(buf, 0)field_set_num (isakmp_gen_fld + 1, buf, 0);
1657 SET_ISAKMP_GEN_LENGTH(buf, sz)field_set_num (isakmp_gen_fld + 2, buf, sz);
1658 SET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base,field_set_num (isakmp_hdr_fld + 7, msg->iov[0].iov_base, field_get_num
(isakmp_hdr_fld + 7, msg->iov[0].iov_base) + sz)
1659 GET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base) + sz)field_set_num (isakmp_hdr_fld + 7, msg->iov[0].iov_base, field_get_num
(isakmp_hdr_fld + 7, msg->iov[0].iov_base) + sz)
;
1660
1661 /*
1662 * For the sake of exchange_validate we index the payloads even in
1663 * outgoing messages, however context and flags are uninteresting in
1664 * this situation.
1665 */
1666 payload_node->p = buf;
1667 TAILQ_INSERT_TAIL(&msg->payload[payload], payload_node, link)do { (payload_node)->link.tqe_next = ((void*)0); (payload_node
)->link.tqe_prev = (&msg->payload[payload])->tqh_last
; *(&msg->payload[payload])->tqh_last = (payload_node
); (&msg->payload[payload])->tqh_last = &(payload_node
)->link.tqe_next; } while (0)
;
1668 return 0;
1669}
1670
1671/* XXX Move up when ready. */
1672struct info_args {
1673 char discr;
1674 u_int32_t doi;
1675 u_int8_t proto;
1676 u_int16_t spi_sz;
1677 union {
1678 struct {
1679 u_int16_t msg_type;
1680 u_int8_t *spi;
1681 } n;
1682 struct {
1683 u_int16_t nspis;
1684 u_int8_t *spis;
1685 } d;
1686 struct {
1687 u_int16_t msg_type;
1688 u_int8_t *spi;
1689 u_int32_t seq;
1690 } dpd;
1691 } u;
1692};
1693
1694/*
1695 * As a reaction to the incoming message MSG create an informational exchange
1696 * protected by ISAKMP_SA and send a notify payload of type NOTIFY, with
1697 * fields initialized from SA. INCOMING is true if the SPI field should be
1698 * filled with the incoming SPI and false if it is to be filled with the
1699 * outgoing one.
1700 *
1701 * XXX Should we handle sending multiple notify payloads? The draft allows
1702 * it, but do we need it? Furthermore, should we not return a success
1703 * status value?
1704 */
1705void
1706message_send_notification(struct message *msg, struct sa *isakmp_sa,
1707 u_int16_t notify, struct proto *proto, int incoming)
1708{
1709 struct info_args args;
1710 struct sa *doi_sa = proto ? proto->sa : isakmp_sa;
1711
1712 args.discr = 'N';
1713 args.doi = doi_sa ? doi_sa->doi->id : ISAKMP_DOI_ISAKMP0;
1714 args.proto = proto ? proto->proto : ISAKMP_PROTO_ISAKMP1;
1715 args.spi_sz = proto ? proto->spi_sz[incoming] : 0;
1716 args.u.n.msg_type = notify;
1717 args.u.n.spi = proto ? proto->spi[incoming] : 0;
1718 if (isakmp_sa && (isakmp_sa->flags & SA_FLAG_READY0x01))
1719 exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_INFO5, 0, &args,
1720 0, 0);
1721 else
1722 exchange_establish_p1(msg->transport, ISAKMP_EXCH_INFO5,
1723 msg->exchange ? msg->exchange->doi->id : ISAKMP_DOI_ISAKMP0,
1724 0, &args, 0, 0, 0);
1725}
1726
1727/* Send a DELETE inside an informational exchange for each protocol in SA. */
1728void
1729message_send_delete(struct sa *sa)
1730{
1731 struct info_args args;
1732 struct proto *proto;
1733 struct sa *isakmp_sa;
1734 struct sockaddr *dst;
1735
1736 if (!sa->transport)
1737 return;
1738
1739 sa->transport->vtbl->get_dst(sa->transport, &dst);
1740 isakmp_sa = sa_isakmp_lookup_by_peer(dst, SA_LEN(dst)((dst)->sa_len));
1741 if (!isakmp_sa) {
1742 /*
1743 * XXX We ought to setup an ISAKMP SA with our peer here and
1744 * send the DELETE over that one.
1745 */
1746 return;
1747 }
1748 args.discr = 'D';
1749 args.doi = sa->doi->id;
1750 args.u.d.nspis = 1;
1751 for (proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first); proto;
1752 proto = TAILQ_NEXT(proto, link)((proto)->link.tqe_next)) {
1753 switch (proto->proto) {
1754 case ISAKMP_PROTO_ISAKMP1:
1755 args.spi_sz = ISAKMP_HDR_COOKIES_LEN(8 + 8);
1756 args.u.d.spis = sa->cookies;
1757 break;
1758
1759 case IPSEC_PROTO_IPSEC_AH2:
1760 case IPSEC_PROTO_IPSEC_ESP3:
1761 case IPSEC_PROTO_IPCOMP4:
1762 args.spi_sz = proto->spi_sz[1];
1763 args.u.d.spis = proto->spi[1];
1764 break;
1765 default:
1766 log_print("message_send_delete: cannot delete unknown "
1767 "protocol %d", proto->proto);
1768 continue;
1769 }
1770
1771 args.proto = proto->proto;
1772 exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_INFO5, 0, &args,
1773 0, 0);
1774 }
1775}
1776
1777void
1778message_send_dpd_notify(struct sa* isakmp_sa, u_int16_t notify, u_int32_t seq)
1779{
1780 struct info_args args;
1781
1782 args.discr = 'P';
1783 args.doi = IPSEC_DOI_IPSEC1;
1784 args.proto = ISAKMP_PROTO_ISAKMP1;
1785 args.spi_sz = ISAKMP_HDR_COOKIES_LEN(8 + 8);
1786 args.u.dpd.msg_type = notify;
1787 args.u.dpd.spi = isakmp_sa->cookies;
1788 args.u.dpd.seq = htonl(seq)(__uint32_t)(__builtin_constant_p(seq) ? (__uint32_t)(((__uint32_t
)(seq) & 0xff) << 24 | ((__uint32_t)(seq) & 0xff00
) << 8 | ((__uint32_t)(seq) & 0xff0000) >> 8 |
((__uint32_t)(seq) & 0xff000000) >> 24) : __swap32md
(seq))
;
1789
1790 exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_INFO5, 0, &args, 0, 0);
1791}
1792
1793/* Build the informational message into MSG. */
1794int
1795message_send_info(struct message *msg)
1796{
1797 u_int8_t *buf;
1798 size_t sz = 0;
1799 struct info_args *args = msg->extra;
1800 u_int8_t payload;
1801
1802 /* Let the DOI get the first hand on the message. */
1803 if (msg->exchange->doi->informational_pre_hook)
1804 if (msg->exchange->doi->informational_pre_hook(msg))
1805 return -1;
1806
1807 switch (args->discr) {
1808 case 'P':
1809 sz = sizeof args->u.dpd.seq;
1810 /* FALLTHROUGH */
1811 case 'N':
1812 sz += ISAKMP_NOTIFY_SPI_OFF12 + args->spi_sz;
1813 break;
1814 case 'D':
1815 default: /* Silence gcc */
1816 sz = ISAKMP_DELETE_SPI_OFF12 + args->u.d.nspis * args->spi_sz;
1817 break;
1818 }
1819
1820 buf = calloc(1, sz);
1821 if (!buf) {
1822 log_error("message_send_info: calloc (1, %lu) failed",
1823 (unsigned long)sz);
1824 message_free(msg);
1825 return -1;
1826 }
1827 switch (args->discr) {
1828 case 'P':
1829 memcpy(buf + ISAKMP_NOTIFY_SPI_OFF12 + args->spi_sz,
1830 &args->u.dpd.seq, sizeof args->u.dpd.seq);
1831 /* FALLTHROUGH */
1832 case 'N':
1833 /* Build the NOTIFY payload. */
1834 payload = ISAKMP_PAYLOAD_NOTIFY11;
1835 SET_ISAKMP_NOTIFY_DOI(buf, args->doi)field_set_num (isakmp_notify_fld + 0, buf, args->doi);
1836 SET_ISAKMP_NOTIFY_PROTO(buf, args->proto)field_set_num (isakmp_notify_fld + 1, buf, args->proto);
1837 SET_ISAKMP_NOTIFY_SPI_SZ(buf, args->spi_sz)field_set_num (isakmp_notify_fld + 2, buf, args->spi_sz);
1838 SET_ISAKMP_NOTIFY_MSG_TYPE(buf, args->u.n.msg_type)field_set_num (isakmp_notify_fld + 3, buf, args->u.n.msg_type
)
;
1839 memcpy(buf + ISAKMP_NOTIFY_SPI_OFF12, args->u.n.spi,
1840 args->spi_sz);
1841 break;
1842
1843 case 'D':
1844 default: /* Silence GCC. */
1845 /* Build the DELETE payload. */
1846 payload = ISAKMP_PAYLOAD_DELETE12;
1847 SET_ISAKMP_DELETE_DOI(buf, args->doi)field_set_num (isakmp_delete_fld + 0, buf, args->doi);
1848 SET_ISAKMP_DELETE_PROTO(buf, args->proto)field_set_num (isakmp_delete_fld + 1, buf, args->proto);
1849 SET_ISAKMP_DELETE_SPI_SZ(buf, args->spi_sz)field_set_num (isakmp_delete_fld + 2, buf, args->spi_sz);
1850 SET_ISAKMP_DELETE_NSPIS(buf, args->u.d.nspis)field_set_num (isakmp_delete_fld + 3, buf, args->u.d.nspis
)
;
1851 memcpy(buf + ISAKMP_DELETE_SPI_OFF12, args->u.d.spis,
1852 args->u.d.nspis * args->spi_sz);
1853 msg->flags |= MSG_PRIORITIZED0x08;
1854 break;
1855 }
1856
1857 if (message_add_payload(msg, payload, buf, sz, 1)) {
1858 free(buf);
1859 message_free(msg);
1860 return -1;
1861 }
1862 /* Let the DOI get the last hand on the message. */
1863 if (msg->exchange->doi->informational_post_hook)
1864 if (msg->exchange->doi->informational_post_hook(msg)) {
1865 message_free(msg);
1866 return -1;
1867 }
1868 return 0;
1869}
1870
1871/*
1872 * Drop the MSG message due to reason given in NOTIFY. If NOTIFY is set
1873 * send out a notification to the originator. Fill this notification with
1874 * values from PROTO. INCOMING decides which SPI to include. If CLEAN is
1875 * set, free the message when ready with it.
1876 */
1877void
1878message_drop(struct message *msg, int notify, struct proto *proto,
1879 int incoming, int clean)
1880{
1881 struct transport *t = msg->transport;
1882 struct sockaddr *dst;
1883 char *address;
1884 short port = 0;
1885
1886 t->vtbl->get_dst(t, &dst);
1887 if (sockaddr2text(dst, &address, 0)) {
1888 log_error("message_drop: sockaddr2text () failed");
1889 address = 0;
1890 }
1891 switch (dst->sa_family) {
1892 case AF_INET2:
1893 port = ((struct sockaddr_in *)dst)->sin_port;
1894 break;
1895 case AF_INET624:
1896 port = ((struct sockaddr_in6 *)dst)->sin6_port;
1897 break;
1898 default:
1899 log_print("message_drop: unknown protocol family %d",
1900 dst->sa_family);
1901 }
1902
1903 log_print("dropped message from %s port %d due to notification type "
1904 "%s", address ? address : "<unknown>", htons(port)(__uint16_t)(__builtin_constant_p(port) ? (__uint16_t)(((__uint16_t
)(port) & 0xffU) << 8 | ((__uint16_t)(port) & 0xff00U
) >> 8) : __swap16md(port))
,
1905 constant_name(isakmp_notify_cst, notify));
1906
1907 free(address);
1908
1909 /* If specified, return a notification. */
1910 if (notify)
1911 message_send_notification(msg, msg->isakmp_sa, notify, proto,
1912 incoming);
1913 if (clean)
1914 message_free(msg);
1915}
1916
1917/*
1918 * If the user demands debug printouts, printout MSG with as much detail
1919 * as we can without resorting to per-payload handling.
1920 */
1921void
1922message_dump_raw(char *header, struct message *msg, int class)
1923{
1924 u_int32_t i, j, k = 0;
1925 char buf[80], *p = buf;
1926
1927 LOG_DBG((class, 70, "%s: message %p", header, msg))log_debug (class, 70, "%s: message %p", header, msg);
1928 field_dump_payload(isakmp_hdr_fld, msg->iov[0].iov_base);
1929 for (i = 0; i < msg->iovlen; i++)
1930 for (j = 0; j < msg->iov[i].iov_len; j++) {
1931 snprintf(p, sizeof buf - (int) (p - buf), "%02x",
1932 ((u_int8_t *) msg->iov[i].iov_base)[j]);
1933 p += strlen(p);
1934 if (++k % 32 == 0) {
1935 *p = '\0';
1936 LOG_DBG((class, 70, "%s: %s", header, buf))log_debug (class, 70, "%s: %s", header, buf);
1937 p = buf;
1938 } else if (k % 4 == 0)
1939 *p++ = ' ';
1940 }
1941 *p = '\0';
1942 if (p != buf)
1943 LOG_DBG((class, 70, "%s: %s", header, buf))log_debug (class, 70, "%s: %s", header, buf);
1944}
1945
1946static void
1947message_packet_log(struct message *msg)
1948{
1949 struct sockaddr *src, *dst;
1950 struct transport *t = msg->transport;
1951
1952 /* Don't log retransmissions. Redundant for incoming packets... */
1953 if (msg->xmits > 0)
1954 return;
1955
1956 if (msg->exchange && msg->exchange->flags & EXCHANGE_FLAG_NAT_T_ENABLE0x0010)
1957 t = ((struct virtual_transport *)msg->transport)->encap;
1958
1959 /* Figure out direction. */
1960 if (msg->exchange &&
1961 msg->exchange->initiator ^ (msg->exchange->step % 2)) {
1962 t->vtbl->get_src(t, &src);
1963 t->vtbl->get_dst(t, &dst);
1964 } else {
1965 t->vtbl->get_src(t, &dst);
1966 t->vtbl->get_dst(t, &src);
1967 }
1968
1969 log_packet_iov(src, dst, msg->iov, msg->iovlen);
1970}
1971
1972/*
1973 * Encrypt an outgoing message MSG. As outgoing messages are represented
1974 * with an iovec with one segment per payload, we need to coalesce them
1975 * into just une buffer containing all payloads and some padding before
1976 * we encrypt.
1977 */
1978static int
1979message_encrypt(struct message *msg)
1980{
1981 struct exchange *exchange = msg->exchange;
1982 size_t i, sz = 0;
1983 u_int8_t *buf;
1984
1985 /* If no payloads, nothing to do. */
1986 if (msg->iovlen == 1)
1987 return 0;
1988
1989 /*
1990 * For encryption we need to put all payloads together in a single
1991 * buffer. This buffer should be padded to the current crypto
1992 * transform's blocksize.
1993 */
1994 for (i = 1; i < msg->iovlen; i++)
1995 sz += msg->iov[i].iov_len;
1996 sz = ((sz + exchange->crypto->blocksize - 1) /
1997 exchange->crypto->blocksize) * exchange->crypto->blocksize;
1998 buf = realloc(msg->iov[1].iov_base, sz);
1999 if (!buf) {
2000 log_error("message_encrypt: realloc (%p, %lu) failed",
2001 msg->iov[1].iov_base, (unsigned long) sz);
2002 return -1;
2003 }
2004 msg->iov[1].iov_base = buf;
2005 for (i = 2; i < msg->iovlen; i++) {
2006 memcpy(buf + msg->iov[1].iov_len, msg->iov[i].iov_base,
2007 msg->iov[i].iov_len);
2008 msg->iov[1].iov_len += msg->iov[i].iov_len;
2009 free(msg->iov[i].iov_base);
2010 }
2011
2012 /* Pad with zeroes. */
2013 memset(buf + msg->iov[1].iov_len, '\0', sz - msg->iov[1].iov_len);
2014 msg->iov[1].iov_len = sz;
2015 msg->iovlen = 2;
2016
2017 SET_ISAKMP_HDR_FLAGS(msg->iov[0].iov_base,field_set_num (isakmp_hdr_fld + 5, msg->iov[0].iov_base, field_get_num
(isakmp_hdr_fld + 5, msg->iov[0].iov_base) | 1)
2018 GET_ISAKMP_HDR_FLAGS(msg->iov[0].iov_base) | ISAKMP_FLAGS_ENC)field_set_num (isakmp_hdr_fld + 5, msg->iov[0].iov_base, field_get_num
(isakmp_hdr_fld + 5, msg->iov[0].iov_base) | 1)
;
2019 SET_ISAKMP_HDR_LENGTH(msg->iov[0].iov_base, ISAKMP_HDR_SZ + sz)field_set_num (isakmp_hdr_fld + 7, msg->iov[0].iov_base, 28
+ sz)
;
2020 crypto_encrypt(exchange->keystate, buf, msg->iov[1].iov_len);
2021 msg->flags |= MSG_ENCRYPTED0x02;
2022
2023 /* Update the IV so we can decrypt the next incoming message. */
2024 crypto_update_iv(exchange->keystate);
2025
2026 return 0;
2027}
2028
2029/*
2030 * Check whether the message MSG is a duplicate of the last one negotiating
2031 * this specific SA.
2032 */
2033static int
2034message_check_duplicate(struct message *msg)
2035{
2036 struct exchange *exchange = msg->exchange;
2037 size_t sz = msg->iov[0].iov_len;
2038 u_int8_t *pkt = msg->iov[0].iov_base;
2039
2040 /* If no SA has been found, we cannot test, thus it's good. */
2041 if (!exchange)
2042 return 0;
2043
2044 LOG_DBG((LOG_MESSAGE, 90, "message_check_duplicate: last_received %p",log_debug (LOG_MESSAGE, 90, "message_check_duplicate: last_received %p"
, exchange->last_received)
2045 exchange->last_received))log_debug (LOG_MESSAGE, 90, "message_check_duplicate: last_received %p"
, exchange->last_received)
;
2046 if (exchange->last_received) {
2047 LOG_DBG_BUF((LOG_MESSAGE, 95,log_debug_buf (LOG_MESSAGE, 95, "message_check_duplicate: last_received"
, exchange->last_received->orig, exchange->last_received
->orig_sz)
2048 "message_check_duplicate: last_received",log_debug_buf (LOG_MESSAGE, 95, "message_check_duplicate: last_received"
, exchange->last_received->orig, exchange->last_received
->orig_sz)
2049 exchange->last_received->orig,log_debug_buf (LOG_MESSAGE, 95, "message_check_duplicate: last_received"
, exchange->last_received->orig, exchange->last_received
->orig_sz)
2050 exchange->last_received->orig_sz))log_debug_buf (LOG_MESSAGE, 95, "message_check_duplicate: last_received"
, exchange->last_received->orig, exchange->last_received
->orig_sz)
;
2051 /* Is it a duplicate, lose the new one. */
2052 if (sz == exchange->last_received->orig_sz &&
2053 memcmp(pkt, exchange->last_received->orig, sz) == 0) {
2054 LOG_DBG((LOG_MESSAGE, 80,log_debug (LOG_MESSAGE, 80, "message_check_duplicate: dropping dup"
)
2055 "message_check_duplicate: dropping dup"))log_debug (LOG_MESSAGE, 80, "message_check_duplicate: dropping dup"
)
;
2056
2057 /*
2058 * Retransmit if the previous sent message was the last
2059 * of an exchange, otherwise just wait for the
2060 * ordinary retransmission.
2061 */
2062 if (exchange->last_sent && (exchange->last_sent->flags
2063 & MSG_LAST0x01))
2064 message_send(exchange->last_sent);
2065 message_free(msg);
2066 return -1;
2067 }
2068 }
2069 /*
2070 * As this new message is an indication that state is moving forward
2071 * at the peer, remove the retransmit timer on our last message.
2072 */
2073 if (exchange->last_sent) {
2074 if (exchange->last_sent == exchange->in_transit) {
2075 struct message *m = exchange->in_transit;
2076 TAILQ_REMOVE(m->transport->vtbl->get_queue(m), m,do { if (((m)->link.tqe_next) != ((void*)0)) (m)->link.
tqe_next->link.tqe_prev = (m)->link.tqe_prev; else (m->
transport->vtbl->get_queue(m))->tqh_last = (m)->link
.tqe_prev; *(m)->link.tqe_prev = (m)->link.tqe_next; ; ;
} while (0)
2077 link)do { if (((m)->link.tqe_next) != ((void*)0)) (m)->link.
tqe_next->link.tqe_prev = (m)->link.tqe_prev; else (m->
transport->vtbl->get_queue(m))->tqh_last = (m)->link
.tqe_prev; *(m)->link.tqe_prev = (m)->link.tqe_next; ; ;
} while (0)
;
2078 exchange->in_transit = 0;
2079 }
2080 message_free(exchange->last_sent);
2081 exchange->last_sent = 0;
2082 }
2083 return 0;
2084}
2085
2086/* Helper to message_negotiate_sa. */
2087static __inline struct payload *
2088step_transform(struct payload *tp, struct payload **propp,
2089 struct payload **sap)
2090{
2091 tp = TAILQ_NEXT(tp, link)((tp)->link.tqe_next);
2092 if (tp) {
4
Assuming 'tp' is null
5
Taking false branch
2093 *propp = tp->context;
2094 *sap = (*propp)->context;
2095 }
2096 return tp;
6
Returning without writing to '*propp'
2097}
2098
2099/*
2100 * Pick out the first transforms out of MSG (which should contain at least one
2101 * SA payload) we accept as a full protection suite.
2102 */
2103int
2104message_negotiate_sa(struct message *msg, int (*validate)(struct exchange *,
2105 struct sa *, struct sa *))
2106{
2107 struct payload *tp, *propp, *sap, *next_tp = 0, *next_propp, *next_sap;
1
'next_propp' declared without an initial value
2108 struct payload *saved_tp = 0, *saved_propp = 0, *saved_sap = 0;
2109 struct sa *sa;
2110 struct proto *proto;
2111 int suite_ok_so_far = 0;
2112 struct exchange *exchange = msg->exchange;
2113
2114 /*
2115 * This algorithm is a weird bottom-up thing... mostly due to the
2116 * payload links pointing upwards.
2117 *
2118 * The algorithm goes something like this:
2119 * Foreach transform
2120 * If transform is compatible
2121 * Remember that this protocol can work
2122 * Skip to last transform of this protocol
2123 * If next transform belongs to a new protocol inside the same suite
2124 * If no transform was found for the current protocol
2125 * Forget all earlier transforms for protocols in this suite
2126 * Skip to last transform of this suite
2127 * If next transform belongs to a new suite
2128 * If the current protocol had an OK transform
2129 * Skip to the last transform of this SA
2130 * If the next transform belongs to a new SA
2131 * If no transforms have been chosen
2132 * Issue a NO_PROPOSAL_CHOSEN notification
2133 */
2134
2135 sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first);
2136 for (tp = payload_first(msg, ISAKMP_PAYLOAD_TRANSFORM3); tp;
2
Loop condition is true. Entering loop body
2137 tp = next_tp) {
2138 propp = tp->context;
2139 sap = propp->context;
2140 sap->flags |= PL_MARK1;
2141 next_tp = step_transform(tp, &next_propp, &next_sap);
3
Calling 'step_transform'
7
Returning from 'step_transform'
2142
2143 /* For each transform, see if it is compatible. */
2144 if (!attribute_map(tp->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF8,
8
Assuming the condition is true
9
Taking true branch
2145 GET_ISAKMP_GEN_LENGTH(tp->p)field_get_num (isakmp_gen_fld + 2, tp->p) -
2146 ISAKMP_TRANSFORM_SA_ATTRS_OFF8,
2147 exchange->doi->is_attribute_incompatible, msg)) {
2148 LOG_DBG((LOG_NEGOTIATION, 30, "message_negotiate_sa: "log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: " "transform %d proto %d proposal %d ok"
, field_get_num (isakmp_transform_fld + 0, tp->p), field_get_num
(isakmp_prop_fld + 1, propp->p), field_get_num (isakmp_prop_fld
+ 0, propp->p))
2149 "transform %d proto %d proposal %d ok",log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: " "transform %d proto %d proposal %d ok"
, field_get_num (isakmp_transform_fld + 0, tp->p), field_get_num
(isakmp_prop_fld + 1, propp->p), field_get_num (isakmp_prop_fld
+ 0, propp->p))
2150 GET_ISAKMP_TRANSFORM_NO(tp->p),log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: " "transform %d proto %d proposal %d ok"
, field_get_num (isakmp_transform_fld + 0, tp->p), field_get_num
(isakmp_prop_fld + 1, propp->p), field_get_num (isakmp_prop_fld
+ 0, propp->p))
2151 GET_ISAKMP_PROP_PROTO(propp->p),log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: " "transform %d proto %d proposal %d ok"
, field_get_num (isakmp_transform_fld + 0, tp->p), field_get_num
(isakmp_prop_fld + 1, propp->p), field_get_num (isakmp_prop_fld
+ 0, propp->p))
2152 GET_ISAKMP_PROP_NO(propp->p)))log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: " "transform %d proto %d proposal %d ok"
, field_get_num (isakmp_transform_fld + 0, tp->p), field_get_num
(isakmp_prop_fld + 1, propp->p), field_get_num (isakmp_prop_fld
+ 0, propp->p))
;
2153 if (sa_add_transform(sa, tp, exchange->initiator,
10
Assuming the condition is false
11
Taking false branch
2154 &proto))
2155 goto cleanup;
2156 suite_ok_so_far = 1;
2157
2158 saved_tp = next_tp;
2159 saved_propp = next_propp;
12
Assigned value is garbage or undefined
2160 saved_sap = next_sap;
2161 /* Skip to last transform of this protocol proposal. */
2162 while ((next_tp = step_transform(tp, &next_propp,
2163 &next_sap)) && next_propp == propp)
2164 tp = next_tp;
2165 }
2166retry_transform:
2167 /*
2168 * Figure out if we will be looking at a new protocol proposal
2169 * inside the current protection suite.
2170 */
2171 if (next_tp && propp != next_propp && sap == next_sap &&
2172 (GET_ISAKMP_PROP_NO(propp->p)field_get_num (isakmp_prop_fld + 0, propp->p) ==
2173 GET_ISAKMP_PROP_NO(next_propp->p)field_get_num (isakmp_prop_fld + 0, next_propp->p))) {
2174 if (!suite_ok_so_far) {
2175 LOG_DBG((LOG_NEGOTIATION, 30,log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proto %d proposal "
"%d failed", field_get_num (isakmp_prop_fld + 1, propp->p
), field_get_num (isakmp_prop_fld + 0, propp->p))
2176 "message_negotiate_sa: proto %d proposal "log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proto %d proposal "
"%d failed", field_get_num (isakmp_prop_fld + 1, propp->p
), field_get_num (isakmp_prop_fld + 0, propp->p))
2177 "%d failed",log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proto %d proposal "
"%d failed", field_get_num (isakmp_prop_fld + 1, propp->p
), field_get_num (isakmp_prop_fld + 0, propp->p))
2178 GET_ISAKMP_PROP_PROTO(propp->p),log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proto %d proposal "
"%d failed", field_get_num (isakmp_prop_fld + 1, propp->p
), field_get_num (isakmp_prop_fld + 0, propp->p))
2179 GET_ISAKMP_PROP_NO(propp->p)))log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proto %d proposal "
"%d failed", field_get_num (isakmp_prop_fld + 1, propp->p
), field_get_num (isakmp_prop_fld + 0, propp->p))
;
2180 /*
2181 * Remove potentially succeeded choices from
2182 * the SA.
2183 */
2184 while ((proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first)))
2185 proto_free(proto);
2186
2187 /*
2188 * Skip to the last transform of this
2189 * protection suite.
2190 */
2191 while ((next_tp = step_transform(tp,
2192 &next_propp, &next_sap)) &&
2193 (GET_ISAKMP_PROP_NO(next_propp->p)field_get_num (isakmp_prop_fld + 0, next_propp->p) ==
2194 GET_ISAKMP_PROP_NO(propp->p)field_get_num (isakmp_prop_fld + 0, propp->p)) &&
2195 next_sap == sap)
2196 tp = next_tp;
2197 }
2198 suite_ok_so_far = 0;
2199 }
2200 /*
2201 * Figure out if we will be looking at a new protection
2202 * suite.
2203 */
2204 if (!next_tp ||
2205 (propp != next_propp && (GET_ISAKMP_PROP_NO(propp->p)field_get_num (isakmp_prop_fld + 0, propp->p) !=
2206 GET_ISAKMP_PROP_NO(next_propp->p)field_get_num (isakmp_prop_fld + 0, next_propp->p))) ||
2207 sap != next_sap) {
2208 /*
2209 * Check if the suite we just considered was OK, if so
2210 * we check it against the accepted ones.
2211 */
2212 if (suite_ok_so_far) {
2213 if (!validate || validate(exchange, sa,
2214 msg->isakmp_sa)) {
2215 LOG_DBG((LOG_NEGOTIATION, 30,log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proposal "
"%d succeeded", field_get_num (isakmp_prop_fld + 0, propp->
p))
2216 "message_negotiate_sa: proposal "log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proposal "
"%d succeeded", field_get_num (isakmp_prop_fld + 0, propp->
p))
2217 "%d succeeded",log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proposal "
"%d succeeded", field_get_num (isakmp_prop_fld + 0, propp->
p))
2218 GET_ISAKMP_PROP_NO(propp->p)))log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proposal "
"%d succeeded", field_get_num (isakmp_prop_fld + 0, propp->
p))
;
2219
2220 /*
2221 * Skip to the last transform of this
2222 * SA.
2223 */
2224 while ((next_tp = step_transform(tp,
2225 &next_propp, &next_sap)) &&
2226 next_sap == sap)
2227 tp = next_tp;
2228 } else {
2229 /* Backtrack. */
2230 LOG_DBG((LOG_NEGOTIATION, 30,log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proposal "
"%d failed", field_get_num (isakmp_prop_fld + 0, propp->p
))
2231 "message_negotiate_sa: proposal "log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proposal "
"%d failed", field_get_num (isakmp_prop_fld + 0, propp->p
))
2232 "%d failed",log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proposal "
"%d failed", field_get_num (isakmp_prop_fld + 0, propp->p
))
2233 GET_ISAKMP_PROP_NO(propp->p)))log_debug (LOG_NEGOTIATION, 30, "message_negotiate_sa: proposal "
"%d failed", field_get_num (isakmp_prop_fld + 0, propp->p
))
;
2234 next_tp = saved_tp;
2235 next_propp = saved_propp;
2236 next_sap = saved_sap;
2237 suite_ok_so_far = 0;
2238
2239 /*
2240 * Remove potentially succeeded
2241 * choices from the SA.
2242 */
2243 while ((proto =
2244 TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first)))
2245 proto_free(proto);
2246 goto retry_transform;
2247 }
2248 }
2249 }
2250 /* Have we walked all the proposals of an SA? */
2251 if (!next_tp || sap != next_sap) {
2252 if (!suite_ok_so_far) {
2253 /*
2254 * XXX We cannot possibly call this a drop...
2255 * seeing we just turn down one of the offers,
2256 * can we? I suggest renaming message_drop to
2257 * something else.
2258 */
2259 log_print("message_negotiate_sa: no "
2260 "compatible proposal found");
2261 message_drop(msg,
2262 ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN14, 0, 1, 0);
2263 }
2264 sa = TAILQ_NEXT(sa, next)((sa)->next.tqe_next);
2265 }
2266 }
2267 return 0;
2268
2269cleanup:
2270 /*
2271 * Remove potentially succeeded choices from the SA.
2272 */
2273 while ((proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first)))
2274 proto_free(proto);
2275 return -1;
2276}
2277
2278/*
2279 * Add SA, proposal and transform payload(s) to MSG out of information
2280 * found in the exchange MSG is part of..
2281 */
2282int
2283message_add_sa_payload(struct message *msg)
2284{
2285 struct exchange *exchange = msg->exchange;
2286 u_int8_t *sa_buf, *saved_nextp_sa, *saved_nextp_prop;
2287 size_t sa_len, extra_sa_len;
2288 int i, nprotos = 0;
2289 struct proto *proto;
2290 u_int8_t **transforms = 0, **proposals = 0;
2291 size_t *transform_lens = 0, *proposal_lens = 0;
2292 struct sa *sa;
2293 struct doi *doi = exchange->doi;
2294 u_int8_t *spi = 0;
2295 size_t spi_sz;
2296
2297 /*
2298 * Generate SA payloads.
2299 */
2300 for (sa = TAILQ_FIRST(&exchange->sa_list)((&exchange->sa_list)->tqh_first); sa;
2301 sa = TAILQ_NEXT(sa, next)((sa)->next.tqe_next)) {
2302 /* Setup a SA payload. */
2303 sa_len = ISAKMP_SA_SIT_OFF8 + doi->situation_size();
2304 extra_sa_len = 0;
2305 sa_buf = malloc(sa_len);
2306 if (!sa_buf) {
2307 log_error("message_add_sa_payload: "
2308 "malloc (%lu) failed", (unsigned long)sa_len);
2309 goto cleanup;
2310 }
2311 SET_ISAKMP_SA_DOI(sa_buf, doi->id)field_set_num (isakmp_sa_fld + 0, sa_buf, doi->id);
2312 doi->setup_situation(sa_buf);
2313
2314 /* Count transforms. */
2315 nprotos = 0;
2316 for (proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first); proto;
2317 proto = TAILQ_NEXT(proto, link)((proto)->link.tqe_next))
2318 nprotos++;
2319
2320 /*
2321 * Allocate transient transform and proposal payload/size
2322 * vectors.
2323 */
2324 transforms = calloc(nprotos, sizeof *transforms);
2325 if (!transforms) {
2326 log_error("message_add_sa_payload: calloc (%d, %lu) "
2327 "failed", nprotos,
2328 (unsigned long)sizeof *transforms);
2329 goto cleanup;
2330 }
2331 transform_lens = calloc(nprotos, sizeof *transform_lens);
2332 if (!transform_lens) {
2333 log_error("message_add_sa_payload: calloc (%d, %lu) "
2334 "failed", nprotos,
2335 (unsigned long) sizeof *transform_lens);
2336 goto cleanup;
2337 }
2338 proposals = calloc(nprotos, sizeof *proposals);
2339 if (!proposals) {
2340 log_error("message_add_sa_payload: calloc (%d, %lu) "
2341 "failed", nprotos,
2342 (unsigned long)sizeof *proposals);
2343 goto cleanup;
2344 }
2345 proposal_lens = calloc(nprotos, sizeof *proposal_lens);
2346 if (!proposal_lens) {
2347 log_error("message_add_sa_payload: calloc (%d, %lu) "
2348 "failed", nprotos,
2349 (unsigned long)sizeof *proposal_lens);
2350 goto cleanup;
2351 }
2352 /* Pick out the chosen transforms. */
2353 for (proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first), i = 0; proto;
2354 proto = TAILQ_NEXT(proto, link)((proto)->link.tqe_next), i++) {
2355 transform_lens[i] =
2356 GET_ISAKMP_GEN_LENGTH(proto->chosen->p)field_get_num (isakmp_gen_fld + 2, proto->chosen->p);
2357 transforms[i] = malloc(transform_lens[i]);
2358 if (!transforms[i]) {
2359 log_error("message_add_sa_payload: malloc "
2360 "(%lu) failed",
2361 (unsigned long)transform_lens[i]);
2362 goto cleanup;
2363 }
2364 /* Get incoming SPI from application. */
2365 if (doi->get_spi) {
2366 spi = doi->get_spi(&spi_sz,
2367 GET_ISAKMP_PROP_PROTO(proto->chosen->context->p)field_get_num (isakmp_prop_fld + 1, proto->chosen->context
->p)
,
2368 msg);
2369 if (spi_sz && !spi)
2370 goto cleanup;
2371 proto->spi[1] = spi;
2372 proto->spi_sz[1] = spi_sz;
2373 } else
2374 spi_sz = 0;
2375
2376 proposal_lens[i] = ISAKMP_PROP_SPI_OFF8 + spi_sz;
2377 proposals[i] = malloc(proposal_lens[i]);
2378 if (!proposals[i]) {
2379 log_error("message_add_sa_payload: malloc "
2380 "(%lu) failed",
2381 (unsigned long)proposal_lens[i]);
2382 goto cleanup;
2383 }
2384 memcpy(transforms[i], proto->chosen->p,
2385 transform_lens[i]);
2386 memcpy(proposals[i], proto->chosen->context->p,
2387 ISAKMP_PROP_SPI_OFF8);
2388 SET_ISAKMP_PROP_NTRANSFORMS(proposals[i], 1)field_set_num (isakmp_prop_fld + 3, proposals[i], 1);
2389 SET_ISAKMP_PROP_SPI_SZ(proposals[i], spi_sz)field_set_num (isakmp_prop_fld + 2, proposals[i], spi_sz);
2390 if (spi_sz)
2391 memcpy(proposals[i] + ISAKMP_PROP_SPI_OFF8, spi,
2392 spi_sz);
2393 extra_sa_len += proposal_lens[i] + transform_lens[i];
2394 }
2395
2396 /*
2397 * Add the payloads. As this is a SA, we need to recompute the
2398 * lengths of the payloads containing others. We also need to
2399 * reset these payload's "next payload type" field.
2400 */
2401 if (message_add_payload(msg, ISAKMP_PAYLOAD_SA1, sa_buf,
2402 sa_len, 1))
2403 goto cleanup;
2404 SET_ISAKMP_GEN_LENGTH(sa_buf, sa_len + extra_sa_len)field_set_num (isakmp_gen_fld + 2, sa_buf, sa_len + extra_sa_len
)
;
2405 sa_buf = 0;
2406
2407 saved_nextp_sa = msg->nextp;
2408 for (proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first), i = 0; proto;
2409 proto = TAILQ_NEXT(proto, link)((proto)->link.tqe_next), i++) {
2410 if (message_add_payload(msg, ISAKMP_PAYLOAD_PROPOSAL2,
2411 proposals[i], proposal_lens[i], i > 0))
2412 goto cleanup;
2413 SET_ISAKMP_GEN_LENGTH(proposals[i], proposal_lens[i] +field_set_num (isakmp_gen_fld + 2, proposals[i], proposal_lens
[i] + transform_lens[i])
2414 transform_lens[i])field_set_num (isakmp_gen_fld + 2, proposals[i], proposal_lens
[i] + transform_lens[i])
;
2415 proposals[i] = 0;
2416
2417 saved_nextp_prop = msg->nextp;
2418 if (message_add_payload(msg, ISAKMP_PAYLOAD_TRANSFORM3,
2419 transforms[i], transform_lens[i], 0))
2420 goto cleanup;
2421 msg->nextp = saved_nextp_prop;
2422 transforms[i] = 0;
2423 }
2424 msg->nextp = saved_nextp_sa;
2425
2426 /* Free the temporary allocations made above. */
2427 free(transforms);
2428 free(transform_lens);
2429 free(proposals);
2430 free(proposal_lens);
2431 }
2432 return 0;
2433
2434cleanup:
2435 free(sa_buf);
2436 for (i = 0; i < nprotos; i++) {
2437 free(transforms[i]);
2438 free(proposals[i]);
2439 }
2440 free(transforms);
2441 free(transform_lens);
2442 free(proposals);
2443 free(proposal_lens);
2444 return -1;
2445}
2446
2447/*
2448 * Return a copy of MSG's constants starting from OFFSET and stash the size
2449 * in SZP. It is the callers responsibility to free this up.
2450 */
2451u_int8_t *
2452message_copy(struct message *msg, size_t offset, size_t *szp)
2453{
2454 int skip = 0;
2455 size_t i, sz = 0;
2456 ssize_t start = -1;
2457 u_int8_t *buf, *p;
2458
2459 /* Calculate size of message and where we want to start to copy. */
2460 for (i = 1; i < msg->iovlen; i++) {
2461 sz += msg->iov[i].iov_len;
2462 if (sz <= offset)
2463 skip = i;
2464 else if (start < 0)
2465 start = offset - (sz - msg->iov[i].iov_len);
2466 }
2467
2468 /* Allocate and copy. */
2469 *szp = sz - offset;
2470 buf = malloc(*szp);
2471 if (!buf)
2472 return 0;
2473 p = buf;
2474 for (i = skip + 1; i < msg->iovlen; i++) {
2475 memcpy(p, (u_int8_t *) msg->iov[i].iov_base + start,
2476 msg->iov[i].iov_len - start);
2477 p += msg->iov[i].iov_len - start;
2478 start = 0;
2479 }
2480 return buf;
2481}
2482
2483/* Register a post-send function POST_SEND with message MSG. */
2484int
2485message_register_post_send(struct message *msg,
2486 void (*post_send)(struct message *))
2487{
2488 struct post_send *node;
2489
2490 node = malloc(sizeof *node);
2491 if (!node)
2492 return -1;
2493 node->func = post_send;
2494 TAILQ_INSERT_TAIL(&msg->post_send, node, link)do { (node)->link.tqe_next = ((void*)0); (node)->link.tqe_prev
= (&msg->post_send)->tqh_last; *(&msg->post_send
)->tqh_last = (node); (&msg->post_send)->tqh_last
= &(node)->link.tqe_next; } while (0)
;
2495 return 0;
2496}
2497
2498/* Run the post-send functions of message MSG. */
2499void
2500message_post_send(struct message *msg)
2501{
2502 struct post_send *node;
2503
2504 while ((node = TAILQ_FIRST(&msg->post_send)((&msg->post_send)->tqh_first)) != 0) {
2505 TAILQ_REMOVE(&msg->post_send, node, link)do { if (((node)->link.tqe_next) != ((void*)0)) (node)->
link.tqe_next->link.tqe_prev = (node)->link.tqe_prev; else
(&msg->post_send)->tqh_last = (node)->link.tqe_prev
; *(node)->link.tqe_prev = (node)->link.tqe_next; ; ; }
while (0)
;
2506 node->func(msg);
2507 free(node);
2508 }
2509}
2510
2511struct payload *
2512payload_first(struct message *msg, u_int8_t payload)
2513{
2514 return TAILQ_FIRST(&msg->payload[payload])((&msg->payload[payload])->tqh_first);
2515}