File: | src/sbin/isakmpd/pf_key_v2.c |
Warning: | line 2729, column 41 Access to field 'pw_name' results in a dereference of a null pointer (loaded from variable 'pwd') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: pf_key_v2.c,v 1.205 2023/08/07 04:01:30 dlg Exp $ */ | |||
2 | /* $EOM: pf_key_v2.c,v 1.79 2000/12/12 00:33:19 niklas Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. | |||
6 | * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis. All rights reserved. | |||
7 | * Copyright (c) 2001 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/ioctl.h> | |||
36 | #include <sys/queue.h> | |||
37 | #include <sys/socket.h> | |||
38 | #include <sys/uio.h> | |||
39 | ||||
40 | #include <net/pfkeyv2.h> | |||
41 | #include <netinet/in.h> | |||
42 | #include <netinet/ip_ipsp.h> | |||
43 | #include <arpa/inet.h> | |||
44 | #include <stdlib.h> | |||
45 | #include <poll.h> | |||
46 | #include <string.h> | |||
47 | #include <unistd.h> | |||
48 | #include <pwd.h> | |||
49 | #include <errno(*__errno()).h> | |||
50 | #include <bitstring.h> | |||
51 | ||||
52 | #include "cert.h" | |||
53 | #include "conf.h" | |||
54 | #include "connection.h" | |||
55 | #include "exchange.h" | |||
56 | #include "ipsec.h" | |||
57 | #include "ipsec_num.h" | |||
58 | #include "key.h" | |||
59 | #include "log.h" | |||
60 | #include "pf_key_v2.h" | |||
61 | #include "sa.h" | |||
62 | #include "timer.h" | |||
63 | #include "transport.h" | |||
64 | #include "ui.h" | |||
65 | #include "util.h" | |||
66 | ||||
67 | #include "policy.h" | |||
68 | ||||
69 | #include "udp_encap.h" | |||
70 | ||||
71 | #define IN6_IS_ADDR_FULL(a)((*(u_int32_t *)(void *)(&(a)->__u6_addr.__u6_addr8[0] ) == 0xffffffff) && (*(u_int32_t *)(void *)(&(a)-> __u6_addr.__u6_addr8[4]) == 0xffffffff) && (*(u_int32_t *)(void *)(&(a)->__u6_addr.__u6_addr8[8]) == 0xffffffff ) && (*(u_int32_t *)(void *)(&(a)->__u6_addr.__u6_addr8 [12]) == 0xffffffff)) \ | |||
72 | ((*(u_int32_t *)(void *)(&(a)->s6_addr__u6_addr.__u6_addr8[0]) == 0xffffffff) && \ | |||
73 | (*(u_int32_t *)(void *)(&(a)->s6_addr__u6_addr.__u6_addr8[4]) == 0xffffffff) && \ | |||
74 | (*(u_int32_t *)(void *)(&(a)->s6_addr__u6_addr.__u6_addr8[8]) == 0xffffffff) && \ | |||
75 | (*(u_int32_t *)(void *)(&(a)->s6_addr__u6_addr.__u6_addr8[12]) == 0xffffffff)) | |||
76 | ||||
77 | #define ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" | |||
78 | ||||
79 | /* | |||
80 | * PF_KEY v2 always work with 64-bit entities and aligns on 64-bit boundaries. | |||
81 | */ | |||
82 | #define PF_KEY_V2_CHUNK8 8 | |||
83 | #define PF_KEY_V2_ROUND(x)(((x) + 8 - 1) & ~(8 - 1)) \ | |||
84 | (((x) + PF_KEY_V2_CHUNK8 - 1) & ~(PF_KEY_V2_CHUNK8 - 1)) | |||
85 | ||||
86 | /* How many microseconds we will wait for a reply from the PF_KEY socket. */ | |||
87 | #define PF_KEY_REPLY_TIMEOUT1000 1000 | |||
88 | ||||
89 | struct pf_key_v2_node { | |||
90 | TAILQ_ENTRY(pf_key_v2_node)struct { struct pf_key_v2_node *tqe_next; struct pf_key_v2_node **tqe_prev; } link; | |||
91 | void *seg; | |||
92 | size_t sz; | |||
93 | int cnt; | |||
94 | u_int16_t type; | |||
95 | u_int8_t flags; | |||
96 | }; | |||
97 | ||||
98 | TAILQ_HEAD(pf_key_v2_msg, pf_key_v2_node)struct pf_key_v2_msg { struct pf_key_v2_node *tqh_first; struct pf_key_v2_node **tqh_last; }; | |||
99 | ||||
100 | #define PF_KEY_V2_NODE_MALLOCED1 1 | |||
101 | #define PF_KEY_V2_NODE_MARK2 2 | |||
102 | ||||
103 | /* Used to derive "unique" connection identifiers. */ | |||
104 | int connection_seq = 0; | |||
105 | ||||
106 | static u_int8_t *pf_key_v2_convert_id(u_int8_t *, int, size_t *, int *); | |||
107 | static struct pf_key_v2_msg *pf_key_v2_call(struct pf_key_v2_msg *); | |||
108 | static struct pf_key_v2_node *pf_key_v2_find_ext(struct pf_key_v2_msg *, | |||
109 | u_int16_t); | |||
110 | static void pf_key_v2_notify(struct pf_key_v2_msg *); | |||
111 | static struct pf_key_v2_msg *pf_key_v2_read(u_int32_t); | |||
112 | static u_int32_t pf_key_v2_seq(void); | |||
113 | static u_int32_t pf_key_v2_write(struct pf_key_v2_msg *); | |||
114 | static int pf_key_v2_remove_conf(char *); | |||
115 | static int pf_key_v2_conf_refhandle(int, char *); | |||
116 | ||||
117 | static int pf_key_v2_conf_refinc(int, char *); | |||
118 | ||||
119 | /* The socket to use for PF_KEY interactions. */ | |||
120 | int pf_key_v2_socket; | |||
121 | ||||
122 | static struct pf_key_v2_msg * | |||
123 | pf_key_v2_msg_new(struct sadb_msg *msg, int flags) | |||
124 | { | |||
125 | struct pf_key_v2_node *node; | |||
126 | struct pf_key_v2_msg *ret; | |||
127 | ||||
128 | node = malloc(sizeof *node); | |||
129 | if (!node) | |||
130 | goto cleanup; | |||
131 | ret = malloc(sizeof *ret); | |||
132 | if (!ret) | |||
133 | goto cleanup; | |||
134 | TAILQ_INIT(ret)do { (ret)->tqh_first = ((void *)0); (ret)->tqh_last = & (ret)->tqh_first; } while (0); | |||
135 | node->seg = msg; | |||
136 | node->sz = sizeof *msg; | |||
137 | node->type = 0; | |||
138 | node->cnt = 1; | |||
139 | node->flags = flags; | |||
140 | TAILQ_INSERT_HEAD(ret, node, link)do { if (((node)->link.tqe_next = (ret)->tqh_first) != ( (void *)0)) (ret)->tqh_first->link.tqe_prev = &(node )->link.tqe_next; else (ret)->tqh_last = &(node)-> link.tqe_next; (ret)->tqh_first = (node); (node)->link. tqe_prev = &(ret)->tqh_first; } while (0); | |||
141 | return ret; | |||
142 | ||||
143 | cleanup: | |||
144 | free(node); | |||
145 | return 0; | |||
146 | } | |||
147 | ||||
148 | /* Add a SZ sized segment SEG to the PF_KEY message MSG. */ | |||
149 | static int | |||
150 | pf_key_v2_msg_add(struct pf_key_v2_msg *msg, struct sadb_ext *ext, int flags) | |||
151 | { | |||
152 | struct pf_key_v2_node *node; | |||
153 | ||||
154 | node = malloc(sizeof *node); | |||
155 | if (!node) | |||
156 | return -1; | |||
157 | node->seg = ext; | |||
158 | node->sz = ext->sadb_ext_len * PF_KEY_V2_CHUNK8; | |||
159 | node->type = ext->sadb_ext_type; | |||
160 | node->flags = flags; | |||
161 | TAILQ_FIRST(msg)((msg)->tqh_first)->cnt++; | |||
162 | TAILQ_INSERT_TAIL(msg, node, link)do { (node)->link.tqe_next = ((void *)0); (node)->link. tqe_prev = (msg)->tqh_last; *(msg)->tqh_last = (node); ( msg)->tqh_last = &(node)->link.tqe_next; } while (0 ); | |||
163 | return 0; | |||
164 | } | |||
165 | ||||
166 | /* Deallocate the PF_KEY message MSG. */ | |||
167 | static void | |||
168 | pf_key_v2_msg_free(struct pf_key_v2_msg *msg) | |||
169 | { | |||
170 | struct pf_key_v2_node *np; | |||
171 | ||||
172 | np = TAILQ_FIRST(msg)((msg)->tqh_first); | |||
173 | while (np) { | |||
174 | TAILQ_REMOVE(msg, np, link)do { if (((np)->link.tqe_next) != ((void *)0)) (np)->link .tqe_next->link.tqe_prev = (np)->link.tqe_prev; else (msg )->tqh_last = (np)->link.tqe_prev; *(np)->link.tqe_prev = (np)->link.tqe_next; ; ; } while (0); | |||
175 | if (np->flags & PF_KEY_V2_NODE_MALLOCED1) | |||
176 | free(np->seg); | |||
177 | free(np); | |||
178 | np = TAILQ_FIRST(msg)((msg)->tqh_first); | |||
179 | } | |||
180 | free(msg); | |||
181 | } | |||
182 | ||||
183 | /* Just return a new sequence number. */ | |||
184 | static u_int32_t | |||
185 | pf_key_v2_seq(void) | |||
186 | { | |||
187 | static u_int32_t seq = 0; | |||
188 | ||||
189 | return ++seq; | |||
190 | } | |||
191 | ||||
192 | /* | |||
193 | * Read a PF_KEY packet with SEQ as the sequence number, looping if necessary. | |||
194 | * If SEQ is zero just read the first message we see, otherwise we queue | |||
195 | * messages up until both the PID and the sequence number match. | |||
196 | */ | |||
197 | static struct pf_key_v2_msg * | |||
198 | pf_key_v2_read(u_int32_t seq) | |||
199 | { | |||
200 | ssize_t n; | |||
201 | u_int8_t *buf = 0; | |||
202 | struct pf_key_v2_msg *ret = 0; | |||
203 | struct sadb_msg *msg; | |||
204 | struct sadb_msg hdr; | |||
205 | struct sadb_ext *ext; | |||
206 | struct timespec ts; | |||
207 | struct pollfd pfd[1]; | |||
208 | ||||
209 | pfd[0].fd = pf_key_v2_socket; | |||
210 | pfd[0].events = POLLIN0x0001; | |||
211 | ||||
212 | while (1) { | |||
213 | /* | |||
214 | * If this is a read of a reply we should actually expect the | |||
215 | * reply to get lost as PF_KEY is an unreliable service per | |||
216 | * the specs. Currently we do this by setting a short timeout, | |||
217 | * and if it is not readable in that time, we fail the read. | |||
218 | */ | |||
219 | if (seq) { | |||
220 | n = poll(pfd, 1, PF_KEY_REPLY_TIMEOUT1000 / 1000); | |||
221 | if (n == -1) { | |||
222 | log_error("pf_key_v2_read: poll() failed"); | |||
223 | goto cleanup; | |||
224 | } | |||
225 | if (!n) { | |||
226 | log_print("pf_key_v2_read: " | |||
227 | "no reply from PF_KEY"); | |||
228 | goto cleanup; | |||
229 | } | |||
230 | } | |||
231 | n = recv(pf_key_v2_socket, &hdr, sizeof hdr, MSG_PEEK0x2); | |||
232 | if (n == -1) { | |||
233 | log_error("pf_key_v2_read: recv (%d, ...) failed", | |||
234 | pf_key_v2_socket); | |||
235 | goto cleanup; | |||
236 | } | |||
237 | if (n != sizeof hdr) { | |||
238 | log_error("pf_key_v2_read: recv (%d, ...) " | |||
239 | "returned short packet (%lu bytes)", | |||
240 | pf_key_v2_socket, (unsigned long) n); | |||
241 | goto cleanup; | |||
242 | } | |||
243 | buf = reallocarray(NULL((void *)0), hdr.sadb_msg_len, PF_KEY_V2_CHUNK8); | |||
244 | if (!buf) { | |||
245 | log_error("pf_key_v2_read: reallocarray (%d, %d) failed", | |||
246 | hdr.sadb_msg_len, PF_KEY_V2_CHUNK8); | |||
247 | goto cleanup; | |||
248 | } | |||
249 | n = hdr.sadb_msg_len * PF_KEY_V2_CHUNK8; | |||
250 | ||||
251 | n = read(pf_key_v2_socket, buf, n); | |||
252 | if (n == -1) { | |||
253 | log_error("pf_key_v2_read: read (%d, ...) failed", | |||
254 | pf_key_v2_socket); | |||
255 | goto cleanup; | |||
256 | } | |||
257 | if (n != hdr.sadb_msg_len * PF_KEY_V2_CHUNK8) { | |||
258 | log_print("pf_key_v2_read: read (%d, ...) " | |||
259 | "returned short packet (%lu bytes)", | |||
260 | pf_key_v2_socket, (unsigned long) n); | |||
261 | goto cleanup; | |||
262 | } | |||
263 | LOG_DBG_BUF((LOG_SYSDEP, 80, "pf_key_v2_read: msg", buf, n))log_debug_buf (LOG_SYSDEP, 80, "pf_key_v2_read: msg", buf, n); | |||
264 | ||||
265 | /* We drop all messages that is not what we expect. */ | |||
266 | msg = (struct sadb_msg *) buf; | |||
267 | if (msg->sadb_msg_version != PF_KEY_V22 || | |||
268 | (msg->sadb_msg_pid != 0 && | |||
269 | msg->sadb_msg_pid != (u_int32_t) getpid())) { | |||
270 | if (seq) { | |||
271 | free(buf); | |||
272 | buf = 0; | |||
273 | continue; | |||
274 | } else { | |||
275 | LOG_DBG((LOG_SYSDEP, 90, "pf_key_v2_read:"log_debug (LOG_SYSDEP, 90, "pf_key_v2_read:" "bad version (%d) or PID (%d, mine is " "%ld), ignored", msg->sadb_msg_version, msg->sadb_msg_pid , (long) getpid()) | |||
276 | "bad version (%d) or PID (%d, mine is "log_debug (LOG_SYSDEP, 90, "pf_key_v2_read:" "bad version (%d) or PID (%d, mine is " "%ld), ignored", msg->sadb_msg_version, msg->sadb_msg_pid , (long) getpid()) | |||
277 | "%ld), ignored", msg->sadb_msg_version,log_debug (LOG_SYSDEP, 90, "pf_key_v2_read:" "bad version (%d) or PID (%d, mine is " "%ld), ignored", msg->sadb_msg_version, msg->sadb_msg_pid , (long) getpid()) | |||
278 | msg->sadb_msg_pid, (long) getpid()))log_debug (LOG_SYSDEP, 90, "pf_key_v2_read:" "bad version (%d) or PID (%d, mine is " "%ld), ignored", msg->sadb_msg_version, msg->sadb_msg_pid , (long) getpid()); | |||
279 | goto cleanup; | |||
280 | } | |||
281 | } | |||
282 | /* Parse the message. */ | |||
283 | ret = pf_key_v2_msg_new(msg, PF_KEY_V2_NODE_MALLOCED1); | |||
284 | if (!ret) | |||
285 | goto cleanup; | |||
286 | buf = 0; | |||
287 | for (ext = (struct sadb_ext *) (msg + 1); | |||
288 | (u_int8_t *) ext - (u_int8_t *) msg < | |||
289 | msg->sadb_msg_len * PF_KEY_V2_CHUNK8; | |||
290 | ext = (struct sadb_ext *) ((u_int8_t *) ext + | |||
291 | ext->sadb_ext_len * PF_KEY_V2_CHUNK8)) | |||
292 | pf_key_v2_msg_add(ret, ext, 0); | |||
293 | ||||
294 | /* | |||
295 | * If the message is not the one we are waiting for, queue it | |||
296 | * up. | |||
297 | */ | |||
298 | if (seq && (msg->sadb_msg_pid != (u_int32_t) getpid() || | |||
299 | msg->sadb_msg_seq != seq)) { | |||
300 | clock_gettime(CLOCK_MONOTONIC3, &ts); | |||
301 | timer_add_event("pf_key_v2_notify", | |||
302 | (void (*) (void *)) pf_key_v2_notify, ret, &ts); | |||
303 | ret = 0; | |||
304 | continue; | |||
305 | } | |||
306 | return ret; | |||
307 | } | |||
308 | ||||
309 | cleanup: | |||
310 | free(buf); | |||
311 | if (ret) | |||
312 | pf_key_v2_msg_free(ret); | |||
313 | return 0; | |||
314 | } | |||
315 | ||||
316 | /* Write the message in PMSG to the PF_KEY socket. */ | |||
317 | u_int32_t | |||
318 | pf_key_v2_write(struct pf_key_v2_msg *pmsg) | |||
319 | { | |||
320 | struct iovec *iov = 0; | |||
321 | ssize_t n; | |||
322 | size_t len; | |||
323 | int i, cnt = TAILQ_FIRST(pmsg)((pmsg)->tqh_first)->cnt; | |||
324 | char header[80]; | |||
325 | struct sadb_msg *msg = TAILQ_FIRST(pmsg)((pmsg)->tqh_first)->seg; | |||
326 | struct pf_key_v2_node *np = TAILQ_FIRST(pmsg)((pmsg)->tqh_first); | |||
327 | ||||
328 | iov = calloc(cnt, sizeof *iov); | |||
329 | if (!iov) { | |||
330 | log_error("pf_key_v2_write: malloc (%lu) failed", | |||
331 | cnt * (unsigned long) sizeof *iov); | |||
332 | return 0; | |||
333 | } | |||
334 | msg->sadb_msg_version = PF_KEY_V22; | |||
335 | msg->sadb_msg_errno = 0; | |||
336 | msg->sadb_msg_reserved = 0; | |||
337 | msg->sadb_msg_pid = getpid(); | |||
338 | if (!msg->sadb_msg_seq) | |||
339 | msg->sadb_msg_seq = pf_key_v2_seq(); | |||
340 | ||||
341 | /* Compute the iovec segments as well as the message length. */ | |||
342 | len = 0; | |||
343 | for (i = 0; i < cnt; i++) { | |||
344 | iov[i].iov_base = np->seg; | |||
345 | len += iov[i].iov_len = np->sz; | |||
346 | ||||
347 | /* | |||
348 | * XXX One can envision setting specific extension fields, | |||
349 | * like *_reserved ones here. For now we require them to be | |||
350 | * set by the caller. | |||
351 | */ | |||
352 | ||||
353 | np = TAILQ_NEXT(np, link)((np)->link.tqe_next); | |||
354 | } | |||
355 | msg->sadb_msg_len = len / PF_KEY_V2_CHUNK8; | |||
356 | ||||
357 | for (i = 0; i < cnt; i++) { | |||
358 | snprintf(header, sizeof header, "pf_key_v2_write: iov[%d]", i); | |||
359 | LOG_DBG_BUF((LOG_SYSDEP, 80, header,log_debug_buf (LOG_SYSDEP, 80, header, (u_int8_t *) iov[i].iov_base , iov[i].iov_len) | |||
360 | (u_int8_t *) iov[i].iov_base, iov[i].iov_len))log_debug_buf (LOG_SYSDEP, 80, header, (u_int8_t *) iov[i].iov_base , iov[i].iov_len); | |||
361 | } | |||
362 | ||||
363 | do { | |||
364 | n = writev(pf_key_v2_socket, iov, cnt); | |||
365 | } while (n == -1 && (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)); | |||
366 | if (n == -1) { | |||
367 | log_error("pf_key_v2_write: writev (%d, %p, %d) failed", | |||
368 | pf_key_v2_socket, iov, cnt); | |||
369 | goto cleanup; | |||
370 | } | |||
371 | if ((size_t) n != len) { | |||
372 | log_error("pf_key_v2_write: " | |||
373 | "writev (%d, ...) returned prematurely (%lu)", | |||
374 | pf_key_v2_socket, (unsigned long) n); | |||
375 | goto cleanup; | |||
376 | } | |||
377 | free(iov); | |||
378 | return msg->sadb_msg_seq; | |||
379 | ||||
380 | cleanup: | |||
381 | free(iov); | |||
382 | return 0; | |||
383 | } | |||
384 | ||||
385 | /* | |||
386 | * Do a PF_KEY "call", i.e. write a message MSG, read the reply and return | |||
387 | * it to the caller. | |||
388 | */ | |||
389 | static struct pf_key_v2_msg * | |||
390 | pf_key_v2_call(struct pf_key_v2_msg *msg) | |||
391 | { | |||
392 | u_int32_t seq; | |||
393 | ||||
394 | seq = pf_key_v2_write(msg); | |||
395 | if (!seq) | |||
396 | return 0; | |||
397 | return pf_key_v2_read(seq); | |||
398 | } | |||
399 | ||||
400 | /* Find the TYPE extension in MSG. Return zero if none found. */ | |||
401 | static struct pf_key_v2_node * | |||
402 | pf_key_v2_find_ext(struct pf_key_v2_msg *msg, u_int16_t type) | |||
403 | { | |||
404 | struct pf_key_v2_node *ext; | |||
405 | ||||
406 | for (ext = TAILQ_NEXT(TAILQ_FIRST(msg), link)((((msg)->tqh_first))->link.tqe_next); ext; | |||
407 | ext = TAILQ_NEXT(ext, link)((ext)->link.tqe_next)) | |||
408 | if (ext->type == type) | |||
409 | return ext; | |||
410 | return 0; | |||
411 | } | |||
412 | ||||
413 | /* | |||
414 | * Open the PF_KEYv2 sockets and return the descriptor used for notifies. | |||
415 | * Return -1 for failure and -2 if no notifies will show up. | |||
416 | */ | |||
417 | int | |||
418 | pf_key_v2_open(void) | |||
419 | { | |||
420 | int fd = -1, err; | |||
421 | struct sadb_msg msg; | |||
422 | struct pf_key_v2_msg *regmsg = 0, *ret = 0; | |||
423 | ||||
424 | /* Open the socket we use to speak to IPsec. */ | |||
425 | pf_key_v2_socket = -1; | |||
426 | fd = socket(PF_KEY30, SOCK_RAW3, PF_KEY_V22); | |||
427 | if (fd == -1) { | |||
428 | log_error("pf_key_v2_open: " | |||
429 | "socket (PF_KEY, SOCK_RAW, PF_KEY_V2) failed"); | |||
430 | goto cleanup; | |||
431 | } | |||
432 | pf_key_v2_socket = fd; | |||
433 | ||||
434 | /* Register it to get ESP and AH acquires from the kernel. */ | |||
435 | msg.sadb_msg_seq = 0; | |||
436 | msg.sadb_msg_type = SADB_REGISTER7; | |||
437 | msg.sadb_msg_satype = SADB_SATYPE_ESP2; | |||
438 | regmsg = pf_key_v2_msg_new(&msg, 0); | |||
439 | if (!regmsg) | |||
440 | goto cleanup; | |||
441 | ret = pf_key_v2_call(regmsg); | |||
442 | pf_key_v2_msg_free(regmsg); | |||
443 | if (!ret) | |||
444 | goto cleanup; | |||
445 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
446 | if (err) { | |||
447 | log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); | |||
448 | goto cleanup; | |||
449 | } | |||
450 | /* XXX Register the accepted transforms. */ | |||
451 | ||||
452 | pf_key_v2_msg_free(ret); | |||
453 | ret = 0; | |||
454 | ||||
455 | msg.sadb_msg_seq = 0; | |||
456 | msg.sadb_msg_type = SADB_REGISTER7; | |||
457 | msg.sadb_msg_satype = SADB_SATYPE_AH1; | |||
458 | regmsg = pf_key_v2_msg_new(&msg, 0); | |||
459 | if (!regmsg) | |||
460 | goto cleanup; | |||
461 | ret = pf_key_v2_call(regmsg); | |||
462 | pf_key_v2_msg_free(regmsg); | |||
463 | if (!ret) | |||
464 | goto cleanup; | |||
465 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
466 | if (err) { | |||
467 | log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); | |||
468 | goto cleanup; | |||
469 | } | |||
470 | /* XXX Register the accepted transforms. */ | |||
471 | ||||
472 | pf_key_v2_msg_free(ret); | |||
473 | ret = 0; | |||
474 | ||||
475 | msg.sadb_msg_seq = 0; | |||
476 | msg.sadb_msg_type = SADB_REGISTER7; | |||
477 | msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9; | |||
478 | regmsg = pf_key_v2_msg_new(&msg, 0); | |||
479 | if (!regmsg) | |||
480 | goto cleanup; | |||
481 | ret = pf_key_v2_call(regmsg); | |||
482 | pf_key_v2_msg_free(regmsg); | |||
483 | if (!ret) | |||
484 | goto cleanup; | |||
485 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
486 | if (err) { | |||
487 | log_print("pf_key_v2_open: REGISTER: %s", strerror(err)); | |||
488 | goto cleanup; | |||
489 | } | |||
490 | /* XXX Register the accepted transforms. */ | |||
491 | ||||
492 | pf_key_v2_msg_free(ret); | |||
493 | ||||
494 | return fd; | |||
495 | ||||
496 | cleanup: | |||
497 | if (pf_key_v2_socket != -1) { | |||
498 | close(pf_key_v2_socket); | |||
499 | pf_key_v2_socket = -1; | |||
500 | } | |||
501 | if (ret) | |||
502 | pf_key_v2_msg_free(ret); | |||
503 | return -1; | |||
504 | } | |||
505 | ||||
506 | /* | |||
507 | * Generate a SPI for protocol PROTO and the source/destination pair given by | |||
508 | * SRC, SRCLEN, DST & DSTLEN. Stash the SPI size in SZ. | |||
509 | */ | |||
510 | u_int8_t * | |||
511 | pf_key_v2_get_spi(size_t *sz, u_int8_t proto, struct sockaddr *src, | |||
512 | struct sockaddr *dst, u_int32_t seq) | |||
513 | { | |||
514 | struct sadb_msg msg; | |||
515 | struct sadb_sa *sa; | |||
516 | struct sadb_address *addr = 0; | |||
517 | struct sadb_spirange spirange; | |||
518 | struct pf_key_v2_msg *getspi = 0, *ret = 0; | |||
519 | struct pf_key_v2_node *ext; | |||
520 | u_int8_t *spi = 0; | |||
521 | int len, err; | |||
522 | ||||
523 | msg.sadb_msg_type = SADB_GETSPI1; | |||
524 | switch (proto) { | |||
525 | case IPSEC_PROTO_IPSEC_ESP3: | |||
526 | msg.sadb_msg_satype = SADB_SATYPE_ESP2; | |||
527 | break; | |||
528 | case IPSEC_PROTO_IPSEC_AH2: | |||
529 | msg.sadb_msg_satype = SADB_SATYPE_AH1; | |||
530 | break; | |||
531 | case IPSEC_PROTO_IPCOMP4: | |||
532 | msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9; | |||
533 | break; | |||
534 | default: | |||
535 | log_print("pf_key_v2_get_spi: invalid proto %d", proto); | |||
536 | goto cleanup; | |||
537 | } | |||
538 | ||||
539 | /* Set the sequence number from the ACQUIRE message. */ | |||
540 | msg.sadb_msg_seq = seq; | |||
541 | getspi = pf_key_v2_msg_new(&msg, 0); | |||
542 | if (!getspi) | |||
543 | goto cleanup; | |||
544 | ||||
545 | /* Setup the ADDRESS extensions. */ | |||
546 | len = | |||
547 | sizeof(struct sadb_address) + PF_KEY_V2_ROUND(SA_LEN(src))(((((src)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
548 | addr = calloc(1, len); | |||
549 | if (!addr) | |||
550 | goto cleanup; | |||
551 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC5; | |||
552 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
553 | addr->sadb_address_reserved = 0; | |||
554 | memcpy(addr + 1, src, SA_LEN(src)((src)->sa_len)); | |||
555 | switch (((struct sockaddr *) (addr + 1))->sa_family) { | |||
556 | case AF_INET2: | |||
557 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
558 | break; | |||
559 | case AF_INET624: | |||
560 | ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | |||
561 | break; | |||
562 | } | |||
563 | if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) addr, | |||
564 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
565 | goto cleanup; | |||
566 | addr = 0; | |||
567 | ||||
568 | len = sizeof(struct sadb_address) + PF_KEY_V2_ROUND(SA_LEN(dst))(((((dst)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
569 | addr = calloc(1, len); | |||
570 | if (!addr) | |||
571 | goto cleanup; | |||
572 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST6; | |||
573 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
574 | addr->sadb_address_reserved = 0; | |||
575 | memcpy(addr + 1, dst, SA_LEN(dst)((dst)->sa_len)); | |||
576 | switch (((struct sockaddr *) (addr + 1))->sa_family) { | |||
577 | case AF_INET2: | |||
578 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
579 | break; | |||
580 | case AF_INET624: | |||
581 | ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | |||
582 | break; | |||
583 | } | |||
584 | if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) addr, | |||
585 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
586 | goto cleanup; | |||
587 | addr = 0; | |||
588 | ||||
589 | /* Setup the SPIRANGE extension. */ | |||
590 | spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE16; | |||
591 | spirange.sadb_spirange_len = sizeof spirange / PF_KEY_V2_CHUNK8; | |||
592 | if (proto == IPSEC_PROTO_IPCOMP4) { | |||
593 | spirange.sadb_spirange_min = CPI_RESERVED_MAX255 + 1; | |||
594 | spirange.sadb_spirange_max = CPI_PRIVATE_MIN61440 - 1; | |||
595 | } else { | |||
596 | spirange.sadb_spirange_min = IPSEC_SPI_LOW0x100; | |||
597 | spirange.sadb_spirange_max = 0xffffffff; | |||
598 | } | |||
599 | spirange.sadb_spirange_reserved = 0; | |||
600 | if (pf_key_v2_msg_add(getspi, (struct sadb_ext *)&spirange, 0) == -1) | |||
601 | goto cleanup; | |||
602 | ||||
603 | ret = pf_key_v2_call(getspi); | |||
604 | pf_key_v2_msg_free(getspi); | |||
605 | getspi = 0; | |||
606 | if (!ret) | |||
607 | goto cleanup; | |||
608 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
609 | if (err) { | |||
610 | log_print("pf_key_v2_get_spi: GETSPI: %s", strerror(err)); | |||
611 | goto cleanup; | |||
612 | } | |||
613 | ext = pf_key_v2_find_ext(ret, SADB_EXT_SA1); | |||
614 | if (!ext) { | |||
615 | log_print("pf_key_v2_get_spi: no SA extension found"); | |||
616 | goto cleanup; | |||
617 | } | |||
618 | sa = ext->seg; | |||
619 | ||||
620 | /* IPCOMP CPIs are only 16 bits long. */ | |||
621 | *sz = (proto == IPSEC_PROTO_IPCOMP4) ? sizeof(u_int16_t) | |||
622 | : sizeof sa->sadb_sa_spi; | |||
623 | spi = malloc(*sz); | |||
624 | if (!spi) | |||
625 | goto cleanup; | |||
626 | /* XXX This is ugly. */ | |||
627 | if (proto == IPSEC_PROTO_IPCOMP4) { | |||
628 | u_int32_t tspi = ntohl(sa->sadb_sa_spi)(__uint32_t)(__builtin_constant_p(sa->sadb_sa_spi) ? (__uint32_t )(((__uint32_t)(sa->sadb_sa_spi) & 0xff) << 24 | ((__uint32_t)(sa->sadb_sa_spi) & 0xff00) << 8 | ((__uint32_t)(sa->sadb_sa_spi) & 0xff0000) >> 8 | ((__uint32_t)(sa->sadb_sa_spi) & 0xff000000) >> 24) : __swap32md(sa->sadb_sa_spi)); | |||
629 | *(u_int16_t *) spi = htons((u_int16_t) tspi)(__uint16_t)(__builtin_constant_p((u_int16_t) tspi) ? (__uint16_t )(((__uint16_t)((u_int16_t) tspi) & 0xffU) << 8 | ( (__uint16_t)((u_int16_t) tspi) & 0xff00U) >> 8) : __swap16md ((u_int16_t) tspi)); | |||
630 | } else | |||
631 | memcpy(spi, &sa->sadb_sa_spi, *sz); | |||
632 | ||||
633 | pf_key_v2_msg_free(ret); | |||
634 | ||||
635 | LOG_DBG_BUF((LOG_SYSDEP, 50, "pf_key_v2_get_spi: spi", spi, *sz))log_debug_buf (LOG_SYSDEP, 50, "pf_key_v2_get_spi: spi", spi, *sz); | |||
636 | return spi; | |||
637 | ||||
638 | cleanup: | |||
639 | free(spi); | |||
640 | free(addr); | |||
641 | if (getspi) | |||
642 | pf_key_v2_msg_free(getspi); | |||
643 | if (ret) | |||
644 | pf_key_v2_msg_free(ret); | |||
645 | return 0; | |||
646 | } | |||
647 | ||||
648 | /* Fetch SA information from the kernel. XXX OpenBSD only? */ | |||
649 | struct sa_kinfo * | |||
650 | pf_key_v2_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, | |||
651 | struct sockaddr *dst) | |||
652 | { | |||
653 | struct sadb_msg msg; | |||
654 | struct sadb_sa *ssa; | |||
655 | struct sadb_address *addr = 0; | |||
656 | struct sockaddr *sa; | |||
657 | struct sadb_lifetime *life; | |||
658 | struct pf_key_v2_msg *gettdb = 0, *ret = 0; | |||
659 | struct pf_key_v2_node *ext; | |||
660 | static struct sa_kinfo ksa; | |||
661 | struct sadb_x_udpencap *udpencap; | |||
662 | int len, err; | |||
663 | ||||
664 | if (spi_sz != sizeof (ssa->sadb_sa_spi)) | |||
665 | return 0; | |||
666 | ||||
667 | msg.sadb_msg_type = SADB_GET5; | |||
668 | switch (proto) { | |||
669 | case IPSEC_PROTO_IPSEC_ESP3: | |||
670 | msg.sadb_msg_satype = SADB_SATYPE_ESP2; | |||
671 | break; | |||
672 | case IPSEC_PROTO_IPSEC_AH2: | |||
673 | msg.sadb_msg_satype = SADB_SATYPE_AH1; | |||
674 | break; | |||
675 | case IPSEC_PROTO_IPCOMP4: | |||
676 | msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9; | |||
677 | break; | |||
678 | default: | |||
679 | log_print("pf_key_v2_get_kernel_sa: invalid proto %d", proto); | |||
680 | goto cleanup; | |||
681 | } | |||
682 | ||||
683 | gettdb = pf_key_v2_msg_new(&msg, 0); | |||
684 | if (!gettdb) | |||
685 | goto cleanup; | |||
686 | ||||
687 | /* SPI */ | |||
688 | ssa = calloc(1, sizeof *ssa); | |||
689 | if (!ssa) { | |||
690 | log_print("pf_key_v2_get_kernel_sa: calloc(1, %lu) failed", | |||
691 | (unsigned long)sizeof *ssa); | |||
692 | goto cleanup; | |||
693 | } | |||
694 | ||||
695 | ssa->sadb_sa_exttype = SADB_EXT_SA1; | |||
696 | ssa->sadb_sa_len = sizeof *ssa / PF_KEY_V2_CHUNK8; | |||
697 | memcpy(&ssa->sadb_sa_spi, spi, sizeof ssa->sadb_sa_spi); | |||
698 | ssa->sadb_sa_state = SADB_SASTATE_MATURE1; | |||
699 | if (pf_key_v2_msg_add(gettdb, (struct sadb_ext *)ssa, | |||
700 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
701 | goto cleanup; | |||
702 | ssa = 0; | |||
703 | ||||
704 | /* Address */ | |||
705 | len = | |||
706 | sizeof(struct sadb_address) + PF_KEY_V2_ROUND(SA_LEN(dst))(((((dst)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
707 | addr = calloc(1, len); | |||
708 | if (!addr) | |||
709 | goto cleanup; | |||
710 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST6; | |||
711 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
712 | addr->sadb_address_reserved = 0; | |||
713 | memcpy(addr + 1, dst, SA_LEN(dst)((dst)->sa_len)); | |||
714 | switch (((struct sockaddr *) (addr + 1))->sa_family) { | |||
715 | case AF_INET2: | |||
716 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
717 | break; | |||
718 | case AF_INET624: | |||
719 | ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | |||
720 | break; | |||
721 | } | |||
722 | if (pf_key_v2_msg_add(gettdb, (struct sadb_ext *)addr, | |||
723 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
724 | goto cleanup; | |||
725 | addr = 0; | |||
726 | ||||
727 | ret = pf_key_v2_call(gettdb); | |||
728 | pf_key_v2_msg_free(gettdb); | |||
729 | gettdb = 0; | |||
730 | if (!ret) | |||
731 | goto cleanup; | |||
732 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
733 | if (err) { | |||
734 | log_print("pf_key_v2_get_kernel_sa: SADB_GET: %s", | |||
735 | strerror(err)); | |||
736 | goto cleanup; | |||
737 | } | |||
738 | ||||
739 | /* Extract the data. */ | |||
740 | bzero(&ksa, sizeof ksa); | |||
741 | ||||
742 | ext = pf_key_v2_find_ext(ret, SADB_EXT_SA1); | |||
743 | if (!ext) | |||
744 | goto cleanup; | |||
745 | ||||
746 | ssa = (struct sadb_sa *)ext; | |||
747 | ksa.spi = ssa->sadb_sa_spi; | |||
748 | ksa.wnd = ssa->sadb_sa_replay; | |||
749 | ksa.flags = ssa->sadb_sa_flags; | |||
750 | ||||
751 | ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_CURRENT2); | |||
752 | if (ext) { | |||
753 | life = (struct sadb_lifetime *)ext->seg; | |||
754 | ksa.cur_allocations = life->sadb_lifetime_allocations; | |||
755 | ksa.cur_bytes = life->sadb_lifetime_bytes; | |||
756 | ksa.first_use = life->sadb_lifetime_usetime; | |||
757 | ksa.established = life->sadb_lifetime_addtime; | |||
758 | } | |||
759 | ||||
760 | ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_SOFT4); | |||
761 | if (ext) { | |||
762 | life = (struct sadb_lifetime *)ext->seg; | |||
763 | ksa.soft_allocations = life->sadb_lifetime_allocations; | |||
764 | ksa.soft_bytes = life->sadb_lifetime_bytes; | |||
765 | ksa.soft_timeout = life->sadb_lifetime_addtime; | |||
766 | ksa.soft_first_use = life->sadb_lifetime_usetime; | |||
767 | } | |||
768 | ||||
769 | ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_HARD3); | |||
770 | if (ext) { | |||
771 | life = (struct sadb_lifetime *)ext->seg; | |||
772 | ksa.exp_allocations = life->sadb_lifetime_allocations; | |||
773 | ksa.exp_bytes = life->sadb_lifetime_bytes; | |||
774 | ksa.exp_timeout = life->sadb_lifetime_addtime; | |||
775 | ksa.exp_first_use = life->sadb_lifetime_usetime; | |||
776 | } | |||
777 | ||||
778 | ext = pf_key_v2_find_ext(ret, SADB_X_EXT_LIFETIME_LASTUSE32); | |||
779 | if (ext) { | |||
780 | life = (struct sadb_lifetime *)ext->seg; | |||
781 | ksa.last_used = life->sadb_lifetime_usetime; | |||
782 | } | |||
783 | ||||
784 | ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_SRC5); | |||
785 | if (ext) { | |||
786 | sa = (struct sockaddr *)ext->seg; | |||
787 | memcpy(&ksa.src, sa, | |||
788 | sa->sa_family == AF_INET2 ? sizeof(struct sockaddr_in) : | |||
789 | sizeof(struct sockaddr_in6)); | |||
790 | } | |||
791 | ||||
792 | ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_DST6); | |||
793 | if (ext) { | |||
794 | sa = (struct sockaddr *)ext->seg; | |||
795 | memcpy(&ksa.dst, sa, | |||
796 | sa->sa_family == AF_INET2 ? sizeof(struct sockaddr_in) : | |||
797 | sizeof(struct sockaddr_in6)); | |||
798 | } | |||
799 | ||||
800 | ext = pf_key_v2_find_ext(ret, SADB_X_EXT_UDPENCAP31); | |||
801 | if (ext) { | |||
802 | udpencap = (struct sadb_x_udpencap *)ext->seg; | |||
803 | ksa.udpencap_port = udpencap->sadb_x_udpencap_port; | |||
804 | } | |||
805 | ||||
806 | pf_key_v2_msg_free(ret); | |||
807 | ||||
808 | LOG_DBG_BUF((LOG_SYSDEP, 50, "pf_key_v2_get_kernel_sa: spi", spi,log_debug_buf (LOG_SYSDEP, 50, "pf_key_v2_get_kernel_sa: spi" , spi, spi_sz) | |||
809 | spi_sz))log_debug_buf (LOG_SYSDEP, 50, "pf_key_v2_get_kernel_sa: spi" , spi, spi_sz); | |||
810 | ||||
811 | return &ksa; | |||
812 | ||||
813 | cleanup: | |||
814 | free(addr); | |||
815 | if (gettdb) | |||
816 | pf_key_v2_msg_free(gettdb); | |||
817 | if (ret) | |||
818 | pf_key_v2_msg_free(ret); | |||
819 | return 0; | |||
820 | } | |||
821 | ||||
822 | static void | |||
823 | pf_key_v2_setup_sockaddr(void *res, struct sockaddr *src, | |||
824 | struct sockaddr *dst, in_port_t port, int ingress) | |||
825 | { | |||
826 | struct sockaddr_in *ip4_sa; | |||
827 | struct sockaddr_in6 *ip6_sa; | |||
828 | u_int8_t *p; | |||
829 | ||||
830 | switch (src->sa_family) { | |||
831 | case AF_INET2: | |||
832 | ip4_sa = (struct sockaddr_in *) res; | |||
833 | ip4_sa->sin_family = AF_INET2; | |||
834 | ip4_sa->sin_len = sizeof *ip4_sa; | |||
835 | ip4_sa->sin_port = port; | |||
836 | if (dst) | |||
837 | p = (u_int8_t *) (ingress ? | |||
838 | &((struct sockaddr_in *)src)->sin_addr.s_addr : | |||
839 | &((struct sockaddr_in *)dst)->sin_addr.s_addr); | |||
840 | else | |||
841 | p = (u_int8_t *)&((struct sockaddr_in *)src)->sin_addr.s_addr; | |||
842 | ip4_sa->sin_addr.s_addr = *((in_addr_t *) p); | |||
843 | break; | |||
844 | ||||
845 | case AF_INET624: | |||
846 | ip6_sa = (struct sockaddr_in6 *) res; | |||
847 | ip6_sa->sin6_family = AF_INET624; | |||
848 | ip6_sa->sin6_len = sizeof *ip6_sa; | |||
849 | ip6_sa->sin6_port = port; | |||
850 | if (dst) | |||
851 | p = (u_int8_t *) (ingress ? | |||
852 | &((struct sockaddr_in6 *)src)->sin6_addr.s6_addr__u6_addr.__u6_addr8 : | |||
853 | &((struct sockaddr_in6 *)dst)->sin6_addr.s6_addr__u6_addr.__u6_addr8); | |||
854 | else | |||
855 | p = (u_int8_t *)&((struct sockaddr_in6 *)src)->sin6_addr.s6_addr__u6_addr.__u6_addr8; | |||
856 | memcpy(ip6_sa->sin6_addr.s6_addr__u6_addr.__u6_addr8, p, sizeof(struct in6_addr)); | |||
857 | break; | |||
858 | ||||
859 | default: | |||
860 | log_print("pf_key_v2_setup_sockaddr: unknown family %d\n", | |||
861 | src->sa_family); | |||
862 | break; | |||
863 | } | |||
864 | } | |||
865 | ||||
866 | /* | |||
867 | * Store/update a PF_KEY_V2 security association with full information from the | |||
868 | * IKE SA and PROTO into the kernel. INCOMING is set if we are setting the | |||
869 | * parameters for the incoming SA, and cleared otherwise. | |||
870 | */ | |||
871 | int | |||
872 | pf_key_v2_set_spi(struct sa *sa, struct proto *proto, int incoming, | |||
873 | struct sa *isakmp_sa) | |||
874 | { | |||
875 | struct sadb_msg msg; | |||
876 | struct sadb_sa ssa; | |||
877 | struct sadb_x_tag *stag = NULL((void *)0); | |||
878 | struct sadb_lifetime *life = 0; | |||
879 | struct sadb_address *addr = 0; | |||
880 | struct sadb_key *key = 0; | |||
881 | struct sadb_ident *sid = 0; | |||
882 | struct sockaddr *src, *dst; | |||
883 | struct pf_key_v2_msg *update = 0, *ret = 0; | |||
884 | struct ipsec_proto *iproto = proto->data; | |||
885 | size_t len; | |||
886 | int keylen, hashlen, err; | |||
887 | u_int8_t *pp; | |||
888 | int idtype; | |||
889 | struct ipsec_sa *isa = sa->data; | |||
890 | struct sadb_protocol flowtype, tprotocol; | |||
891 | struct sadb_x_udpencap udpencap; | |||
892 | char *addr_str, *s; | |||
893 | char iface_str[32]; | |||
894 | ||||
895 | msg.sadb_msg_type = incoming ? SADB_UPDATE2 : SADB_ADD3; | |||
896 | switch (proto->proto) { | |||
897 | case IPSEC_PROTO_IPSEC_ESP3: | |||
898 | msg.sadb_msg_satype = SADB_SATYPE_ESP2; | |||
899 | keylen = ipsec_esp_enckeylength(proto); | |||
900 | hashlen = ipsec_esp_authkeylength(proto); | |||
901 | ||||
902 | switch (proto->id) { | |||
903 | case IPSEC_ESP_3DES3: | |||
904 | ssa.sadb_sa_encrypt = SADB_EALG_3DESCBC3; | |||
905 | break; | |||
906 | ||||
907 | case IPSEC_ESP_AES12: | |||
908 | ssa.sadb_sa_encrypt = SADB_X_EALG_AES12; | |||
909 | break; | |||
910 | ||||
911 | case IPSEC_ESP_AES_CTR13: | |||
912 | ssa.sadb_sa_encrypt = SADB_X_EALG_AESCTR13; | |||
913 | break; | |||
914 | ||||
915 | case IPSEC_ESP_AES_GCM_1620: | |||
916 | ssa.sadb_sa_encrypt = SADB_X_EALG_AESGCM1620; | |||
917 | break; | |||
918 | ||||
919 | case IPSEC_ESP_AES_GMAC23: | |||
920 | ssa.sadb_sa_encrypt = SADB_X_EALG_AESGMAC21; | |||
921 | break; | |||
922 | ||||
923 | case IPSEC_ESP_CAST6: | |||
924 | ssa.sadb_sa_encrypt = SADB_X_EALG_CAST6; | |||
925 | break; | |||
926 | ||||
927 | case IPSEC_ESP_BLOWFISH7: | |||
928 | ssa.sadb_sa_encrypt = SADB_X_EALG_BLF7; | |||
929 | break; | |||
930 | ||||
931 | case IPSEC_ESP_NULL11: | |||
932 | ssa.sadb_sa_encrypt = SADB_EALG_NULL11; | |||
933 | break; | |||
934 | ||||
935 | default: | |||
936 | LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: "log_debug (LOG_SYSDEP, 50, "pf_key_v2_set_spi: " "unknown encryption algorithm %d" , proto->id) | |||
937 | "unknown encryption algorithm %d", proto->id))log_debug (LOG_SYSDEP, 50, "pf_key_v2_set_spi: " "unknown encryption algorithm %d" , proto->id); | |||
938 | return -1; | |||
939 | } | |||
940 | ||||
941 | switch (iproto->auth) { | |||
942 | case IPSEC_AUTH_HMAC_MD51: | |||
943 | ssa.sadb_sa_auth = SADB_AALG_MD5HMAC2; | |||
944 | break; | |||
945 | ||||
946 | case IPSEC_AUTH_HMAC_SHA2: | |||
947 | ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC3; | |||
948 | break; | |||
949 | ||||
950 | case IPSEC_AUTH_HMAC_RIPEMD8: | |||
951 | ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC8; | |||
952 | break; | |||
953 | ||||
954 | case IPSEC_AUTH_HMAC_SHA2_2565: | |||
955 | ssa.sadb_sa_auth = SADB_X_AALG_SHA2_2565; | |||
956 | break; | |||
957 | ||||
958 | case IPSEC_AUTH_HMAC_SHA2_3846: | |||
959 | ssa.sadb_sa_auth = SADB_X_AALG_SHA2_3846; | |||
960 | break; | |||
961 | ||||
962 | case IPSEC_AUTH_HMAC_SHA2_5127: | |||
963 | ssa.sadb_sa_auth = SADB_X_AALG_SHA2_5127; | |||
964 | break; | |||
965 | ||||
966 | case IPSEC_AUTH_DES_MAC3: | |||
967 | case IPSEC_AUTH_KPDK4: | |||
968 | /* XXX We should be supporting KPDK */ | |||
969 | LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: "log_debug (LOG_SYSDEP, 50, "pf_key_v2_set_spi: " "unknown authentication algorithm %d" , iproto->auth) | |||
970 | "unknown authentication algorithm %d",log_debug (LOG_SYSDEP, 50, "pf_key_v2_set_spi: " "unknown authentication algorithm %d" , iproto->auth) | |||
971 | iproto->auth))log_debug (LOG_SYSDEP, 50, "pf_key_v2_set_spi: " "unknown authentication algorithm %d" , iproto->auth); | |||
972 | return -1; | |||
973 | ||||
974 | default: | |||
975 | ssa.sadb_sa_auth = SADB_AALG_NONE0; | |||
976 | } | |||
977 | break; | |||
978 | ||||
979 | case IPSEC_PROTO_IPSEC_AH2: | |||
980 | msg.sadb_msg_satype = SADB_SATYPE_AH1; | |||
981 | hashlen = ipsec_ah_keylength(proto); | |||
982 | keylen = 0; | |||
983 | ||||
984 | ssa.sadb_sa_encrypt = SADB_EALG_NONE0; | |||
985 | switch (proto->id) { | |||
986 | case IPSEC_AH_MD52: | |||
987 | ssa.sadb_sa_auth = SADB_AALG_MD5HMAC2; | |||
988 | break; | |||
989 | ||||
990 | case IPSEC_AH_SHA3: | |||
991 | ssa.sadb_sa_auth = SADB_AALG_SHA1HMAC3; | |||
992 | break; | |||
993 | ||||
994 | case IPSEC_AH_RIPEMD8: | |||
995 | ssa.sadb_sa_auth = SADB_X_AALG_RIPEMD160HMAC8; | |||
996 | break; | |||
997 | ||||
998 | case IPSEC_AH_SHA2_2565: | |||
999 | ssa.sadb_sa_auth = SADB_X_AALG_SHA2_2565; | |||
1000 | break; | |||
1001 | ||||
1002 | case IPSEC_AH_SHA2_3846: | |||
1003 | ssa.sadb_sa_auth = SADB_X_AALG_SHA2_3846; | |||
1004 | break; | |||
1005 | ||||
1006 | case IPSEC_AH_SHA2_5127: | |||
1007 | ssa.sadb_sa_auth = SADB_X_AALG_SHA2_5127; | |||
1008 | break; | |||
1009 | ||||
1010 | default: | |||
1011 | LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: "log_debug (LOG_SYSDEP, 50, "pf_key_v2_set_spi: " "unknown authentication algorithm %d" , proto->id) | |||
1012 | "unknown authentication algorithm %d", proto->id))log_debug (LOG_SYSDEP, 50, "pf_key_v2_set_spi: " "unknown authentication algorithm %d" , proto->id); | |||
1013 | goto cleanup; | |||
1014 | } | |||
1015 | break; | |||
1016 | ||||
1017 | case IPSEC_PROTO_IPCOMP4: | |||
1018 | msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9; | |||
1019 | ssa.sadb_sa_auth = SADB_AALG_NONE0; | |||
1020 | keylen = 0; | |||
1021 | hashlen = 0; | |||
1022 | ||||
1023 | /* | |||
1024 | * Put compression algorithm type in the sadb_sa_encrypt | |||
1025 | * field. | |||
1026 | */ | |||
1027 | switch (proto->id) { | |||
1028 | case IPSEC_IPCOMP_OUI1: | |||
1029 | ssa.sadb_sa_encrypt = SADB_X_CALG_OUI1; | |||
1030 | break; | |||
1031 | ||||
1032 | case IPSEC_IPCOMP_DEFLATE2: | |||
1033 | ssa.sadb_sa_encrypt = SADB_X_CALG_DEFLATE2; | |||
1034 | break; | |||
1035 | ||||
1036 | default: | |||
1037 | break; | |||
1038 | } | |||
1039 | break; | |||
1040 | ||||
1041 | default: | |||
1042 | log_print("pf_key_v2_set_spi: invalid proto %d", proto->proto); | |||
1043 | goto cleanup; | |||
1044 | } | |||
1045 | if (incoming) | |||
1046 | sa->transport->vtbl->get_src(sa->transport, &dst); | |||
1047 | else | |||
1048 | sa->transport->vtbl->get_dst(sa->transport, &dst); | |||
1049 | msg.sadb_msg_seq = sa->seq; | |||
1050 | update = pf_key_v2_msg_new(&msg, 0); | |||
1051 | if (!update) | |||
1052 | goto cleanup; | |||
1053 | ||||
1054 | /* Setup the rest of the SA extension. */ | |||
1055 | ssa.sadb_sa_exttype = SADB_EXT_SA1; | |||
1056 | ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK8; | |||
1057 | if (proto->spi_sz[incoming] == 2) /* IPCOMP uses 16bit CPIs. */ | |||
1058 | ssa.sadb_sa_spi = htonl(proto->spi[incoming][0] << 8 |(__uint32_t)(__builtin_constant_p(proto->spi[incoming][0] << 8 | proto->spi[incoming][1]) ? (__uint32_t)(((__uint32_t) (proto->spi[incoming][0] << 8 | proto->spi[incoming ][1]) & 0xff) << 24 | ((__uint32_t)(proto->spi[incoming ][0] << 8 | proto->spi[incoming][1]) & 0xff00) << 8 | ((__uint32_t)(proto->spi[incoming][0] << 8 | proto ->spi[incoming][1]) & 0xff0000) >> 8 | ((__uint32_t )(proto->spi[incoming][0] << 8 | proto->spi[incoming ][1]) & 0xff000000) >> 24) : __swap32md(proto->spi [incoming][0] << 8 | proto->spi[incoming][1])) | |||
1059 | proto->spi[incoming][1])(__uint32_t)(__builtin_constant_p(proto->spi[incoming][0] << 8 | proto->spi[incoming][1]) ? (__uint32_t)(((__uint32_t) (proto->spi[incoming][0] << 8 | proto->spi[incoming ][1]) & 0xff) << 24 | ((__uint32_t)(proto->spi[incoming ][0] << 8 | proto->spi[incoming][1]) & 0xff00) << 8 | ((__uint32_t)(proto->spi[incoming][0] << 8 | proto ->spi[incoming][1]) & 0xff0000) >> 8 | ((__uint32_t )(proto->spi[incoming][0] << 8 | proto->spi[incoming ][1]) & 0xff000000) >> 24) : __swap32md(proto->spi [incoming][0] << 8 | proto->spi[incoming][1])); | |||
1060 | else | |||
1061 | memcpy(&ssa.sadb_sa_spi, proto->spi[incoming], | |||
1062 | sizeof ssa.sadb_sa_spi); | |||
1063 | ssa.sadb_sa_replay = conf_get_str("General", "Shared-SADB") ? 0 : | |||
1064 | iproto->replay_window; | |||
1065 | ssa.sadb_sa_state = SADB_SASTATE_MATURE1; | |||
1066 | ssa.sadb_sa_flags = 0; | |||
1067 | if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL1 || | |||
1068 | iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL3 || | |||
1069 | iproto->encap_mode == IPSEC_ENCAP_UDP_ENCAP_TUNNEL_DRAFT61443) | |||
1070 | ssa.sadb_sa_flags = SADB_X_SAFLAGS_TUNNEL0x004; | |||
1071 | ||||
1072 | if (isakmp_sa->flags & SA_FLAG_NAT_T_ENABLE0x100) { | |||
1073 | bzero(&udpencap, sizeof udpencap); | |||
1074 | ssa.sadb_sa_flags |= SADB_X_SAFLAGS_UDPENCAP0x200; | |||
1075 | udpencap.sadb_x_udpencap_exttype = SADB_X_EXT_UDPENCAP31; | |||
1076 | udpencap.sadb_x_udpencap_len = | |||
1077 | sizeof udpencap / PF_KEY_V2_CHUNK8; | |||
1078 | udpencap.sadb_x_udpencap_port = sockaddr_port(dst); | |||
1079 | if (pf_key_v2_msg_add(update, (struct sadb_ext *)&udpencap, 0) | |||
1080 | == -1) | |||
1081 | goto cleanup; | |||
1082 | } | |||
1083 | ||||
1084 | if (pf_key_v2_msg_add(update, (struct sadb_ext *)&ssa, 0) == -1) | |||
1085 | goto cleanup; | |||
1086 | ||||
1087 | if (sa->seconds || sa->kilobytes) { | |||
1088 | /* Setup the hard limits. */ | |||
1089 | life = malloc(sizeof *life); | |||
1090 | if (!life) | |||
1091 | goto cleanup; | |||
1092 | life->sadb_lifetime_len = sizeof *life / PF_KEY_V2_CHUNK8; | |||
1093 | life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD3; | |||
1094 | life->sadb_lifetime_allocations = 0; | |||
1095 | life->sadb_lifetime_bytes = sa->kilobytes * 1024; | |||
1096 | /* | |||
1097 | * XXX I am not sure which one is best in security respect. | |||
1098 | * Maybe the RFCs actually mandate what a lifetime really is. | |||
1099 | */ | |||
1100 | #if 0 | |||
1101 | life->sadb_lifetime_addtime = 0; | |||
1102 | life->sadb_lifetime_usetime = sa->seconds; | |||
1103 | #else | |||
1104 | life->sadb_lifetime_addtime = sa->seconds; | |||
1105 | life->sadb_lifetime_usetime = 0; | |||
1106 | #endif | |||
1107 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) life, | |||
1108 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1109 | goto cleanup; | |||
1110 | life = 0; | |||
1111 | ||||
1112 | /* | |||
1113 | * Setup the soft limits, we use 90 % of the hard ones. | |||
1114 | * XXX A configurable ratio would be better. | |||
1115 | */ | |||
1116 | life = malloc(sizeof *life); | |||
1117 | if (!life) | |||
1118 | goto cleanup; | |||
1119 | life->sadb_lifetime_len = sizeof *life / PF_KEY_V2_CHUNK8; | |||
1120 | life->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT4; | |||
1121 | life->sadb_lifetime_allocations = 0; | |||
1122 | life->sadb_lifetime_bytes = sa->kilobytes * 1024 * 9 / 10; | |||
1123 | /* | |||
1124 | * XXX I am not sure which one is best in security respect. | |||
1125 | * Maybe the RFCs actually mandate what a lifetime really is. | |||
1126 | */ | |||
1127 | #if 0 | |||
1128 | life->sadb_lifetime_addtime = 0; | |||
1129 | life->sadb_lifetime_usetime = sa->seconds * 9 / 10; | |||
1130 | #else | |||
1131 | life->sadb_lifetime_addtime = sa->seconds * 9 / 10; | |||
1132 | life->sadb_lifetime_usetime = 0; | |||
1133 | #endif | |||
1134 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) life, | |||
1135 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1136 | goto cleanup; | |||
1137 | life = 0; | |||
1138 | } | |||
1139 | /* | |||
1140 | * Setup the ADDRESS extensions. | |||
1141 | */ | |||
1142 | if (incoming) | |||
1143 | sa->transport->vtbl->get_dst(sa->transport, &src); | |||
1144 | else | |||
1145 | sa->transport->vtbl->get_src(sa->transport, &src); | |||
1146 | len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(src))(((((src)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
1147 | addr = calloc(1, len); | |||
1148 | if (!addr) | |||
1149 | goto cleanup; | |||
1150 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC5; | |||
1151 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1152 | addr->sadb_address_reserved = 0; | |||
1153 | memcpy(addr + 1, src, SA_LEN(src)((src)->sa_len)); | |||
1154 | switch (((struct sockaddr *) (addr + 1))->sa_family) { | |||
1155 | case AF_INET2: | |||
1156 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
1157 | break; | |||
1158 | case AF_INET624: | |||
1159 | ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | |||
1160 | break; | |||
1161 | } | |||
1162 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | |||
1163 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1164 | goto cleanup; | |||
1165 | addr = 0; | |||
1166 | ||||
1167 | len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(dst))(((((dst)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
1168 | addr = calloc(1, len); | |||
1169 | if (!addr) | |||
1170 | goto cleanup; | |||
1171 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST6; | |||
1172 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1173 | addr->sadb_address_reserved = 0; | |||
1174 | memcpy(addr + 1, dst, SA_LEN(dst)((dst)->sa_len)); | |||
1175 | switch (((struct sockaddr *) (addr + 1))->sa_family) { | |||
1176 | case AF_INET2: | |||
1177 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
1178 | break; | |||
1179 | case AF_INET624: | |||
1180 | ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | |||
1181 | break; | |||
1182 | } | |||
1183 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | |||
1184 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1185 | goto cleanup; | |||
1186 | addr = 0; | |||
1187 | ||||
1188 | if (proto->proto != IPSEC_PROTO_IPCOMP4) { | |||
1189 | /* Setup the KEY extensions. */ | |||
1190 | if (hashlen) { | |||
1191 | len = sizeof *key + PF_KEY_V2_ROUND(hashlen)(((hashlen) + 8 - 1) & ~(8 - 1)); | |||
1192 | key = malloc(len); | |||
1193 | if (!key) | |||
1194 | goto cleanup; | |||
1195 | key->sadb_key_exttype = SADB_EXT_KEY_AUTH8; | |||
1196 | key->sadb_key_len = len / PF_KEY_V2_CHUNK8; | |||
1197 | key->sadb_key_bits = hashlen * 8; | |||
1198 | key->sadb_key_reserved = 0; | |||
1199 | memcpy(key + 1, | |||
1200 | iproto->keymat[incoming] + | |||
1201 | (proto->proto == | |||
1202 | IPSEC_PROTO_IPSEC_ESP3 ? keylen : 0), | |||
1203 | hashlen); | |||
1204 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) key, | |||
1205 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1206 | goto cleanup; | |||
1207 | key = 0; | |||
1208 | } | |||
1209 | if (keylen) { | |||
1210 | len = sizeof *key + PF_KEY_V2_ROUND(keylen)(((keylen) + 8 - 1) & ~(8 - 1)); | |||
1211 | key = malloc(len); | |||
1212 | if (!key) | |||
1213 | goto cleanup; | |||
1214 | key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT9; | |||
1215 | key->sadb_key_len = len / PF_KEY_V2_CHUNK8; | |||
1216 | key->sadb_key_bits = keylen * 8; | |||
1217 | key->sadb_key_reserved = 0; | |||
1218 | memcpy(key + 1, iproto->keymat[incoming], keylen); | |||
1219 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) key, | |||
1220 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1221 | goto cleanup; | |||
1222 | key = 0; | |||
1223 | } | |||
1224 | } | |||
1225 | /* Setup identity extensions. */ | |||
1226 | if (isakmp_sa->id_i) { | |||
1227 | pp = pf_key_v2_convert_id(isakmp_sa->id_i, isakmp_sa->id_i_len, | |||
1228 | &len, &idtype); | |||
1229 | if (!pp) | |||
1230 | goto nosid; | |||
1231 | ||||
1232 | sid = calloc(PF_KEY_V2_ROUND(len + 1)(((len + 1) + 8 - 1) & ~(8 - 1)) + sizeof *sid, | |||
1233 | sizeof(u_int8_t)); | |||
1234 | if (!sid) { | |||
1235 | free(pp); | |||
1236 | goto cleanup; | |||
1237 | } | |||
1238 | sid->sadb_ident_type = idtype; | |||
1239 | sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK8) + | |||
1240 | PF_KEY_V2_ROUND(len + 1)(((len + 1) + 8 - 1) & ~(8 - 1)) / PF_KEY_V2_CHUNK8; | |||
1241 | if ((isakmp_sa->initiator && !incoming) || | |||
1242 | (!isakmp_sa->initiator && incoming)) | |||
1243 | sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC10; | |||
1244 | else | |||
1245 | sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST11; | |||
1246 | ||||
1247 | memcpy(sid + 1, pp, len); | |||
1248 | free(pp); | |||
1249 | ||||
1250 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) sid, | |||
1251 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1252 | goto cleanup; | |||
1253 | sid = 0; | |||
1254 | ||||
1255 | nosid: | |||
1256 | free(sid); | |||
1257 | sid = 0; | |||
1258 | } | |||
1259 | if (isakmp_sa->id_r) { | |||
1260 | pp = pf_key_v2_convert_id(isakmp_sa->id_r, isakmp_sa->id_r_len, | |||
1261 | &len, &idtype); | |||
1262 | if (!pp) | |||
1263 | goto nodid; | |||
1264 | ||||
1265 | sid = calloc(PF_KEY_V2_ROUND(len + 1)(((len + 1) + 8 - 1) & ~(8 - 1)) + sizeof *sid, | |||
1266 | sizeof(u_int8_t)); | |||
1267 | if (!sid) { | |||
1268 | free(pp); | |||
1269 | goto cleanup; | |||
1270 | } | |||
1271 | sid->sadb_ident_type = idtype; | |||
1272 | sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK8) + | |||
1273 | PF_KEY_V2_ROUND(len + 1)(((len + 1) + 8 - 1) & ~(8 - 1)) / PF_KEY_V2_CHUNK8; | |||
1274 | if ((isakmp_sa->initiator && !incoming) || | |||
1275 | (!isakmp_sa->initiator && incoming)) | |||
1276 | sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST11; | |||
1277 | else | |||
1278 | sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC10; | |||
1279 | ||||
1280 | memcpy(sid + 1, pp, len); | |||
1281 | free(pp); | |||
1282 | ||||
1283 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) sid, | |||
1284 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1285 | goto cleanup; | |||
1286 | sid = 0; | |||
1287 | ||||
1288 | nodid: | |||
1289 | free(sid); | |||
1290 | sid = 0; | |||
1291 | } | |||
1292 | ||||
1293 | /* Setup the flow type extension. */ | |||
1294 | bzero(&flowtype, sizeof flowtype); | |||
1295 | flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE20; | |||
1296 | flowtype.sadb_protocol_len = sizeof flowtype / PF_KEY_V2_CHUNK8; | |||
1297 | flowtype.sadb_protocol_direction = incoming ? | |||
1298 | IPSP_DIRECTION_IN0x1 : IPSP_DIRECTION_OUT0x2; | |||
1299 | ||||
1300 | if (pf_key_v2_msg_add(update, (struct sadb_ext *)&flowtype, 0) == -1) | |||
1301 | goto cleanup; | |||
1302 | ||||
1303 | bzero(&tprotocol, sizeof tprotocol); | |||
1304 | tprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL19; | |||
1305 | tprotocol.sadb_protocol_len = sizeof tprotocol / PF_KEY_V2_CHUNK8; | |||
1306 | tprotocol.sadb_protocol_proto = isa->tproto; | |||
1307 | ||||
1308 | if (pf_key_v2_msg_add(update, (struct sadb_ext *)&tprotocol, | |||
1309 | 0) == -1) | |||
1310 | goto cleanup; | |||
1311 | ||||
1312 | len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(isa->src_net))(((((isa->src_net)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
1313 | addr = calloc(1, len); | |||
1314 | if (!addr) | |||
1315 | goto cleanup; | |||
1316 | addr->sadb_address_exttype = incoming ? | |||
1317 | SADB_X_EXT_DST_FLOW22 : SADB_X_EXT_SRC_FLOW21; | |||
1318 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1319 | addr->sadb_address_reserved = 0; | |||
1320 | pf_key_v2_setup_sockaddr(addr + 1, isa->src_net, 0, isa->sport, 0); | |||
1321 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | |||
1322 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1323 | goto cleanup; | |||
1324 | addr = 0; | |||
1325 | ||||
1326 | addr = calloc(1, len); | |||
1327 | if (!addr) | |||
1328 | goto cleanup; | |||
1329 | addr->sadb_address_exttype = | |||
1330 | incoming ? SADB_X_EXT_DST_MASK18 : SADB_X_EXT_SRC_MASK17; | |||
1331 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1332 | addr->sadb_address_reserved = 0; | |||
1333 | pf_key_v2_setup_sockaddr(addr + 1, isa->src_mask, 0, | |||
1334 | isa->sport ? 0xffff : 0, 0); | |||
1335 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | |||
1336 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1337 | goto cleanup; | |||
1338 | addr = 0; | |||
1339 | ||||
1340 | addr = calloc(1, len); | |||
1341 | if (!addr) | |||
1342 | goto cleanup; | |||
1343 | addr->sadb_address_exttype = incoming ? | |||
1344 | SADB_X_EXT_SRC_FLOW21 : SADB_X_EXT_DST_FLOW22; | |||
1345 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1346 | addr->sadb_address_reserved = 0; | |||
1347 | pf_key_v2_setup_sockaddr(addr + 1, isa->dst_net, 0, isa->dport, 0); | |||
1348 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | |||
1349 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1350 | goto cleanup; | |||
1351 | addr = 0; | |||
1352 | ||||
1353 | addr = calloc(1, len); | |||
1354 | if (!addr) | |||
1355 | goto cleanup; | |||
1356 | addr->sadb_address_exttype = | |||
1357 | incoming ? SADB_X_EXT_SRC_MASK17 : SADB_X_EXT_DST_MASK18; | |||
1358 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1359 | addr->sadb_address_reserved = 0; | |||
1360 | pf_key_v2_setup_sockaddr(addr + 1, isa->dst_mask, 0, | |||
1361 | isa->dport ? 0xffff : 0, 0); | |||
1362 | if (pf_key_v2_msg_add(update, (struct sadb_ext *) addr, | |||
1363 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1364 | goto cleanup; | |||
1365 | addr = 0; | |||
1366 | ||||
1367 | /* Add a pf tag to matching packets of this SA. */ | |||
1368 | if (sa->tag != NULL((void *)0)) { | |||
1369 | len = sizeof(*stag) + PF_KEY_V2_ROUND(strlen(sa->tag) + 1)(((strlen(sa->tag) + 1) + 8 - 1) & ~(8 - 1)); | |||
1370 | if ((stag = calloc(1, len)) == NULL((void *)0)) | |||
1371 | goto cleanup; | |||
1372 | stag->sadb_x_tag_exttype = SADB_X_EXT_TAG33; | |||
1373 | stag->sadb_x_tag_len = len / PF_KEY_V2_CHUNK8; | |||
1374 | stag->sadb_x_tag_taglen = strlen(sa->tag) + 1; | |||
1375 | s = (char *)(stag + 1); | |||
1376 | strlcpy(s, sa->tag, stag->sadb_x_tag_taglen); | |||
1377 | if (pf_key_v2_msg_add(update, (struct sadb_ext *)stag, | |||
1378 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1379 | goto cleanup; | |||
1380 | } | |||
1381 | ||||
1382 | if (sa->flags & SA_FLAG_IFACE0x400) { | |||
1383 | struct sadb_x_iface *siface; | |||
1384 | ||||
1385 | len = sizeof(*siface); | |||
1386 | siface = calloc(1, len); | |||
1387 | if (siface == NULL((void *)0)) | |||
1388 | goto cleanup; | |||
1389 | ||||
1390 | siface->sadb_x_iface_len = len / PF_KEY_V2_CHUNK8; | |||
1391 | siface->sadb_x_iface_exttype = SADB_X_EXT_IFACE40; | |||
1392 | siface->sadb_x_iface_unit = sa->iface; | |||
1393 | siface->sadb_x_iface_direction = incoming ? | |||
1394 | IPSP_DIRECTION_IN0x1 : IPSP_DIRECTION_OUT0x2; | |||
1395 | ||||
1396 | if (pf_key_v2_msg_add(update, (struct sadb_ext *)siface, | |||
1397 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1398 | goto cleanup; | |||
1399 | ||||
1400 | snprintf(iface_str, sizeof(iface_str), "iface %u", sa->iface); | |||
1401 | } | |||
1402 | ||||
1403 | /* XXX Here can sensitivity extensions be setup. */ | |||
1404 | ||||
1405 | if (sockaddr2text(dst, &addr_str, 0)) | |||
1406 | addr_str = 0; | |||
1407 | ||||
1408 | LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_set_spi: "log_debug (LOG_SYSDEP, 10, "pf_key_v2_set_spi: " "satype %d dst %s SPI 0x%x%s%s%s" , msg.sadb_msg_satype, addr_str ? addr_str : "unknown", (__uint32_t )(__builtin_constant_p(ssa.sadb_sa_spi) ? (__uint32_t)(((__uint32_t )(ssa.sadb_sa_spi) & 0xff) << 24 | ((__uint32_t)(ssa .sadb_sa_spi) & 0xff00) << 8 | ((__uint32_t)(ssa.sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa.sadb_sa_spi) & 0xff000000) >> 24) : __swap32md(ssa.sadb_sa_spi) ), sa->tag ? " tag " : "", sa->tag ? sa->tag : "", iface_str ) | |||
1409 | "satype %d dst %s SPI 0x%x%s%s%s", msg.sadb_msg_satype,log_debug (LOG_SYSDEP, 10, "pf_key_v2_set_spi: " "satype %d dst %s SPI 0x%x%s%s%s" , msg.sadb_msg_satype, addr_str ? addr_str : "unknown", (__uint32_t )(__builtin_constant_p(ssa.sadb_sa_spi) ? (__uint32_t)(((__uint32_t )(ssa.sadb_sa_spi) & 0xff) << 24 | ((__uint32_t)(ssa .sadb_sa_spi) & 0xff00) << 8 | ((__uint32_t)(ssa.sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa.sadb_sa_spi) & 0xff000000) >> 24) : __swap32md(ssa.sadb_sa_spi) ), sa->tag ? " tag " : "", sa->tag ? sa->tag : "", iface_str ) | |||
1410 | addr_str ? addr_str : "unknown",log_debug (LOG_SYSDEP, 10, "pf_key_v2_set_spi: " "satype %d dst %s SPI 0x%x%s%s%s" , msg.sadb_msg_satype, addr_str ? addr_str : "unknown", (__uint32_t )(__builtin_constant_p(ssa.sadb_sa_spi) ? (__uint32_t)(((__uint32_t )(ssa.sadb_sa_spi) & 0xff) << 24 | ((__uint32_t)(ssa .sadb_sa_spi) & 0xff00) << 8 | ((__uint32_t)(ssa.sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa.sadb_sa_spi) & 0xff000000) >> 24) : __swap32md(ssa.sadb_sa_spi) ), sa->tag ? " tag " : "", sa->tag ? sa->tag : "", iface_str ) | |||
1411 | ntohl(ssa.sadb_sa_spi), sa->tag ? " tag " : "",log_debug (LOG_SYSDEP, 10, "pf_key_v2_set_spi: " "satype %d dst %s SPI 0x%x%s%s%s" , msg.sadb_msg_satype, addr_str ? addr_str : "unknown", (__uint32_t )(__builtin_constant_p(ssa.sadb_sa_spi) ? (__uint32_t)(((__uint32_t )(ssa.sadb_sa_spi) & 0xff) << 24 | ((__uint32_t)(ssa .sadb_sa_spi) & 0xff00) << 8 | ((__uint32_t)(ssa.sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa.sadb_sa_spi) & 0xff000000) >> 24) : __swap32md(ssa.sadb_sa_spi) ), sa->tag ? " tag " : "", sa->tag ? sa->tag : "", iface_str ) | |||
1412 | sa->tag ? sa->tag : "", iface_str))log_debug (LOG_SYSDEP, 10, "pf_key_v2_set_spi: " "satype %d dst %s SPI 0x%x%s%s%s" , msg.sadb_msg_satype, addr_str ? addr_str : "unknown", (__uint32_t )(__builtin_constant_p(ssa.sadb_sa_spi) ? (__uint32_t)(((__uint32_t )(ssa.sadb_sa_spi) & 0xff) << 24 | ((__uint32_t)(ssa .sadb_sa_spi) & 0xff00) << 8 | ((__uint32_t)(ssa.sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa.sadb_sa_spi) & 0xff000000) >> 24) : __swap32md(ssa.sadb_sa_spi) ), sa->tag ? " tag " : "", sa->tag ? sa->tag : "", iface_str ); | |||
1413 | ||||
1414 | free(addr_str); | |||
1415 | ||||
1416 | /* | |||
1417 | * Although PF_KEY knows about expirations, it is unreliable per the | |||
1418 | * specs thus we need to do them inside isakmpd as well. | |||
1419 | */ | |||
1420 | if (sa->seconds) | |||
1421 | if (sa_setup_expirations(sa)) | |||
1422 | goto cleanup; | |||
1423 | ||||
1424 | ret = pf_key_v2_call(update); | |||
1425 | pf_key_v2_msg_free(update); | |||
1426 | update = 0; | |||
1427 | if (!ret) | |||
1428 | goto cleanup; | |||
1429 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
1430 | pf_key_v2_msg_free(ret); | |||
1431 | ret = 0; | |||
1432 | ||||
1433 | /* | |||
1434 | * If we are doing an addition into an SADB shared with our peer, | |||
1435 | * errors here are to be expected as the peer will already have | |||
1436 | * created the SA, and can thus be ignored. | |||
1437 | */ | |||
1438 | if (err && !(msg.sadb_msg_type == SADB_ADD3 && | |||
1439 | conf_get_str("General", "Shared-SADB"))) { | |||
1440 | log_print("pf_key_v2_set_spi: %s: %s", | |||
1441 | msg.sadb_msg_type == SADB_ADD3 ? "ADD" : "UPDATE", | |||
1442 | strerror(err)); | |||
1443 | goto cleanup; | |||
1444 | } | |||
1445 | LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_set_spi: done"))log_debug (LOG_SYSDEP, 50, "pf_key_v2_set_spi: done"); | |||
1446 | ||||
1447 | return 0; | |||
1448 | ||||
1449 | cleanup: | |||
1450 | free(sid); | |||
1451 | free(addr); | |||
1452 | free(life); | |||
1453 | free(key); | |||
1454 | if (update) | |||
1455 | pf_key_v2_msg_free(update); | |||
1456 | if (ret) | |||
1457 | pf_key_v2_msg_free(ret); | |||
1458 | return -1; | |||
1459 | } | |||
1460 | ||||
1461 | static __inline__ int | |||
1462 | pf_key_v2_mask_to_bits(u_int32_t mask) | |||
1463 | { | |||
1464 | u_int32_t hmask = ntohl(mask)(__uint32_t)(__builtin_constant_p(mask) ? (__uint32_t)(((__uint32_t )(mask) & 0xff) << 24 | ((__uint32_t)(mask) & 0xff00 ) << 8 | ((__uint32_t)(mask) & 0xff0000) >> 8 | ((__uint32_t)(mask) & 0xff000000) >> 24) : __swap32md (mask)); | |||
1465 | ||||
1466 | return (33 - ffs(~hmask + 1)) % 33; | |||
1467 | } | |||
1468 | ||||
1469 | static int | |||
1470 | pf_key_v2_mask6_to_bits(u_int8_t *mask) | |||
1471 | { | |||
1472 | int n; | |||
1473 | ||||
1474 | bit_ffc(mask, 128, &n)do { register bitstr_t *__name = (mask); register int __bit, __nbits = (128), __value = -1; for (__bit = 0; __bit < __nbits; ++ __bit) if (!((__name)[((__bit) >> 3)] & (1 << ((__bit)&0x7)))) { __value = __bit; break; } *(&n) = __value; } while(0); | |||
1475 | return n == -1 ? 128 : n; | |||
1476 | } | |||
1477 | ||||
1478 | /* | |||
1479 | * Enable/disable a flow. | |||
1480 | * XXX Assumes OpenBSD {ADD,DEL}FLOW extensions. | |||
1481 | */ | |||
1482 | static int | |||
1483 | pf_key_v2_flow(struct sockaddr *laddr, struct sockaddr *lmask, | |||
1484 | struct sockaddr *raddr, struct sockaddr *rmask, | |||
1485 | u_int8_t tproto, u_int16_t sport, u_int16_t dport, | |||
1486 | u_int8_t *spi, u_int8_t proto, struct sockaddr *dst, | |||
1487 | struct sockaddr *src, int delete, int ingress, | |||
1488 | u_int8_t srcid_type, u_int8_t *srcid, int srcid_len, | |||
1489 | u_int8_t dstid_type, u_int8_t *dstid, int dstid_len, | |||
1490 | struct ipsec_proto *iproto) | |||
1491 | { | |||
1492 | char *laddr_str, *lmask_str, *raddr_str, *rmask_str; | |||
1493 | ||||
1494 | struct sadb_msg msg; | |||
1495 | struct sadb_protocol flowtype; | |||
1496 | struct sadb_ident *sid = 0; | |||
1497 | struct sadb_address *addr = 0; | |||
1498 | struct sadb_protocol tprotocol; | |||
1499 | struct pf_key_v2_msg *flow = 0, *ret = 0; | |||
1500 | size_t len; | |||
1501 | int err; | |||
1502 | ||||
1503 | msg.sadb_msg_type = delete ? SADB_X_DELFLOW13 : SADB_X_ADDFLOW12; | |||
1504 | switch (proto) { | |||
1505 | case IPSEC_PROTO_IPSEC_ESP3: | |||
1506 | msg.sadb_msg_satype = SADB_SATYPE_ESP2; | |||
1507 | break; | |||
1508 | case IPSEC_PROTO_IPSEC_AH2: | |||
1509 | msg.sadb_msg_satype = SADB_SATYPE_AH1; | |||
1510 | break; | |||
1511 | case IPSEC_PROTO_IPCOMP4: | |||
1512 | msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9; | |||
1513 | break; | |||
1514 | default: | |||
1515 | log_print("pf_key_v2_flow: invalid proto %d", proto); | |||
1516 | goto cleanup; | |||
1517 | } | |||
1518 | msg.sadb_msg_seq = 0; | |||
1519 | flow = pf_key_v2_msg_new(&msg, 0); | |||
1520 | if (!flow) | |||
1521 | goto cleanup; | |||
1522 | ||||
1523 | if (!delete) { | |||
1524 | /* Setup the source ID, if provided. */ | |||
1525 | if (srcid) { | |||
1526 | sid = calloc( | |||
1527 | PF_KEY_V2_ROUND(srcid_len + 1)(((srcid_len + 1) + 8 - 1) & ~(8 - 1)) + sizeof *sid, | |||
1528 | sizeof(u_int8_t)); | |||
1529 | if (!sid) | |||
1530 | goto cleanup; | |||
1531 | ||||
1532 | sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK8) | |||
1533 | + PF_KEY_V2_ROUND(srcid_len + 1)(((srcid_len + 1) + 8 - 1) & ~(8 - 1)) / PF_KEY_V2_CHUNK8; | |||
1534 | sid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC10; | |||
1535 | sid->sadb_ident_type = srcid_type; | |||
1536 | ||||
1537 | memcpy(sid + 1, srcid, srcid_len); | |||
1538 | ||||
1539 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *) sid, | |||
1540 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1541 | goto cleanup; | |||
1542 | ||||
1543 | sid = 0; | |||
1544 | } | |||
1545 | /* Setup the destination ID, if provided. */ | |||
1546 | if (dstid) { | |||
1547 | sid = calloc( | |||
1548 | PF_KEY_V2_ROUND(dstid_len + 1)(((dstid_len + 1) + 8 - 1) & ~(8 - 1)) + sizeof *sid, | |||
1549 | sizeof(u_int8_t)); | |||
1550 | if (!sid) | |||
1551 | goto cleanup; | |||
1552 | ||||
1553 | sid->sadb_ident_len = ((sizeof *sid) / PF_KEY_V2_CHUNK8) | |||
1554 | + PF_KEY_V2_ROUND(dstid_len + 1)(((dstid_len + 1) + 8 - 1) & ~(8 - 1)) / PF_KEY_V2_CHUNK8; | |||
1555 | sid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST11; | |||
1556 | sid->sadb_ident_type = dstid_type; | |||
1557 | ||||
1558 | memcpy(sid + 1, dstid, dstid_len); | |||
1559 | ||||
1560 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *) sid, | |||
1561 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1562 | goto cleanup; | |||
1563 | ||||
1564 | sid = 0; | |||
1565 | } | |||
1566 | } | |||
1567 | /* Setup the flow type extension. */ | |||
1568 | bzero(&flowtype, sizeof flowtype); | |||
1569 | flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE20; | |||
1570 | flowtype.sadb_protocol_len = sizeof flowtype / PF_KEY_V2_CHUNK8; | |||
1571 | flowtype.sadb_protocol_direction = | |||
1572 | ingress ? IPSP_DIRECTION_IN0x1 : IPSP_DIRECTION_OUT0x2; | |||
1573 | flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_REQUIRE3; | |||
1574 | ||||
1575 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *)&flowtype, 0) == -1) | |||
1576 | goto cleanup; | |||
1577 | ||||
1578 | /* | |||
1579 | * Setup the ADDRESS extensions. | |||
1580 | */ | |||
1581 | len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(src))(((((src)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
1582 | if (!delete) | |||
1583 | { | |||
1584 | addr = calloc(1, len); | |||
1585 | if (!addr) | |||
1586 | goto cleanup; | |||
1587 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST6; | |||
1588 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1589 | addr->sadb_address_reserved = 0; | |||
1590 | pf_key_v2_setup_sockaddr(addr + 1, src, dst, 0, ingress); | |||
1591 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | |||
1592 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1593 | goto cleanup; | |||
1594 | addr = 0; | |||
1595 | } | |||
1596 | len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(laddr))(((((laddr)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
1597 | addr = calloc(1, len); | |||
1598 | if (!addr) | |||
1599 | goto cleanup; | |||
1600 | addr->sadb_address_exttype = SADB_X_EXT_SRC_FLOW21; | |||
1601 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1602 | addr->sadb_address_reserved = 0; | |||
1603 | pf_key_v2_setup_sockaddr(addr + 1, laddr, 0, sport, 0); | |||
1604 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | |||
1605 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1606 | goto cleanup; | |||
1607 | addr = 0; | |||
1608 | ||||
1609 | addr = calloc(1, len); | |||
1610 | if (!addr) | |||
1611 | goto cleanup; | |||
1612 | addr->sadb_address_exttype = SADB_X_EXT_SRC_MASK17; | |||
1613 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1614 | addr->sadb_address_reserved = 0; | |||
1615 | pf_key_v2_setup_sockaddr(addr + 1, lmask, 0, sport ? 0xffff : 0, 0); | |||
1616 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | |||
1617 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1618 | goto cleanup; | |||
1619 | addr = 0; | |||
1620 | ||||
1621 | addr = calloc(1, len); | |||
1622 | if (!addr) | |||
1623 | goto cleanup; | |||
1624 | addr->sadb_address_exttype = SADB_X_EXT_DST_FLOW22; | |||
1625 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1626 | addr->sadb_address_reserved = 0; | |||
1627 | pf_key_v2_setup_sockaddr(addr + 1, raddr, 0, dport, 0); | |||
1628 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | |||
1629 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1630 | goto cleanup; | |||
1631 | addr = 0; | |||
1632 | ||||
1633 | addr = calloc(1, len); | |||
1634 | if (!addr) | |||
1635 | goto cleanup; | |||
1636 | addr->sadb_address_exttype = SADB_X_EXT_DST_MASK18; | |||
1637 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
1638 | addr->sadb_address_reserved = 0; | |||
1639 | pf_key_v2_setup_sockaddr(addr + 1, rmask, 0, dport ? 0xffff : 0, 0); | |||
1640 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *) addr, | |||
1641 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
1642 | goto cleanup; | |||
1643 | addr = 0; | |||
1644 | ||||
1645 | /* Setup the protocol extension. */ | |||
1646 | bzero(&tprotocol, sizeof tprotocol); | |||
1647 | tprotocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL19; | |||
1648 | tprotocol.sadb_protocol_len = sizeof tprotocol / PF_KEY_V2_CHUNK8; | |||
1649 | tprotocol.sadb_protocol_proto = tproto; | |||
1650 | ||||
1651 | if (pf_key_v2_msg_add(flow, (struct sadb_ext *)&tprotocol, 0) == -1) | |||
1652 | goto cleanup; | |||
1653 | ||||
1654 | if (sockaddr2text(laddr, &laddr_str, 0)) | |||
1655 | laddr_str = 0; | |||
1656 | if (sockaddr2text(lmask, &lmask_str, 0)) | |||
1657 | lmask_str = 0; | |||
1658 | if (sockaddr2text(raddr, &raddr_str, 0)) | |||
1659 | raddr_str = 0; | |||
1660 | if (sockaddr2text(rmask, &rmask_str, 0)) | |||
1661 | rmask_str = 0; | |||
1662 | ||||
1663 | LOG_DBG((LOG_SYSDEP, 50,log_debug (LOG_SYSDEP, 50, "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u" , laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>", tproto, (__uint16_t)(__builtin_constant_p (sport) ? (__uint16_t)(((__uint16_t)(sport) & 0xffU) << 8 | ((__uint16_t)(sport) & 0xff00U) >> 8) : __swap16md (sport)), (__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t )(((__uint16_t)(dport) & 0xffU) << 8 | ((__uint16_t )(dport) & 0xff00U) >> 8) : __swap16md(dport))) | |||
1664 | "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u",log_debug (LOG_SYSDEP, 50, "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u" , laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>", tproto, (__uint16_t)(__builtin_constant_p (sport) ? (__uint16_t)(((__uint16_t)(sport) & 0xffU) << 8 | ((__uint16_t)(sport) & 0xff00U) >> 8) : __swap16md (sport)), (__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t )(((__uint16_t)(dport) & 0xffU) << 8 | ((__uint16_t )(dport) & 0xff00U) >> 8) : __swap16md(dport))) | |||
1665 | laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>",log_debug (LOG_SYSDEP, 50, "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u" , laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>", tproto, (__uint16_t)(__builtin_constant_p (sport) ? (__uint16_t)(((__uint16_t)(sport) & 0xffU) << 8 | ((__uint16_t)(sport) & 0xff00U) >> 8) : __swap16md (sport)), (__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t )(((__uint16_t)(dport) & 0xffU) << 8 | ((__uint16_t )(dport) & 0xff00U) >> 8) : __swap16md(dport))) | |||
1666 | raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>",log_debug (LOG_SYSDEP, 50, "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u" , laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>", tproto, (__uint16_t)(__builtin_constant_p (sport) ? (__uint16_t)(((__uint16_t)(sport) & 0xffU) << 8 | ((__uint16_t)(sport) & 0xff00U) >> 8) : __swap16md (sport)), (__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t )(((__uint16_t)(dport) & 0xffU) << 8 | ((__uint16_t )(dport) & 0xff00U) >> 8) : __swap16md(dport))) | |||
1667 | tproto, ntohs(sport), ntohs(dport)))log_debug (LOG_SYSDEP, 50, "pf_key_v2_flow: src %s %s dst %s %s proto %u sport %u dport %u" , laddr_str ? laddr_str : "<??\?>", lmask_str ? lmask_str : "<??\?>", raddr_str ? raddr_str : "<??\?>", rmask_str ? rmask_str : "<??\?>", tproto, (__uint16_t)(__builtin_constant_p (sport) ? (__uint16_t)(((__uint16_t)(sport) & 0xffU) << 8 | ((__uint16_t)(sport) & 0xff00U) >> 8) : __swap16md (sport)), (__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t )(((__uint16_t)(dport) & 0xffU) << 8 | ((__uint16_t )(dport) & 0xff00U) >> 8) : __swap16md(dport))); | |||
1668 | ||||
1669 | free(laddr_str); | |||
1670 | free(lmask_str); | |||
1671 | free(raddr_str); | |||
1672 | free(rmask_str); | |||
1673 | ||||
1674 | ret = pf_key_v2_call(flow); | |||
1675 | pf_key_v2_msg_free(flow); | |||
1676 | flow = 0; | |||
1677 | if (!ret) | |||
1678 | goto cleanup; | |||
1679 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
1680 | if (err) { | |||
1681 | if (err == ESRCH3) /* These are common and usually | |||
1682 | * harmless. */ | |||
1683 | LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_flow: %sFLOW: %s",log_debug (LOG_SYSDEP, 10, "pf_key_v2_flow: %sFLOW: %s", delete ? "DEL" : "ADD", strerror(err)) | |||
1684 | delete ? "DEL" : "ADD", strerror(err)))log_debug (LOG_SYSDEP, 10, "pf_key_v2_flow: %sFLOW: %s", delete ? "DEL" : "ADD", strerror(err)); | |||
1685 | else | |||
1686 | log_print("pf_key_v2_flow: %sFLOW: %s", | |||
1687 | delete ? "DEL" : "ADD", strerror(err)); | |||
1688 | goto cleanup; | |||
1689 | } | |||
1690 | pf_key_v2_msg_free(ret); | |||
1691 | ||||
1692 | LOG_DBG((LOG_MISC, 50, "pf_key_v2_flow: %sFLOW: done",log_debug (LOG_MISC, 50, "pf_key_v2_flow: %sFLOW: done", delete ? "DEL" : "ADD") | |||
1693 | delete ? "DEL" : "ADD"))log_debug (LOG_MISC, 50, "pf_key_v2_flow: %sFLOW: done", delete ? "DEL" : "ADD"); | |||
1694 | ||||
1695 | return 0; | |||
1696 | ||||
1697 | cleanup: | |||
1698 | free(sid); | |||
1699 | free(addr); | |||
1700 | if (flow) | |||
1701 | pf_key_v2_msg_free(flow); | |||
1702 | if (ret) | |||
1703 | pf_key_v2_msg_free(ret); | |||
1704 | return -1; | |||
1705 | } | |||
1706 | ||||
1707 | static u_int8_t * | |||
1708 | pf_key_v2_convert_id(u_int8_t *id, int idlen, size_t *reslen, int *idtype) | |||
1709 | { | |||
1710 | u_int8_t *addr, *res = 0; | |||
1711 | char addrbuf[ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" + 5]; | |||
1712 | ||||
1713 | switch (id[0]) { | |||
1714 | case IPSEC_ID_FQDN2: | |||
1715 | res = calloc(idlen - ISAKMP_ID_DATA_OFF8 + ISAKMP_GEN_SZ4, | |||
1716 | sizeof(u_int8_t)); | |||
1717 | if (!res) | |||
1718 | return 0; | |||
1719 | ||||
1720 | *reslen = idlen - ISAKMP_ID_DATA_OFF8 + ISAKMP_GEN_SZ4; | |||
1721 | memcpy(res, id + ISAKMP_ID_DATA_OFF8 - ISAKMP_GEN_SZ4, *reslen); | |||
1722 | *idtype = SADB_IDENTTYPE_FQDN2; | |||
1723 | LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: FQDN %.*s",log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: FQDN %.*s", (int) *reslen, res) | |||
1724 | (int) *reslen, res))log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: FQDN %.*s", (int) *reslen, res); | |||
1725 | return res; | |||
1726 | ||||
1727 | case IPSEC_ID_USER_FQDN3: | |||
1728 | res = calloc(idlen - ISAKMP_ID_DATA_OFF8 + ISAKMP_GEN_SZ4, | |||
1729 | sizeof(u_int8_t)); | |||
1730 | if (!res) | |||
1731 | return 0; | |||
1732 | ||||
1733 | *reslen = idlen - ISAKMP_ID_DATA_OFF8 + ISAKMP_GEN_SZ4; | |||
1734 | memcpy(res, id + ISAKMP_ID_DATA_OFF8 - ISAKMP_GEN_SZ4, *reslen); | |||
1735 | *idtype = SADB_IDENTTYPE_USERFQDN3; | |||
1736 | LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: UFQDN %.*s",log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: UFQDN %.*s" , (int) *reslen, res) | |||
1737 | (int) *reslen, res))log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: UFQDN %.*s" , (int) *reslen, res); | |||
1738 | return res; | |||
1739 | ||||
1740 | case IPSEC_ID_IPV4_ADDR1: | |||
1741 | if (inet_ntop(AF_INET2, id + ISAKMP_ID_DATA_OFF8 - ISAKMP_GEN_SZ4, | |||
1742 | addrbuf, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) | |||
1743 | return 0; | |||
1744 | *reslen = strlen(addrbuf) + 3; | |||
1745 | strlcat(addrbuf, "/32", ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" + 5); | |||
1746 | res = (u_int8_t *) strdup(addrbuf); | |||
1747 | if (!res) | |||
1748 | return 0; | |||
1749 | *idtype = SADB_IDENTTYPE_PREFIX1; | |||
1750 | LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: "log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: " "IPv4 address %s" , res) | |||
1751 | "IPv4 address %s", res))log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: " "IPv4 address %s" , res); | |||
1752 | return res; | |||
1753 | ||||
1754 | case IPSEC_ID_IPV6_ADDR5: | |||
1755 | if (inet_ntop(AF_INET624, | |||
1756 | id + ISAKMP_ID_DATA_OFF8 - ISAKMP_GEN_SZ4, | |||
1757 | addrbuf, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) | |||
1758 | return 0; | |||
1759 | *reslen = strlen(addrbuf) + 4; | |||
1760 | strlcat(addrbuf, "/128", ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" + 5); | |||
1761 | res = (u_int8_t *) strdup(addrbuf); | |||
1762 | if (!res) | |||
1763 | return 0; | |||
1764 | LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: "log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: " "IPv6 address %s" , res) | |||
1765 | "IPv6 address %s", res))log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: " "IPv6 address %s" , res); | |||
1766 | *idtype = SADB_IDENTTYPE_PREFIX1; | |||
1767 | return res; | |||
1768 | ||||
1769 | case IPSEC_ID_IPV4_ADDR_SUBNET4: /* XXX PREFIX */ | |||
1770 | addr = id + ISAKMP_ID_DATA_OFF8 - ISAKMP_GEN_SZ4; | |||
1771 | if (inet_ntop(AF_INET2, addr, addrbuf, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) | |||
1772 | return 0; | |||
1773 | snprintf(addrbuf + strlen(addrbuf), | |||
1774 | ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" - strlen(addrbuf), "/%d", | |||
1775 | pf_key_v2_mask_to_bits(*(u_int32_t *)(addr + | |||
1776 | sizeof(struct in_addr)))); | |||
1777 | *reslen = strlen(addrbuf); | |||
1778 | res = (u_int8_t *) strdup(addrbuf); | |||
1779 | if (!res) | |||
1780 | return 0; | |||
1781 | *idtype = SADB_IDENTTYPE_PREFIX1; | |||
1782 | LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: "log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: " "IPv4 subnet %s" , res) | |||
1783 | "IPv4 subnet %s", res))log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: " "IPv4 subnet %s" , res); | |||
1784 | return res; | |||
1785 | ||||
1786 | case IPSEC_ID_IPV6_ADDR_SUBNET6: /* XXX PREFIX */ | |||
1787 | addr = id + ISAKMP_ID_DATA_OFF8 - ISAKMP_GEN_SZ4; | |||
1788 | if (inet_ntop(AF_INET624, addr, addrbuf, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) | |||
1789 | return 0; | |||
1790 | snprintf(addrbuf + strlen(addrbuf), | |||
1791 | ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" - strlen(addrbuf), "/%d", | |||
1792 | pf_key_v2_mask6_to_bits(addr + | |||
1793 | sizeof(struct in6_addr))); | |||
1794 | *reslen = strlen(addrbuf); | |||
1795 | res = (u_int8_t *) strdup(addrbuf); | |||
1796 | if (!res) | |||
1797 | return 0; | |||
1798 | LOG_DBG((LOG_SYSDEP, 40, "pf_key_v2_convert_id: "log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: " "IPv6 subnet %s" , res) | |||
1799 | "IPv6 subnet %s", res))log_debug (LOG_SYSDEP, 40, "pf_key_v2_convert_id: " "IPv6 subnet %s" , res); | |||
1800 | *idtype = SADB_IDENTTYPE_PREFIX1; | |||
1801 | return res; | |||
1802 | ||||
1803 | case IPSEC_ID_IPV4_RANGE7: | |||
1804 | case IPSEC_ID_IPV6_RANGE8: | |||
1805 | case IPSEC_ID_DER_ASN1_DN9: | |||
1806 | case IPSEC_ID_DER_ASN1_GN10: | |||
1807 | case IPSEC_ID_KEY_ID11: | |||
1808 | /* XXX Not implemented yet. */ | |||
1809 | return 0; | |||
1810 | } | |||
1811 | ||||
1812 | return 0; | |||
1813 | } | |||
1814 | ||||
1815 | /* Enable a flow given an SA. */ | |||
1816 | int | |||
1817 | pf_key_v2_enable_sa(struct sa *sa, struct sa *isakmp_sa) | |||
1818 | { | |||
1819 | struct ipsec_sa *isa = sa->data; | |||
1820 | struct sockaddr *dst, *src; | |||
1821 | int error; | |||
1822 | struct proto *proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first); | |||
1823 | int sidtype = 0, didtype = 0; | |||
1824 | size_t sidlen = 0, didlen = 0; | |||
1825 | u_int8_t *sid = 0, *did = 0; | |||
1826 | ||||
1827 | if (proto == NULL((void *)0)) { | |||
1828 | log_print("pf_key_v2_enable_sa: no proto"); | |||
1829 | return EINVAL22; | |||
1830 | } | |||
1831 | ||||
1832 | sa->transport->vtbl->get_dst(sa->transport, &dst); | |||
1833 | sa->transport->vtbl->get_src(sa->transport, &src); | |||
1834 | ||||
1835 | if (isakmp_sa->id_i) { | |||
1836 | if (isakmp_sa->initiator) | |||
1837 | sid = pf_key_v2_convert_id(isakmp_sa->id_i, | |||
1838 | isakmp_sa->id_i_len, &sidlen, &sidtype); | |||
1839 | else | |||
1840 | did = pf_key_v2_convert_id(isakmp_sa->id_i, | |||
1841 | isakmp_sa->id_i_len, &didlen, &didtype); | |||
1842 | } | |||
1843 | if (isakmp_sa->id_r) { | |||
1844 | if (isakmp_sa->initiator) | |||
1845 | did = pf_key_v2_convert_id(isakmp_sa->id_r, | |||
1846 | isakmp_sa->id_r_len, &didlen, &didtype); | |||
1847 | else | |||
1848 | sid = pf_key_v2_convert_id(isakmp_sa->id_r, | |||
1849 | isakmp_sa->id_r_len, &sidlen, &sidtype); | |||
1850 | } | |||
1851 | ||||
1852 | error = pf_key_v2_flow(isa->src_net, isa->src_mask, isa->dst_net, | |||
1853 | isa->dst_mask, isa->tproto, isa->sport, isa->dport, proto->spi[0], | |||
1854 | proto->proto, dst, src, 0, 0, sidtype, sid, sidlen, didtype, did, | |||
1855 | didlen, proto->data); | |||
1856 | if (error) | |||
1857 | goto cleanup; | |||
1858 | ||||
1859 | error = pf_key_v2_flow(isa->dst_net, isa->dst_mask, isa->src_net, | |||
1860 | isa->src_mask, isa->tproto, isa->dport, isa->sport, proto->spi[1], | |||
1861 | proto->proto, src, dst, 0, 1, sidtype, sid, sidlen, didtype, did, | |||
1862 | didlen, proto->data); | |||
1863 | ||||
1864 | cleanup: | |||
1865 | free(sid); | |||
1866 | free(did); | |||
1867 | ||||
1868 | return error; | |||
1869 | } | |||
1870 | ||||
1871 | /* Increase reference count of refcounted sections. */ | |||
1872 | static int | |||
1873 | pf_key_v2_conf_refinc(int af, char *section) | |||
1874 | { | |||
1875 | char conn[22]; | |||
1876 | int num; | |||
1877 | ||||
1878 | if (!section) | |||
1879 | return 0; | |||
1880 | ||||
1881 | num = conf_get_num(section, "Refcount", 0); | |||
1882 | if (num == 0) | |||
1883 | return 0; | |||
1884 | ||||
1885 | snprintf(conn, sizeof conn, "%d", num + 1); | |||
1886 | conf_set(af, section, "Refcount", conn, 1, 0); | |||
1887 | return 0; | |||
1888 | } | |||
1889 | ||||
1890 | /* | |||
1891 | * Return 0 if the section didn't exist or was removed, non-zero otherwise. | |||
1892 | * Don't touch non-refcounted (statically defined) sections. | |||
1893 | */ | |||
1894 | static int | |||
1895 | pf_key_v2_conf_refhandle(int af, char *section) | |||
1896 | { | |||
1897 | char conn[22]; | |||
1898 | int num; | |||
1899 | ||||
1900 | if (!section) | |||
1901 | return 0; | |||
1902 | ||||
1903 | num = conf_get_num(section, "Refcount", 0); | |||
1904 | if (num == 1) { | |||
1905 | conf_remove_section(af, section); | |||
1906 | num--; | |||
1907 | } else if (num != 0) { | |||
1908 | snprintf(conn, sizeof conn, "%d", num - 1); | |||
1909 | conf_set(af, section, "Refcount", conn, 1, 0); | |||
1910 | } | |||
1911 | return num; | |||
1912 | } | |||
1913 | ||||
1914 | /* Remove all dynamically-established configuration entries. */ | |||
1915 | static int | |||
1916 | pf_key_v2_remove_conf(char *section) | |||
1917 | { | |||
1918 | char *ikepeer, *localid, *remoteid, *configname; | |||
1919 | struct conf_list_node *attr; | |||
1920 | struct conf_list *attrs; | |||
1921 | int af; | |||
1922 | ||||
1923 | if (!section) | |||
1924 | return 0; | |||
1925 | ||||
1926 | if (!conf_get_str(section, "Phase")) | |||
1927 | return 0; | |||
1928 | ||||
1929 | /* Only remove dynamically-established entries. */ | |||
1930 | attrs = conf_get_list(section, "Flags"); | |||
1931 | if (attrs) { | |||
1932 | for (attr = TAILQ_FIRST(&attrs->fields)((&attrs->fields)->tqh_first); attr; | |||
1933 | attr = TAILQ_NEXT(attr, link)((attr)->link.tqe_next)) | |||
1934 | if (!strcasecmp(attr->field, "__ondemand")) | |||
1935 | goto passed; | |||
1936 | ||||
1937 | conf_free_list(attrs); | |||
1938 | } | |||
1939 | return 0; | |||
1940 | ||||
1941 | passed: | |||
1942 | conf_free_list(attrs); | |||
1943 | ||||
1944 | af = conf_begin(); | |||
1945 | ||||
1946 | configname = conf_get_str(section, "Configuration"); | |||
1947 | pf_key_v2_conf_refhandle(af, configname); | |||
1948 | ||||
1949 | /* These are the Phase 2 Local/Remote IDs. */ | |||
1950 | localid = conf_get_str(section, "Local-ID"); | |||
1951 | pf_key_v2_conf_refhandle(af, localid); | |||
1952 | ||||
1953 | remoteid = conf_get_str(section, "Remote-ID"); | |||
1954 | pf_key_v2_conf_refhandle(af, remoteid); | |||
1955 | ||||
1956 | ikepeer = conf_get_str(section, "ISAKMP-peer"); | |||
1957 | ||||
1958 | pf_key_v2_conf_refhandle(af, section); | |||
1959 | ||||
1960 | if (ikepeer) { | |||
1961 | remoteid = conf_get_str(ikepeer, "Remote-ID"); | |||
1962 | localid = conf_get_str(ikepeer, "ID"); | |||
1963 | configname = conf_get_str(ikepeer, "Configuration"); | |||
1964 | ||||
1965 | pf_key_v2_conf_refhandle(af, ikepeer); | |||
1966 | pf_key_v2_conf_refhandle(af, configname); | |||
1967 | ||||
1968 | /* Phase 1 IDs */ | |||
1969 | pf_key_v2_conf_refhandle(af, localid); | |||
1970 | pf_key_v2_conf_refhandle(af, remoteid); | |||
1971 | } | |||
1972 | conf_end(af, 1); | |||
1973 | return 0; | |||
1974 | } | |||
1975 | ||||
1976 | /* Disable a flow given a SA. */ | |||
1977 | int | |||
1978 | pf_key_v2_disable_sa(struct sa *sa, int incoming) | |||
1979 | { | |||
1980 | struct ipsec_sa *isa = sa->data; | |||
1981 | struct sockaddr *dst, *src; | |||
1982 | struct proto *proto = TAILQ_FIRST(&sa->protos)((&sa->protos)->tqh_first); | |||
1983 | ||||
1984 | sa->transport->vtbl->get_dst(sa->transport, &dst); | |||
1985 | sa->transport->vtbl->get_src(sa->transport, &src); | |||
1986 | ||||
1987 | if (!incoming) | |||
1988 | return pf_key_v2_flow(isa->src_net, isa->src_mask, | |||
1989 | isa->dst_net, isa->dst_mask, isa->tproto, isa->sport, | |||
1990 | isa->dport, proto->spi[0], proto->proto, src, dst, 1, 0, | |||
1991 | 0, 0, 0, 0, 0, 0, proto->data); | |||
1992 | else { | |||
1993 | return pf_key_v2_flow(isa->dst_net, isa->dst_mask, | |||
1994 | isa->src_net, isa->src_mask, isa->tproto, isa->dport, | |||
1995 | isa->sport, proto->spi[1], proto->proto, src, dst, 1, 1, | |||
1996 | 0, 0, 0, 0, 0, 0, proto->data); | |||
1997 | } | |||
1998 | } | |||
1999 | ||||
2000 | /* | |||
2001 | * Delete the IPsec SA represented by the INCOMING direction in protocol PROTO | |||
2002 | * of the IKE security association SA. Also delete potential flows tied to it. | |||
2003 | */ | |||
2004 | int | |||
2005 | pf_key_v2_delete_spi(struct sa *sa, struct proto *proto, int incoming) | |||
2006 | { | |||
2007 | struct sadb_msg msg; | |||
2008 | struct sadb_sa ssa; | |||
2009 | struct sadb_address *addr = 0; | |||
2010 | struct sockaddr *saddr; | |||
2011 | int len, err; | |||
2012 | struct pf_key_v2_msg *delete = 0, *ret = 0; | |||
2013 | ||||
2014 | /* If it's not an established SA, don't proceed. */ | |||
2015 | if (!(sa->flags & SA_FLAG_READY0x01)) | |||
2016 | return 0; | |||
2017 | ||||
2018 | if (sa->name && !(sa->flags & SA_FLAG_REPLACED0x08)) { | |||
2019 | LOG_DBG((LOG_SYSDEP, 50,log_debug (LOG_SYSDEP, 50, "pf_key_v2_delete_spi: removing configuration %s" , sa->name) | |||
2020 | "pf_key_v2_delete_spi: removing configuration %s",log_debug (LOG_SYSDEP, 50, "pf_key_v2_delete_spi: removing configuration %s" , sa->name) | |||
2021 | sa->name))log_debug (LOG_SYSDEP, 50, "pf_key_v2_delete_spi: removing configuration %s" , sa->name); | |||
2022 | pf_key_v2_remove_conf(sa->name); | |||
2023 | } | |||
2024 | msg.sadb_msg_type = SADB_DELETE4; | |||
2025 | switch (proto->proto) { | |||
2026 | case IPSEC_PROTO_IPSEC_ESP3: | |||
2027 | msg.sadb_msg_satype = SADB_SATYPE_ESP2; | |||
2028 | break; | |||
2029 | case IPSEC_PROTO_IPSEC_AH2: | |||
2030 | msg.sadb_msg_satype = SADB_SATYPE_AH1; | |||
2031 | break; | |||
2032 | case IPSEC_PROTO_IPCOMP4: | |||
2033 | msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9; | |||
2034 | break; | |||
2035 | default: | |||
2036 | log_print("pf_key_v2_delete_spi: invalid proto %d", | |||
2037 | proto->proto); | |||
2038 | goto cleanup; | |||
2039 | } | |||
2040 | msg.sadb_msg_seq = 0; | |||
2041 | delete = pf_key_v2_msg_new(&msg, 0); | |||
2042 | if (!delete) | |||
2043 | goto cleanup; | |||
2044 | ||||
2045 | /* Setup the SA extension. */ | |||
2046 | ssa.sadb_sa_exttype = SADB_EXT_SA1; | |||
2047 | ssa.sadb_sa_len = sizeof ssa / PF_KEY_V2_CHUNK8; | |||
2048 | memcpy(&ssa.sadb_sa_spi, proto->spi[incoming], sizeof ssa.sadb_sa_spi); | |||
2049 | ssa.sadb_sa_replay = 0; | |||
2050 | ssa.sadb_sa_state = 0; | |||
2051 | ssa.sadb_sa_auth = 0; | |||
2052 | ssa.sadb_sa_encrypt = 0; | |||
2053 | ssa.sadb_sa_flags = 0; | |||
2054 | if (pf_key_v2_msg_add(delete, (struct sadb_ext *)&ssa, 0) == -1) | |||
2055 | goto cleanup; | |||
2056 | ||||
2057 | /* | |||
2058 | * Setup the ADDRESS extensions. | |||
2059 | */ | |||
2060 | if (incoming) | |||
2061 | sa->transport->vtbl->get_dst(sa->transport, &saddr); | |||
2062 | else | |||
2063 | sa->transport->vtbl->get_src(sa->transport, &saddr); | |||
2064 | len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(saddr))(((((saddr)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
2065 | addr = calloc(1, len); | |||
2066 | if (!addr) | |||
2067 | goto cleanup; | |||
2068 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC5; | |||
2069 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
2070 | addr->sadb_address_reserved = 0; | |||
2071 | memcpy(addr + 1, saddr, SA_LEN(saddr)((saddr)->sa_len)); | |||
2072 | switch (saddr->sa_family) { | |||
2073 | case AF_INET2: | |||
2074 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
2075 | break; | |||
2076 | case AF_INET624: | |||
2077 | ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | |||
2078 | break; | |||
2079 | } | |||
2080 | if (pf_key_v2_msg_add(delete, (struct sadb_ext *) addr, | |||
2081 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
2082 | goto cleanup; | |||
2083 | addr = 0; | |||
2084 | ||||
2085 | if (incoming) | |||
2086 | sa->transport->vtbl->get_src(sa->transport, &saddr); | |||
2087 | else | |||
2088 | sa->transport->vtbl->get_dst(sa->transport, &saddr); | |||
2089 | len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(saddr))(((((saddr)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
2090 | addr = calloc(1, len); | |||
2091 | if (!addr) | |||
2092 | goto cleanup; | |||
2093 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST6; | |||
2094 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
2095 | addr->sadb_address_reserved = 0; | |||
2096 | memcpy(addr + 1, saddr, SA_LEN(saddr)((saddr)->sa_len)); | |||
2097 | switch (saddr->sa_family) { | |||
2098 | case AF_INET2: | |||
2099 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
2100 | break; | |||
2101 | case AF_INET624: | |||
2102 | ((struct sockaddr_in6 *) (addr + 1))->sin6_port = 0; | |||
2103 | break; | |||
2104 | } | |||
2105 | if (pf_key_v2_msg_add(delete, (struct sadb_ext *) addr, | |||
2106 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
2107 | goto cleanup; | |||
2108 | addr = 0; | |||
2109 | ||||
2110 | ret = pf_key_v2_call(delete); | |||
2111 | pf_key_v2_msg_free(delete); | |||
2112 | delete = 0; | |||
2113 | if (!ret) | |||
2114 | goto cleanup; | |||
2115 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
2116 | if (err) { | |||
2117 | LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_delete_spi: DELETE: %s",log_debug (LOG_SYSDEP, 10, "pf_key_v2_delete_spi: DELETE: %s" , strerror(err)) | |||
2118 | strerror(err)))log_debug (LOG_SYSDEP, 10, "pf_key_v2_delete_spi: DELETE: %s" , strerror(err)); | |||
2119 | goto cleanup; | |||
2120 | } | |||
2121 | pf_key_v2_msg_free(ret); | |||
2122 | ||||
2123 | LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_delete_spi: done"))log_debug (LOG_SYSDEP, 50, "pf_key_v2_delete_spi: done"); | |||
2124 | ||||
2125 | return 0; | |||
2126 | ||||
2127 | cleanup: | |||
2128 | free(addr); | |||
2129 | if (delete) | |||
2130 | pf_key_v2_msg_free(delete); | |||
2131 | if (ret) | |||
2132 | pf_key_v2_msg_free(ret); | |||
2133 | return -1; | |||
2134 | } | |||
2135 | ||||
2136 | static void | |||
2137 | pf_key_v2_stayalive(struct exchange *exchange, void *vconn, int fail) | |||
2138 | { | |||
2139 | char *conn = vconn; | |||
2140 | struct sa *sa; | |||
2141 | ||||
2142 | /* XXX What if it is phase 1 ? */ | |||
2143 | sa = sa_lookup_by_name(conn, 2); | |||
2144 | if (sa) | |||
2145 | sa->flags |= SA_FLAG_STAYALIVE0x02; | |||
2146 | ||||
2147 | /* | |||
2148 | * Remove failed configuration entry -- call twice because it is | |||
2149 | * created with a Refcount of 2. | |||
2150 | */ | |||
2151 | if (fail && (!exchange || exchange->name)) { | |||
2152 | pf_key_v2_remove_conf(conn); | |||
2153 | pf_key_v2_remove_conf(conn); | |||
2154 | } | |||
2155 | free(conn); | |||
2156 | } | |||
2157 | ||||
2158 | /* Check if a connection CONN exists, otherwise establish it. */ | |||
2159 | void | |||
2160 | pf_key_v2_connection_check(char *conn) | |||
2161 | { | |||
2162 | if (!sa_lookup_by_name(conn, 2)) { | |||
2163 | LOG_DBG((LOG_SYSDEP, 70,log_debug (LOG_SYSDEP, 70, "pf_key_v2_connection_check: SA for %s missing" , conn) | |||
2164 | "pf_key_v2_connection_check: SA for %s missing", conn))log_debug (LOG_SYSDEP, 70, "pf_key_v2_connection_check: SA for %s missing" , conn); | |||
2165 | exchange_establish(conn, pf_key_v2_stayalive, conn, 0); | |||
2166 | } else { | |||
2167 | LOG_DBG((LOG_SYSDEP, 70, "pf_key_v2_connection_check: "log_debug (LOG_SYSDEP, 70, "pf_key_v2_connection_check: " "SA for %s exists" , conn) | |||
2168 | "SA for %s exists", conn))log_debug (LOG_SYSDEP, 70, "pf_key_v2_connection_check: " "SA for %s exists" , conn); | |||
2169 | free(conn); | |||
2170 | } | |||
2171 | } | |||
2172 | ||||
2173 | /* Handle a PF_KEY lifetime expiration message PMSG. */ | |||
2174 | static void | |||
2175 | pf_key_v2_expire(struct pf_key_v2_msg *pmsg) | |||
2176 | { | |||
2177 | struct sadb_msg *msg; | |||
2178 | struct sadb_sa *ssa; | |||
2179 | struct sadb_address *dst; | |||
2180 | struct sockaddr *dstaddr; | |||
2181 | struct sadb_lifetime *life, *lifecurrent; | |||
2182 | struct sa *sa; | |||
2183 | struct pf_key_v2_node *lifenode, *ext; | |||
2184 | char *dst_str; | |||
2185 | ||||
2186 | msg = (struct sadb_msg *)TAILQ_FIRST(pmsg)((pmsg)->tqh_first)->seg; | |||
2187 | ext = pf_key_v2_find_ext(pmsg, SADB_EXT_SA1); | |||
2188 | if (!ext) { | |||
2189 | log_print("pf_key_v2_expire: no SA extension found"); | |||
2190 | return; | |||
2191 | } | |||
2192 | ssa = ext->seg; | |||
2193 | ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_DST6); | |||
2194 | if (!ext) { | |||
2195 | log_print("pf_key_v2_expire: " | |||
2196 | "no destination address extension found"); | |||
2197 | return; | |||
2198 | } | |||
2199 | dst = ext->seg; | |||
2200 | dstaddr = (struct sockaddr *) (dst + 1); | |||
2201 | lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_HARD3); | |||
2202 | if (!lifenode) | |||
2203 | lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_SOFT4); | |||
2204 | if (!lifenode) { | |||
2205 | log_print("pf_key_v2_expire: no lifetime extension found"); | |||
2206 | return; | |||
2207 | } | |||
2208 | life = lifenode->seg; | |||
2209 | ||||
2210 | lifenode = pf_key_v2_find_ext(pmsg, SADB_EXT_LIFETIME_CURRENT2); | |||
2211 | if (!lifenode) { | |||
2212 | log_print("pf_key_v2_expire: " | |||
2213 | "no current lifetime extension found"); | |||
2214 | return; | |||
2215 | } | |||
2216 | lifecurrent = lifenode->seg; | |||
2217 | ||||
2218 | if (sockaddr2text(dstaddr, &dst_str, 0)) | |||
2219 | dst_str = 0; | |||
2220 | ||||
2221 | LOG_DBG((LOG_SYSDEP, 20, "pf_key_v2_expire: "log_debug (LOG_SYSDEP, 20, "pf_key_v2_expire: " "%s dst %s SPI %x sproto %d" , life->sadb_lifetime_exttype == 4 ? "SOFT" : "HARD", dst_str ? dst_str : "<unknown>", (__uint32_t)(__builtin_constant_p (ssa->sadb_sa_spi) ? (__uint32_t)(((__uint32_t)(ssa->sadb_sa_spi ) & 0xff) << 24 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff00) << 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff000000) >> 24) : __swap32md(ssa->sadb_sa_spi )), msg->sadb_msg_satype) | |||
2222 | "%s dst %s SPI %x sproto %d",log_debug (LOG_SYSDEP, 20, "pf_key_v2_expire: " "%s dst %s SPI %x sproto %d" , life->sadb_lifetime_exttype == 4 ? "SOFT" : "HARD", dst_str ? dst_str : "<unknown>", (__uint32_t)(__builtin_constant_p (ssa->sadb_sa_spi) ? (__uint32_t)(((__uint32_t)(ssa->sadb_sa_spi ) & 0xff) << 24 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff00) << 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff000000) >> 24) : __swap32md(ssa->sadb_sa_spi )), msg->sadb_msg_satype) | |||
2223 | life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT ? "SOFT"log_debug (LOG_SYSDEP, 20, "pf_key_v2_expire: " "%s dst %s SPI %x sproto %d" , life->sadb_lifetime_exttype == 4 ? "SOFT" : "HARD", dst_str ? dst_str : "<unknown>", (__uint32_t)(__builtin_constant_p (ssa->sadb_sa_spi) ? (__uint32_t)(((__uint32_t)(ssa->sadb_sa_spi ) & 0xff) << 24 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff00) << 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff000000) >> 24) : __swap32md(ssa->sadb_sa_spi )), msg->sadb_msg_satype) | |||
2224 | : "HARD", dst_str ? dst_str : "<unknown>",log_debug (LOG_SYSDEP, 20, "pf_key_v2_expire: " "%s dst %s SPI %x sproto %d" , life->sadb_lifetime_exttype == 4 ? "SOFT" : "HARD", dst_str ? dst_str : "<unknown>", (__uint32_t)(__builtin_constant_p (ssa->sadb_sa_spi) ? (__uint32_t)(((__uint32_t)(ssa->sadb_sa_spi ) & 0xff) << 24 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff00) << 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff000000) >> 24) : __swap32md(ssa->sadb_sa_spi )), msg->sadb_msg_satype) | |||
2225 | ntohl(ssa->sadb_sa_spi), msg->sadb_msg_satype))log_debug (LOG_SYSDEP, 20, "pf_key_v2_expire: " "%s dst %s SPI %x sproto %d" , life->sadb_lifetime_exttype == 4 ? "SOFT" : "HARD", dst_str ? dst_str : "<unknown>", (__uint32_t)(__builtin_constant_p (ssa->sadb_sa_spi) ? (__uint32_t)(((__uint32_t)(ssa->sadb_sa_spi ) & 0xff) << 24 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff00) << 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff0000) >> 8 | ((__uint32_t)(ssa->sadb_sa_spi ) & 0xff000000) >> 24) : __swap32md(ssa->sadb_sa_spi )), msg->sadb_msg_satype); | |||
2226 | ||||
2227 | free(dst_str); | |||
2228 | ||||
2229 | /* | |||
2230 | * Find the IPsec SA. The IPsec stack has two SAs for every IKE SA, | |||
2231 | * one outgoing and one incoming, we regard expirations for any of | |||
2232 | * them as an expiration of the full IKE SA. Likewise, in | |||
2233 | * protection suites consisting of more than one protocol, any | |||
2234 | * expired individual IPsec stack SA will be seen as an expiration | |||
2235 | * of the full suite. | |||
2236 | */ | |||
2237 | switch (msg->sadb_msg_satype) { | |||
2238 | case SADB_SATYPE_ESP2: | |||
2239 | sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, | |||
2240 | IPSEC_PROTO_IPSEC_ESP3); | |||
2241 | break; | |||
2242 | ||||
2243 | case SADB_SATYPE_AH1: | |||
2244 | sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, | |||
2245 | IPSEC_PROTO_IPSEC_AH2); | |||
2246 | break; | |||
2247 | ||||
2248 | case SADB_X_SATYPE_IPCOMP9: | |||
2249 | sa = ipsec_sa_lookup(dstaddr, ssa->sadb_sa_spi, | |||
2250 | IPSEC_PROTO_IPCOMP4); | |||
2251 | break; | |||
2252 | ||||
2253 | default: | |||
2254 | /* XXX Log? */ | |||
2255 | sa = 0; | |||
2256 | break; | |||
2257 | } | |||
2258 | ||||
2259 | /* If the SA is already gone, don't do anything. */ | |||
2260 | if (!sa) | |||
2261 | return; | |||
2262 | ||||
2263 | /* | |||
2264 | * If we got a notification, try to renegotiate the SA -- unless of | |||
2265 | * course it has already been replaced by another. | |||
2266 | * Also, ignore SAs that were not dynamically established, or that | |||
2267 | * did not see any use. | |||
2268 | */ | |||
2269 | if (!(sa->flags & SA_FLAG_REPLACED0x08) && | |||
2270 | (sa->flags & SA_FLAG_ONDEMAND0x04) && | |||
2271 | lifecurrent->sadb_lifetime_bytes) | |||
2272 | exchange_establish(sa->name, 0, 0, 0); | |||
2273 | ||||
2274 | if (life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_HARD3) { | |||
2275 | /* Remove the old SA, it isn't useful anymore. */ | |||
2276 | sa_free(sa); | |||
2277 | } | |||
2278 | } | |||
2279 | ||||
2280 | static int | |||
2281 | mask4len(const struct sockaddr_in *mask) | |||
2282 | { | |||
2283 | int len; | |||
2284 | u_int32_t m; | |||
2285 | ||||
2286 | len = 0; | |||
2287 | for (m = 0x80000000; m & ntohl(mask->sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(mask->sin_addr.s_addr) ? (__uint32_t)(((__uint32_t)(mask->sin_addr.s_addr) & 0xff ) << 24 | ((__uint32_t)(mask->sin_addr.s_addr) & 0xff00) << 8 | ((__uint32_t)(mask->sin_addr.s_addr) & 0xff0000) >> 8 | ((__uint32_t)(mask->sin_addr .s_addr) & 0xff000000) >> 24) : __swap32md(mask-> sin_addr.s_addr)); m >>= 1) | |||
2288 | len++; | |||
2289 | if (len == 32) | |||
2290 | len = -1; | |||
2291 | return len; | |||
2292 | } | |||
2293 | ||||
2294 | #ifndef s6_addr8__u6_addr.__u6_addr8 | |||
2295 | #define s6_addr8__u6_addr.__u6_addr8 __u6_addr.__u6_addr8 | |||
2296 | #endif | |||
2297 | ||||
2298 | static int | |||
2299 | mask6len(const struct sockaddr_in6 *mask) | |||
2300 | { | |||
2301 | int i, len; | |||
2302 | u_int8_t m; | |||
2303 | ||||
2304 | len = 0; | |||
2305 | for (i = 0, m = 0; i < 16 && !m; i++) | |||
2306 | for (m = 0x80; m & mask->sin6_addr.s6_addr8__u6_addr.__u6_addr8[i]; m >>= 1) | |||
2307 | len++; | |||
2308 | if (len == 128) | |||
2309 | len = -1; | |||
2310 | return len; | |||
2311 | } | |||
2312 | ||||
2313 | static int | |||
2314 | phase2id(char *str, size_t size, const char *side, const char *sflow, | |||
2315 | int masklen, u_int8_t proto, u_int16_t port) | |||
2316 | { | |||
2317 | char smasklen[10], sproto[10], sport[10]; | |||
2318 | ||||
2319 | smasklen[0] = sproto[0] = sport[0] = 0; | |||
2320 | if (masklen != -1) | |||
2321 | snprintf(smasklen, sizeof smasklen, "/%d", masklen); | |||
2322 | if (proto) | |||
2323 | snprintf(sproto, sizeof sproto, "=%u", proto); | |||
2324 | if (port) | |||
2325 | snprintf(sport, sizeof sport, ":%u", ntohs(port)(__uint16_t)(__builtin_constant_p(port) ? (__uint16_t)(((__uint16_t )(port) & 0xffU) << 8 | ((__uint16_t)(port) & 0xff00U ) >> 8) : __swap16md(port))); | |||
2326 | ||||
2327 | return snprintf(str, size, "%s-%s%s%s%s", side, sflow, smasklen, | |||
2328 | sproto, sport); | |||
2329 | } | |||
2330 | ||||
2331 | /* Handle a PF_KEY SA ACQUIRE message PMSG. */ | |||
2332 | static void | |||
2333 | pf_key_v2_acquire(struct pf_key_v2_msg *pmsg) | |||
2334 | { | |||
2335 | struct sadb_msg *msg, askpolicy_msg; | |||
2336 | struct pf_key_v2_msg *askpolicy = 0, *ret = 0; | |||
2337 | struct sadb_x_policy policy; | |||
2338 | struct sadb_address *dst = 0, *src = 0; | |||
2339 | struct sockaddr *dstaddr, *srcaddr = 0; | |||
2340 | struct sadb_ident *srcident = 0, *dstident = 0; | |||
2341 | char dstbuf[ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], srcbuf[ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *peer = 0; | |||
2342 | char confname[120], *conn = 0; | |||
2343 | char *srcid = 0, *dstid = 0, *prefstring = 0; | |||
2344 | int slen, af, afamily, masklen; | |||
2345 | struct sockaddr *smask, *sflow, *dmask, *dflow; | |||
2346 | struct sadb_protocol *sproto; | |||
2347 | char ssflow[ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], sdflow[ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; | |||
2348 | char sdmask[ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], ssmask[ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; | |||
2349 | int dmasklen, smasklen; | |||
2350 | char *sidtype = 0, *didtype = 0; | |||
2351 | char lname[100], dname[100], configname[200]; | |||
2352 | int shostflag = 0, dhostflag = 0; | |||
2353 | struct pf_key_v2_node *ext; | |||
2354 | struct passwd *pwd = 0; | |||
| ||||
2355 | u_int16_t sport = 0, dport = 0; | |||
2356 | u_int8_t tproto = 0; | |||
2357 | char tmbuf[sizeof sport * 3 + 1], *xform; | |||
2358 | int connlen; | |||
2359 | ||||
2360 | /* This needs to be dynamically allocated. */ | |||
2361 | connlen = 22; | |||
2362 | conn = malloc(connlen); | |||
2363 | if (!conn) { | |||
2364 | log_error("pf_key_v2_acquire: malloc (%d) failed", connlen); | |||
2365 | return; | |||
2366 | } | |||
2367 | msg = (struct sadb_msg *)TAILQ_FIRST(pmsg)((pmsg)->tqh_first)->seg; | |||
2368 | ||||
2369 | ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_DST6); | |||
2370 | if (!ext) { | |||
2371 | log_print("pf_key_v2_acquire: " | |||
2372 | "no destination address specified"); | |||
2373 | free(conn); | |||
2374 | return; | |||
2375 | } | |||
2376 | dst = ext->seg; | |||
2377 | ||||
2378 | ext = pf_key_v2_find_ext(pmsg, SADB_EXT_ADDRESS_SRC5); | |||
2379 | if (ext) | |||
2380 | src = ext->seg; | |||
2381 | ||||
2382 | ext = pf_key_v2_find_ext(pmsg, SADB_EXT_IDENTITY_SRC10); | |||
2383 | if (ext) | |||
2384 | srcident = ext->seg; | |||
2385 | ||||
2386 | ext = pf_key_v2_find_ext(pmsg, SADB_EXT_IDENTITY_DST11); | |||
2387 | if (ext) | |||
2388 | dstident = ext->seg; | |||
2389 | ||||
2390 | /* Ask the kernel for the matching policy. */ | |||
2391 | bzero(&askpolicy_msg, sizeof askpolicy_msg); | |||
2392 | askpolicy_msg.sadb_msg_type = SADB_X_ASKPOLICY15; | |||
2393 | askpolicy = pf_key_v2_msg_new(&askpolicy_msg, 0); | |||
2394 | if (!askpolicy) | |||
2395 | goto fail; | |||
2396 | ||||
2397 | policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY25; | |||
2398 | policy.sadb_x_policy_len = sizeof policy / PF_KEY_V2_CHUNK8; | |||
2399 | policy.sadb_x_policy_seq = msg->sadb_msg_seq; | |||
2400 | if (pf_key_v2_msg_add(askpolicy, (struct sadb_ext *)&policy, 0) == -1) | |||
2401 | goto fail; | |||
2402 | ||||
2403 | ret = pf_key_v2_call(askpolicy); | |||
2404 | if (!ret) | |||
2405 | goto fail; | |||
2406 | ||||
2407 | /* Now we have all the information needed. */ | |||
2408 | ||||
2409 | ext = pf_key_v2_find_ext(ret, SADB_X_EXT_SRC_FLOW21); | |||
2410 | if (!ext) { | |||
2411 | log_print("pf_key_v2_acquire: no source flow extension found"); | |||
2412 | goto fail; | |||
2413 | } | |||
2414 | sflow = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); | |||
2415 | ||||
2416 | ext = pf_key_v2_find_ext(ret, SADB_X_EXT_DST_FLOW22); | |||
2417 | if (!ext) { | |||
2418 | log_print("pf_key_v2_acquire: " | |||
2419 | "no destination flow extension found"); | |||
2420 | goto fail; | |||
2421 | } | |||
2422 | dflow = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); | |||
2423 | ext = pf_key_v2_find_ext(ret, SADB_X_EXT_SRC_MASK17); | |||
2424 | if (!ext) { | |||
2425 | log_print("pf_key_v2_acquire: no source mask extension found"); | |||
2426 | goto fail; | |||
2427 | } | |||
2428 | smask = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); | |||
2429 | ||||
2430 | ext = pf_key_v2_find_ext(ret, SADB_X_EXT_DST_MASK18); | |||
2431 | if (!ext) { | |||
2432 | log_print("pf_key_v2_acquire: " | |||
2433 | "no destination mask extension found"); | |||
2434 | goto fail; | |||
2435 | } | |||
2436 | dmask = (struct sockaddr *) (((struct sadb_address *) ext->seg) + 1); | |||
2437 | ||||
2438 | ext = pf_key_v2_find_ext(ret, SADB_X_EXT_FLOW_TYPE20); | |||
2439 | if (!ext) { | |||
2440 | log_print("pf_key_v2_acquire: no flow type extension found"); | |||
2441 | goto fail; | |||
2442 | } | |||
2443 | sproto = ext->seg; | |||
2444 | tproto = sproto->sadb_protocol_proto; | |||
2445 | ||||
2446 | bzero(ssflow, sizeof ssflow); | |||
2447 | bzero(sdflow, sizeof sdflow); | |||
2448 | bzero(ssmask, sizeof ssmask); | |||
2449 | bzero(sdmask, sizeof sdmask); | |||
2450 | smasklen = dmasklen = -1; | |||
2451 | ||||
2452 | sidtype = didtype = "IPV4_ADDR_SUBNET"; /* default */ | |||
2453 | ||||
2454 | switch (sflow->sa_family) { | |||
2455 | case AF_INET2: | |||
2456 | if (inet_ntop(AF_INET2, | |||
2457 | &((struct sockaddr_in *) sflow)->sin_addr, ssflow, | |||
2458 | ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2459 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2460 | goto fail; | |||
2461 | } | |||
2462 | sport = ((struct sockaddr_in *) sflow)->sin_port; | |||
2463 | if (inet_ntop(AF_INET2, | |||
2464 | &((struct sockaddr_in *) dflow)->sin_addr, sdflow, | |||
2465 | ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2466 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2467 | goto fail; | |||
2468 | } | |||
2469 | dport = ((struct sockaddr_in *) dflow)->sin_port; | |||
2470 | if (inet_ntop(AF_INET2, | |||
2471 | &((struct sockaddr_in *) smask)->sin_addr, ssmask, | |||
2472 | ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2473 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2474 | goto fail; | |||
2475 | } | |||
2476 | if (inet_ntop(AF_INET2, | |||
2477 | &((struct sockaddr_in *) dmask)->sin_addr, sdmask, | |||
2478 | ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2479 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2480 | goto fail; | |||
2481 | } | |||
2482 | smasklen = mask4len((struct sockaddr_in *) smask); | |||
2483 | dmasklen = mask4len((struct sockaddr_in *) dmask); | |||
2484 | if (((struct sockaddr_in *) smask)->sin_addr.s_addr == | |||
2485 | INADDR_BROADCAST((u_int32_t)(0xffffffff))) { | |||
2486 | shostflag = 1; | |||
2487 | sidtype = "IPV4_ADDR"; | |||
2488 | } | |||
2489 | if (((struct sockaddr_in *) dmask)->sin_addr.s_addr == | |||
2490 | INADDR_BROADCAST((u_int32_t)(0xffffffff))) { | |||
2491 | dhostflag = 1; | |||
2492 | didtype = "IPV4_ADDR"; | |||
2493 | } | |||
2494 | break; | |||
2495 | ||||
2496 | case AF_INET624: | |||
2497 | if (inet_ntop(AF_INET624, | |||
2498 | &((struct sockaddr_in6 *) sflow)->sin6_addr, | |||
2499 | ssflow, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2500 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2501 | goto fail; | |||
2502 | } | |||
2503 | sport = ((struct sockaddr_in6 *) sflow)->sin6_port; | |||
2504 | if (inet_ntop(AF_INET624, | |||
2505 | &((struct sockaddr_in6 *) dflow)->sin6_addr, | |||
2506 | sdflow, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2507 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2508 | goto fail; | |||
2509 | } | |||
2510 | dport = ((struct sockaddr_in6 *) dflow)->sin6_port; | |||
2511 | if (inet_ntop(AF_INET624, | |||
2512 | &((struct sockaddr_in6 *) smask)->sin6_addr, | |||
2513 | ssmask, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2514 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2515 | goto fail; | |||
2516 | } | |||
2517 | if (inet_ntop(AF_INET624, | |||
2518 | &((struct sockaddr_in6 *) dmask)->sin6_addr, | |||
2519 | sdmask, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2520 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2521 | goto fail; | |||
2522 | } | |||
2523 | smasklen = mask6len((struct sockaddr_in6 *) smask); | |||
2524 | dmasklen = mask6len((struct sockaddr_in6 *) dmask); | |||
2525 | sidtype = didtype = "IPV6_ADDR_SUBNET"; | |||
2526 | if (IN6_IS_ADDR_FULL(&((struct sockaddr_in6 *)smask)->sin6_addr)((*(u_int32_t *)(void *)(&(&((struct sockaddr_in6 *)smask )->sin6_addr)->__u6_addr.__u6_addr8[0]) == 0xffffffff) && (*(u_int32_t *)(void *)(&(&((struct sockaddr_in6 *)smask )->sin6_addr)->__u6_addr.__u6_addr8[4]) == 0xffffffff) && (*(u_int32_t *)(void *)(&(&((struct sockaddr_in6 *)smask )->sin6_addr)->__u6_addr.__u6_addr8[8]) == 0xffffffff) && (*(u_int32_t *)(void *)(&(&((struct sockaddr_in6 *)smask )->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0xffffffff) )) { | |||
2527 | shostflag = 1; | |||
2528 | sidtype = "IPV6_ADDR"; | |||
2529 | } | |||
2530 | if (IN6_IS_ADDR_FULL(&((struct sockaddr_in6 *)dmask)->sin6_addr)((*(u_int32_t *)(void *)(&(&((struct sockaddr_in6 *)dmask )->sin6_addr)->__u6_addr.__u6_addr8[0]) == 0xffffffff) && (*(u_int32_t *)(void *)(&(&((struct sockaddr_in6 *)dmask )->sin6_addr)->__u6_addr.__u6_addr8[4]) == 0xffffffff) && (*(u_int32_t *)(void *)(&(&((struct sockaddr_in6 *)dmask )->sin6_addr)->__u6_addr.__u6_addr8[8]) == 0xffffffff) && (*(u_int32_t *)(void *)(&(&((struct sockaddr_in6 *)dmask )->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0xffffffff) )) { | |||
2531 | dhostflag = 1; | |||
2532 | didtype = "IPV6_ADDR"; | |||
2533 | } | |||
2534 | break; | |||
2535 | } | |||
2536 | ||||
2537 | dstaddr = (struct sockaddr *)(dst + 1); | |||
2538 | bzero(dstbuf, sizeof dstbuf); | |||
2539 | bzero(srcbuf, sizeof srcbuf); | |||
2540 | ||||
2541 | if (dstaddr->sa_family == 0) { | |||
2542 | /* | |||
2543 | * Destination was not specified in the flow -- can we derive | |||
2544 | * it? | |||
2545 | */ | |||
2546 | if (dhostflag == 0) { | |||
2547 | log_print("pf_key_v2_acquire: " | |||
2548 | "Cannot determine precise destination"); | |||
2549 | goto fail; | |||
2550 | } | |||
2551 | dstaddr = dflow; | |||
2552 | } | |||
2553 | switch (dstaddr->sa_family) { | |||
2554 | case AF_INET2: | |||
2555 | if (inet_ntop(AF_INET2, | |||
2556 | &((struct sockaddr_in *) dstaddr)->sin_addr, | |||
2557 | dstbuf, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2558 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2559 | goto fail; | |||
2560 | } | |||
2561 | LOG_DBG((LOG_SYSDEP, 20,log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d" , dstbuf, msg->sadb_msg_satype) | |||
2562 | "pf_key_v2_acquire: dst=%s sproto %d", dstbuf,log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d" , dstbuf, msg->sadb_msg_satype) | |||
2563 | msg->sadb_msg_satype))log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d" , dstbuf, msg->sadb_msg_satype); | |||
2564 | break; | |||
2565 | ||||
2566 | case AF_INET624: | |||
2567 | if (inet_ntop(AF_INET624, | |||
2568 | &((struct sockaddr_in6 *) dstaddr)->sin6_addr, | |||
2569 | dstbuf, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2570 | log_print("pf_key_v2_acquire: inet_ntop failed"); | |||
2571 | goto fail; | |||
2572 | } | |||
2573 | LOG_DBG((LOG_SYSDEP, 20,log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d" , dstbuf, msg->sadb_msg_satype) | |||
2574 | "pf_key_v2_acquire: dst=%s sproto %d", dstbuf,log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d" , dstbuf, msg->sadb_msg_satype) | |||
2575 | msg->sadb_msg_satype))log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: dst=%s sproto %d" , dstbuf, msg->sadb_msg_satype); | |||
2576 | break; | |||
2577 | } | |||
2578 | ||||
2579 | if (src
| |||
2580 | srcaddr = (struct sockaddr *) (src + 1); | |||
2581 | ||||
2582 | switch (srcaddr->sa_family) { | |||
2583 | case AF_INET2: | |||
2584 | if (inet_ntop(AF_INET2, | |||
2585 | &((struct sockaddr_in *) srcaddr)->sin_addr, | |||
2586 | srcbuf, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2587 | log_print("pf_key_v2_acquire: " | |||
2588 | "inet_ntop failed"); | |||
2589 | goto fail; | |||
2590 | } | |||
2591 | break; | |||
2592 | ||||
2593 | case AF_INET624: | |||
2594 | if (inet_ntop(AF_INET624, | |||
2595 | &((struct sockaddr_in6 *)srcaddr)->sin6_addr, | |||
2596 | srcbuf, ADDRESS_MAXsizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") == NULL((void *)0)) { | |||
2597 | log_print("pf_key_v2_acquire: " | |||
2598 | "inet_ntop failed"); | |||
2599 | goto fail; | |||
2600 | } | |||
2601 | break; | |||
2602 | ||||
2603 | default: | |||
2604 | /* | |||
2605 | * The kernel will pass an all '0' EXT_ADDRESS_SRC if | |||
2606 | * it wasn't specified for the flow. In that case, do | |||
2607 | * NOT specify the srcaddr in the Peer-name below | |||
2608 | */ | |||
2609 | srcbuf[0] = 0; | |||
2610 | srcaddr = NULL((void *)0); | |||
2611 | break; | |||
2612 | } | |||
2613 | } | |||
2614 | /* Insert source ID. */ | |||
2615 | if (srcident) { | |||
2616 | slen = (srcident->sadb_ident_len * sizeof(u_int64_t)) | |||
2617 | - sizeof(struct sadb_ident); | |||
2618 | if (((unsigned char *) (srcident + 1))[slen - 1] != '\0') { | |||
2619 | log_print("pf_key_v2_acquire: " | |||
2620 | "source identity not NUL-terminated"); | |||
2621 | goto fail; | |||
2622 | } | |||
2623 | /* Check for valid type. */ | |||
2624 | switch (srcident->sadb_ident_type) { | |||
2625 | case SADB_IDENTTYPE_PREFIX1: | |||
2626 | /* Determine what the address family is. */ | |||
2627 | srcid = memchr(srcident + 1, ':', slen); | |||
2628 | if (srcid) | |||
2629 | afamily = AF_INET624; | |||
2630 | else | |||
2631 | afamily = AF_INET2; | |||
2632 | ||||
2633 | srcid = memchr(srcident + 1, '/', slen); | |||
2634 | if (!srcid) { | |||
2635 | log_print("pf_key_v2_acquire: " | |||
2636 | "badly formatted PREFIX identity"); | |||
2637 | goto fail; | |||
2638 | } | |||
2639 | masklen = atoi(srcid + 1); | |||
2640 | ||||
2641 | /* XXX We only support host addresses. */ | |||
2642 | if ((afamily == AF_INET624 && masklen != 128) || | |||
2643 | (afamily == AF_INET2 && masklen != 32)) { | |||
2644 | log_print("pf_key_v2_acquire: " | |||
2645 | "non-host address specified in source " | |||
2646 | "identity (mask length %d), ignoring " | |||
2647 | "request", masklen); | |||
2648 | goto fail; | |||
2649 | } | |||
2650 | /* | |||
2651 | * NUL-terminate the PREFIX string at the separator, | |||
2652 | * then dup. | |||
2653 | */ | |||
2654 | *srcid = '\0'; | |||
2655 | if (asprintf(&srcid, "id-%s", | |||
2656 | (char *) (srcident + 1)) == -1) { | |||
2657 | log_error("pf_key_v2_acquire: asprintf() failed"); | |||
2658 | goto fail; | |||
2659 | } | |||
2660 | ||||
2661 | /* Set the section if it doesn't already exist. */ | |||
2662 | af = conf_begin(); | |||
2663 | if (!conf_get_str(srcid, "ID-type")) { | |||
2664 | if (conf_set(af, srcid, "ID-type", | |||
2665 | afamily == AF_INET2 ? "IPV4_ADDR" : | |||
2666 | "IPV6_ADDR", 1, 0) || | |||
2667 | conf_set(af, srcid, "Refcount", "1", 1, 0) || | |||
2668 | conf_set(af, srcid, "Address", | |||
2669 | (char *) (srcident + 1), 1, 0)) { | |||
2670 | conf_end(af, 0); | |||
2671 | goto fail; | |||
2672 | } | |||
2673 | } else | |||
2674 | pf_key_v2_conf_refinc(af, srcid); | |||
2675 | conf_end(af, 1); | |||
2676 | break; | |||
2677 | ||||
2678 | case SADB_IDENTTYPE_FQDN2: | |||
2679 | prefstring = "FQDN"; | |||
2680 | /*FALLTHROUGH*/ | |||
2681 | case SADB_IDENTTYPE_USERFQDN3: | |||
2682 | if (!prefstring
| |||
2683 | prefstring = "USER_FQDN"; | |||
2684 | ||||
2685 | /* | |||
2686 | * Check whether there is a string following | |||
2687 | * the header; if no, that there is a user ID | |||
2688 | * (and acquire the login name). If there is | |||
2689 | * both a string and a user ID, check that | |||
2690 | * they match. | |||
2691 | */ | |||
2692 | if ((slen == 0) && | |||
2693 | (srcident->sadb_ident_id == 0)) { | |||
2694 | log_print("pf_key_v2_acquire: " | |||
2695 | "no user FQDN or ID provided"); | |||
2696 | goto fail; | |||
2697 | } | |||
2698 | if (srcident->sadb_ident_id) { | |||
2699 | pwd = | |||
2700 | getpwuid(srcident->sadb_ident_id); | |||
2701 | if (!pwd) { | |||
2702 | log_error("pf_key_v2_acquire: " | |||
2703 | "could not acquire " | |||
2704 | "username from provided " | |||
2705 | "ID %llu", | |||
2706 | srcident->sadb_ident_id); | |||
2707 | goto fail; | |||
2708 | } | |||
2709 | if (slen != 0) | |||
2710 | if (strcmp(pwd->pw_name, | |||
2711 | (char *) (srcident + 1)) | |||
2712 | != 0) { | |||
2713 | log_print("pf_key_v2_acquire: " | |||
2714 | "provided user " | |||
2715 | "name and ID do " | |||
2716 | "not match (%s != " | |||
2717 | "%s)", | |||
2718 | (char *) (srcident + 1), | |||
2719 | pwd->pw_name); | |||
2720 | /* | |||
2721 | * String has | |||
2722 | * precedence, per | |||
2723 | * RFC 2367. | |||
2724 | */ | |||
2725 | } | |||
2726 | } | |||
2727 | } | |||
2728 | if (asprintf(&srcid, "id-%s", | |||
2729 | slen ? (char *) (srcident + 1) : pwd->pw_name) == -1) { | |||
| ||||
2730 | log_error("pf_key_v2_acquire: asprintf() failed"); | |||
2731 | goto fail; | |||
2732 | } | |||
2733 | pwd = 0; | |||
2734 | ||||
2735 | /* Set the section if it doesn't already exist. */ | |||
2736 | af = conf_begin(); | |||
2737 | if (!conf_get_str(srcid, "ID-type")) { | |||
2738 | if (conf_set(af, srcid, "ID-type", prefstring, | |||
2739 | 1, 0) || | |||
2740 | conf_set(af, srcid, "Refcount", "1", 1, 0) || | |||
2741 | conf_set(af, srcid, "Name", | |||
2742 | srcid + 3, 1, 0)) { | |||
2743 | conf_end(af, 0); | |||
2744 | goto fail; | |||
2745 | } | |||
2746 | } else | |||
2747 | pf_key_v2_conf_refinc(af, srcid); | |||
2748 | conf_end(af, 1); | |||
2749 | break; | |||
2750 | ||||
2751 | default: | |||
2752 | LOG_DBG((LOG_SYSDEP, 20,log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: invalid source ID type %d" , srcident->sadb_ident_type) | |||
2753 | "pf_key_v2_acquire: invalid source ID type %d",log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: invalid source ID type %d" , srcident->sadb_ident_type) | |||
2754 | srcident->sadb_ident_type))log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: invalid source ID type %d" , srcident->sadb_ident_type); | |||
2755 | goto fail; | |||
2756 | } | |||
2757 | ||||
2758 | LOG_DBG((LOG_SYSDEP, 50,log_debug (LOG_SYSDEP, 50, "pf_key_v2_acquire: constructed source ID \"%s\"" , srcid) | |||
2759 | "pf_key_v2_acquire: constructed source ID \"%s\"", srcid))log_debug (LOG_SYSDEP, 50, "pf_key_v2_acquire: constructed source ID \"%s\"" , srcid); | |||
2760 | prefstring = 0; | |||
2761 | } | |||
2762 | /* Insert destination ID. */ | |||
2763 | if (dstident) { | |||
2764 | slen = (dstident->sadb_ident_len * sizeof(u_int64_t)) | |||
2765 | - sizeof(struct sadb_ident); | |||
2766 | ||||
2767 | /* Check for valid type. */ | |||
2768 | switch (dstident->sadb_ident_type) { | |||
2769 | case SADB_IDENTTYPE_PREFIX1: | |||
2770 | /* Determine what the address family is. */ | |||
2771 | dstid = memchr(dstident + 1, ':', slen); | |||
2772 | if (dstid) | |||
2773 | afamily = AF_INET624; | |||
2774 | else | |||
2775 | afamily = AF_INET2; | |||
2776 | ||||
2777 | dstid = memchr(dstident + 1, '/', slen); | |||
2778 | if (!dstid) { | |||
2779 | log_print("pf_key_v2_acquire: " | |||
2780 | "badly formatted PREFIX identity"); | |||
2781 | goto fail; | |||
2782 | } | |||
2783 | masklen = atoi(dstid + 1); | |||
2784 | ||||
2785 | /* XXX We only support host addresses. */ | |||
2786 | if ((afamily == AF_INET624 && masklen != 128) || | |||
2787 | (afamily == AF_INET2 && masklen != 32)) { | |||
2788 | log_print("pf_key_v2_acquire: " | |||
2789 | "non-host address specified in " | |||
2790 | "destination identity (mask length %d), " | |||
2791 | "ignoring request", masklen); | |||
2792 | goto fail; | |||
2793 | } | |||
2794 | /* | |||
2795 | * NUL-terminate the PREFIX string at the separator, | |||
2796 | * then dup. | |||
2797 | */ | |||
2798 | *dstid = '\0'; | |||
2799 | if (asprintf(&dstid, "id-%s", | |||
2800 | (char *) (dstident + 1)) == -1) { | |||
2801 | log_error("pf_key_v2_acquire: asprintf() failed"); | |||
2802 | goto fail; | |||
2803 | } | |||
2804 | ||||
2805 | /* Set the section if it doesn't already exist. */ | |||
2806 | af = conf_begin(); | |||
2807 | if (!conf_get_str(dstid, "ID-type")) { | |||
2808 | if (conf_set(af, dstid, "ID-type", | |||
2809 | afamily == AF_INET2 ? "IPV4_ADDR" : | |||
2810 | "IPV6_ADDR", 1, 0) || | |||
2811 | conf_set(af, dstid, "Refcount", "1", 1, 0) || | |||
2812 | conf_set(af, dstid, "Address", | |||
2813 | (char *) (dstident + 1), 1, 0)) { | |||
2814 | conf_end(af, 0); | |||
2815 | goto fail; | |||
2816 | } | |||
2817 | } else | |||
2818 | pf_key_v2_conf_refinc(af, dstid); | |||
2819 | conf_end(af, 1); | |||
2820 | break; | |||
2821 | ||||
2822 | case SADB_IDENTTYPE_FQDN2: | |||
2823 | prefstring = "FQDN"; | |||
2824 | /*FALLTHROUGH*/ | |||
2825 | case SADB_IDENTTYPE_USERFQDN3: | |||
2826 | if (!prefstring) { | |||
2827 | prefstring = "USER_FQDN"; | |||
2828 | ||||
2829 | /* | |||
2830 | * Check whether there is a string following | |||
2831 | * the header; if no, that there is a user ID | |||
2832 | * (and acquire the login name). If there is | |||
2833 | * both a string and a user ID, check that | |||
2834 | * they match. | |||
2835 | */ | |||
2836 | if (slen == 0 && | |||
2837 | dstident->sadb_ident_id == 0) { | |||
2838 | log_print("pf_key_v2_acquire: " | |||
2839 | "no user FQDN or ID provided"); | |||
2840 | goto fail; | |||
2841 | } | |||
2842 | if (dstident->sadb_ident_id) { | |||
2843 | pwd = getpwuid(dstident->sadb_ident_id); | |||
2844 | if (!pwd) { | |||
2845 | log_error("pf_key_v2_acquire: " | |||
2846 | "could not acquire " | |||
2847 | "username from provided " | |||
2848 | "ID %llu", | |||
2849 | dstident->sadb_ident_id); | |||
2850 | goto fail; | |||
2851 | } | |||
2852 | if (slen != 0) | |||
2853 | if (strcmp(pwd->pw_name, | |||
2854 | (char *) (dstident + 1)) | |||
2855 | != 0) { | |||
2856 | log_print("pf_key_v2_acquire: " | |||
2857 | "provided user " | |||
2858 | "name and ID do " | |||
2859 | "not match (%s != " | |||
2860 | "%s)", | |||
2861 | (char *) (dstident + 1), | |||
2862 | pwd->pw_name); | |||
2863 | /* | |||
2864 | * String has | |||
2865 | * precedence, per RF | |||
2866 | * 2367. | |||
2867 | */ | |||
2868 | } | |||
2869 | } | |||
2870 | } | |||
2871 | if (asprintf(&dstid, "id-%s", | |||
2872 | slen ? (char *) (dstident + 1) : pwd->pw_name) == -1) { | |||
2873 | log_error("pf_key_v2_acquire: asprintf() failed"); | |||
2874 | goto fail; | |||
2875 | } | |||
2876 | pwd = 0; | |||
2877 | ||||
2878 | /* Set the section if it doesn't already exist. */ | |||
2879 | af = conf_begin(); | |||
2880 | if (!conf_get_str(dstid, "ID-type")) { | |||
2881 | if (conf_set(af, dstid, "ID-type", prefstring, | |||
2882 | 1, 0) || | |||
2883 | conf_set(af, dstid, "Refcount", "1", 1, 0) || | |||
2884 | conf_set(af, dstid, "Name", | |||
2885 | dstid + 3, 1, 0)) { | |||
2886 | conf_end(af, 0); | |||
2887 | goto fail; | |||
2888 | } | |||
2889 | } else | |||
2890 | pf_key_v2_conf_refinc(af, dstid); | |||
2891 | conf_end(af, 1); | |||
2892 | break; | |||
2893 | ||||
2894 | default: | |||
2895 | LOG_DBG((LOG_SYSDEP, 20, "pf_key_v2_acquire: "log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: " "invalid destination ID type %d" , dstident->sadb_ident_type) | |||
2896 | "invalid destination ID type %d",log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: " "invalid destination ID type %d" , dstident->sadb_ident_type) | |||
2897 | dstident->sadb_ident_type))log_debug (LOG_SYSDEP, 20, "pf_key_v2_acquire: " "invalid destination ID type %d" , dstident->sadb_ident_type); | |||
2898 | goto fail; | |||
2899 | } | |||
2900 | ||||
2901 | LOG_DBG((LOG_SYSDEP, 50,log_debug (LOG_SYSDEP, 50, "pf_key_v2_acquire: constructed destination ID \"%s\"" , dstid) | |||
2902 | "pf_key_v2_acquire: constructed destination ID \"%s\"",log_debug (LOG_SYSDEP, 50, "pf_key_v2_acquire: constructed destination ID \"%s\"" , dstid) | |||
2903 | dstid))log_debug (LOG_SYSDEP, 50, "pf_key_v2_acquire: constructed destination ID \"%s\"" , dstid); | |||
2904 | } | |||
2905 | /* Now we've placed the necessary IDs in the configuration space. */ | |||
2906 | ||||
2907 | /* Get a new connection sequence number. */ | |||
2908 | for (;; connection_seq++) { | |||
2909 | snprintf(conn, connlen, "Connection-%u", connection_seq); | |||
2910 | ||||
2911 | /* Does it exist ? */ | |||
2912 | if (!conf_get_str(conn, "Phase")) | |||
2913 | break; | |||
2914 | } | |||
2915 | ||||
2916 | /* | |||
2917 | * Set the IPsec connection entry. In particular, the following fields: | |||
2918 | * - Phase | |||
2919 | * - ISAKMP-peer | |||
2920 | * - Local-ID/Remote-ID (if provided) | |||
2921 | * - Acquire-ID (sequence number of kernel message, e.g., PF_KEYv2) | |||
2922 | * - Configuration | |||
2923 | * | |||
2924 | * Also set the following section: | |||
2925 | * [peer-dstaddr(-local-srcaddr)] | |||
2926 | * with these fields: | |||
2927 | * - Phase | |||
2928 | * - ID (if provided) | |||
2929 | * - Remote-ID (if provided) | |||
2930 | * - Local-address (if provided) | |||
2931 | * - Address | |||
2932 | * - Configuration (if an entry phase1-dstaddr-srcadd) | |||
2933 | * exists -- otherwise use the defaults) | |||
2934 | */ | |||
2935 | ||||
2936 | /* | |||
2937 | * The various cases: | |||
2938 | * - peer-dstaddr | |||
2939 | * - peer-dstaddr-local-srcaddr | |||
2940 | */ | |||
2941 | if (asprintf(&peer, "peer-%s%s%s", dstbuf, srcaddr ? "-local-" : "", | |||
2942 | srcaddr ? srcbuf : "") == -1) | |||
2943 | goto fail; | |||
2944 | ||||
2945 | /* | |||
2946 | * Set the IPsec connection section. Refcount is set to 2, because | |||
2947 | * it will be linked both to the incoming and the outgoing SA. | |||
2948 | */ | |||
2949 | af = conf_begin(); | |||
2950 | if (conf_set(af, conn, "Phase", "2", 0, 0) || | |||
2951 | conf_set(af, conn, "Flags", "__ondemand", 0, 0) || | |||
2952 | conf_set(af, conn, "Refcount", "2", 0, 0) || | |||
2953 | conf_set(af, conn, "ISAKMP-peer", peer, 0, 0)) { | |||
2954 | conf_end(af, 0); | |||
2955 | goto fail; | |||
2956 | } | |||
2957 | /* Set the sequence number. */ | |||
2958 | snprintf(lname, sizeof lname, "%u", msg->sadb_msg_seq); | |||
2959 | if (conf_set(af, conn, "Acquire-ID", lname, 0, 0)) { | |||
2960 | conf_end(af, 0); | |||
2961 | goto fail; | |||
2962 | } | |||
2963 | /* | |||
2964 | * Set Phase 2 IDs -- this is the Local-ID section. | |||
2965 | * - from-address | |||
2966 | * - from-address=proto | |||
2967 | * - from-address=proto:port | |||
2968 | * - from-network/masklen | |||
2969 | * - from-network/masklen=proto | |||
2970 | * - from-network/masklen=proto:port | |||
2971 | */ | |||
2972 | phase2id(lname, sizeof lname, "from", ssflow, smasklen, tproto, sport); | |||
2973 | if (conf_set(af, conn, "Local-ID", lname, 0, 0)) { | |||
2974 | conf_end(af, 0); | |||
2975 | goto fail; | |||
2976 | } | |||
2977 | if (!conf_get_str(lname, "ID-type")) { | |||
2978 | if (conf_set(af, lname, "Refcount", "1", 0, 0)) { | |||
2979 | conf_end(af, 0); | |||
2980 | goto fail; | |||
2981 | } | |||
2982 | if (shostflag) { | |||
2983 | if (conf_set(af, lname, "ID-type", sidtype, 0, 0) || | |||
2984 | conf_set(af, lname, "Address", ssflow, 0, 0)) { | |||
2985 | conf_end(af, 0); | |||
2986 | goto fail; | |||
2987 | } | |||
2988 | } else { | |||
2989 | if (conf_set(af, lname, "ID-type", sidtype, 0, 0) || | |||
2990 | conf_set(af, lname, "Network", ssflow, 0, 0) || | |||
2991 | conf_set(af, lname, "Netmask", ssmask, 0, 0)) { | |||
2992 | conf_end(af, 0); | |||
2993 | goto fail; | |||
2994 | } | |||
2995 | } | |||
2996 | if (tproto) { | |||
2997 | snprintf(tmbuf, sizeof sport * 3 + 1, "%u", tproto); | |||
2998 | if (conf_set(af, lname, "Protocol", tmbuf, 0, 0)) { | |||
2999 | conf_end(af, 0); | |||
3000 | goto fail; | |||
3001 | } | |||
3002 | if (sport) { | |||
3003 | snprintf(tmbuf, sizeof sport * 3 + 1, "%u", | |||
3004 | ntohs(sport)(__uint16_t)(__builtin_constant_p(sport) ? (__uint16_t)(((__uint16_t )(sport) & 0xffU) << 8 | ((__uint16_t)(sport) & 0xff00U) >> 8) : __swap16md(sport))); | |||
3005 | if (conf_set(af, lname, "Port", tmbuf, 0, 0)) { | |||
3006 | conf_end(af, 0); | |||
3007 | goto fail; | |||
3008 | } | |||
3009 | } | |||
3010 | } | |||
3011 | } else | |||
3012 | pf_key_v2_conf_refinc(af, lname); | |||
3013 | ||||
3014 | /* | |||
3015 | * Set Remote-ID section. | |||
3016 | * to-address | |||
3017 | * to-address=proto | |||
3018 | * to-address=proto:port | |||
3019 | * to-network/masklen | |||
3020 | * to-network/masklen=proto | |||
3021 | * to-network/masklen=proto:port | |||
3022 | */ | |||
3023 | phase2id(dname, sizeof dname, "to", sdflow, dmasklen, tproto, dport); | |||
3024 | if (conf_set(af, conn, "Remote-ID", dname, 0, 0)) { | |||
3025 | conf_end(af, 0); | |||
3026 | goto fail; | |||
3027 | } | |||
3028 | if (!conf_get_str(dname, "ID-type")) { | |||
3029 | if (conf_set(af, dname, "Refcount", "1", 0, 0)) { | |||
3030 | conf_end(af, 0); | |||
3031 | goto fail; | |||
3032 | } | |||
3033 | if (dhostflag) { | |||
3034 | if (conf_set(af, dname, "ID-type", didtype, 0, 0) || | |||
3035 | conf_set(af, dname, "Address", sdflow, 0, 0)) { | |||
3036 | conf_end(af, 0); | |||
3037 | goto fail; | |||
3038 | } | |||
3039 | } else { | |||
3040 | if (conf_set(af, dname, "ID-type", didtype, 0, 0) || | |||
3041 | conf_set(af, dname, "Network", sdflow, 0, 0) || | |||
3042 | conf_set(af, dname, "Netmask", sdmask, 0, 0)) { | |||
3043 | conf_end(af, 0); | |||
3044 | goto fail; | |||
3045 | } | |||
3046 | } | |||
3047 | ||||
3048 | if (tproto) { | |||
3049 | snprintf(tmbuf, sizeof dport * 3 + 1, "%u", tproto); | |||
3050 | if (conf_set(af, dname, "Protocol", tmbuf, 0, 0)) { | |||
3051 | conf_end(af, 0); | |||
3052 | goto fail; | |||
3053 | } | |||
3054 | if (dport) { | |||
3055 | snprintf(tmbuf, sizeof dport * 3 + 1, "%u", | |||
3056 | ntohs(dport)(__uint16_t)(__builtin_constant_p(dport) ? (__uint16_t)(((__uint16_t )(dport) & 0xffU) << 8 | ((__uint16_t)(dport) & 0xff00U) >> 8) : __swap16md(dport))); | |||
3057 | if (conf_set(af, dname, "Port", tmbuf, 0, 0)) { | |||
3058 | conf_end(af, 0); | |||
3059 | goto fail; | |||
3060 | } | |||
3061 | } | |||
3062 | } | |||
3063 | } else | |||
3064 | pf_key_v2_conf_refinc(af, dname); | |||
3065 | ||||
3066 | /* | |||
3067 | * XXX | |||
3068 | * We should be using information from the proposal to set this up. | |||
3069 | * At least, we should make this selectable. | |||
3070 | */ | |||
3071 | ||||
3072 | /* | |||
3073 | * Phase 2 configuration. | |||
3074 | * - phase2-from-address-to-address | |||
3075 | * - ... | |||
3076 | * - phase2-from-net/len=proto:port-to-net/len=proto:port | |||
3077 | */ | |||
3078 | snprintf(configname, sizeof configname, "phase2-%s-%s", lname, dname); | |||
3079 | if (conf_set(af, conn, "Configuration", configname, 0, 0)) { | |||
3080 | conf_end(af, 0); | |||
3081 | goto fail; | |||
3082 | } | |||
3083 | if (!conf_get_str(configname, "Exchange_type")) { | |||
3084 | if (conf_set(af, configname, "Exchange_type", "Quick_mode", | |||
3085 | 0, 0) || | |||
3086 | conf_set(af, peer, "Refcount", "1", 0, 0) || | |||
3087 | conf_set(af, configname, "DOI", "IPSEC", 0, 0)) { | |||
3088 | conf_end(af, 0); | |||
3089 | goto fail; | |||
3090 | } | |||
3091 | if (conf_get_str("General", "Default-phase-2-suites")) { | |||
3092 | if (conf_set(af, configname, "Suites", | |||
3093 | conf_get_str("General", "Default-phase-2-suites"), | |||
3094 | 0, 0)) { | |||
3095 | conf_end(af, 0); | |||
3096 | goto fail; | |||
3097 | } | |||
3098 | } else { | |||
3099 | if (conf_set(af, configname, "Suites", | |||
3100 | "QM-ESP-3DES-SHA-PFS-SUITE", 0, 0)) { | |||
3101 | conf_end(af, 0); | |||
3102 | goto fail; | |||
3103 | } | |||
3104 | } | |||
3105 | } else | |||
3106 | pf_key_v2_conf_refinc(af, configname); | |||
3107 | ||||
3108 | /* Set the ISAKMP-peer section. */ | |||
3109 | if (!conf_get_str(peer, "Phase")) { | |||
3110 | if (conf_set(af, peer, "Phase", "1", 0, 0) || | |||
3111 | conf_set(af, peer, "Refcount", "1", 0, 0) || | |||
3112 | conf_set(af, peer, "Address", dstbuf, 0, 0)) { | |||
3113 | conf_end(af, 0); | |||
3114 | goto fail; | |||
3115 | } | |||
3116 | if (srcaddr && conf_set(af, peer, "Local-address", srcbuf, 0, | |||
3117 | 0)) { | |||
3118 | conf_end(af, 0); | |||
3119 | goto fail; | |||
3120 | } | |||
3121 | snprintf(confname, sizeof confname, "phase1-%s", peer); | |||
3122 | if (conf_set(af, peer, "Configuration", confname, 0, 0)) { | |||
3123 | conf_end(af, 0); | |||
3124 | goto fail; | |||
3125 | } | |||
3126 | ||||
3127 | /* Phase 1 configuration. */ | |||
3128 | if (!conf_get_str(confname, "exchange_type")) { | |||
3129 | xform = conf_get_str("Default-phase-1-configuration", | |||
3130 | "Transforms"); | |||
3131 | if (conf_set(af, confname, "Transforms", xform ? xform : | |||
3132 | "3DES-SHA-RSA_SIG", 0, 0)) { | |||
3133 | conf_end(af, 0); | |||
3134 | goto fail; | |||
3135 | } | |||
3136 | ||||
3137 | if (conf_set(af, confname, "Exchange_Type", "ID_PROT", | |||
3138 | 0, 0) || | |||
3139 | conf_set(af, confname, "DOI", "IPSEC", 0, 0) || | |||
3140 | conf_set(af, confname, "Refcount", "1", 0, 0)) { | |||
3141 | conf_end(af, 0); | |||
3142 | goto fail; | |||
3143 | } | |||
3144 | } else | |||
3145 | pf_key_v2_conf_refinc(af, confname); | |||
3146 | ||||
3147 | /* The ID we should use in Phase 1. */ | |||
3148 | if (srcid && conf_set(af, peer, "ID", srcid, 0, 0)) { | |||
3149 | conf_end(af, 0); | |||
3150 | goto fail; | |||
3151 | } | |||
3152 | /* The ID the other side should use in Phase 1. */ | |||
3153 | if (dstid && conf_set(af, peer, "Remote-ID", dstid, 0, 0)) { | |||
3154 | conf_end(af, 0); | |||
3155 | goto fail; | |||
3156 | } | |||
3157 | } else | |||
3158 | pf_key_v2_conf_refinc(af, peer); | |||
3159 | ||||
3160 | /* All done. */ | |||
3161 | conf_end(af, 1); | |||
3162 | ||||
3163 | /* Let's rock 'n roll. */ | |||
3164 | connection_record_passive(conn); | |||
3165 | pf_key_v2_connection_check(conn); | |||
3166 | conn = 0; | |||
3167 | ||||
3168 | /* Fall-through to cleanup. */ | |||
3169 | fail: | |||
3170 | if (ret) | |||
3171 | pf_key_v2_msg_free(ret); | |||
3172 | if (askpolicy) | |||
3173 | pf_key_v2_msg_free(askpolicy); | |||
3174 | free(srcid); | |||
3175 | free(dstid); | |||
3176 | free(peer); | |||
3177 | free(conn); | |||
3178 | return; | |||
3179 | } | |||
3180 | ||||
3181 | static void | |||
3182 | pf_key_v2_notify(struct pf_key_v2_msg *msg) | |||
3183 | { | |||
3184 | switch (((struct sadb_msg *)TAILQ_FIRST(msg)((msg)->tqh_first)->seg)->sadb_msg_type) { | |||
3185 | case SADB_EXPIRE8: | |||
3186 | pf_key_v2_expire(msg); | |||
3187 | break; | |||
3188 | ||||
3189 | case SADB_ACQUIRE6: | |||
3190 | if (!ui_daemon_passive) | |||
3191 | pf_key_v2_acquire(msg); | |||
3192 | break; | |||
3193 | ||||
3194 | default: | |||
3195 | log_print("pf_key_v2_notify: unexpected message type (%d)", | |||
3196 | ((struct sadb_msg *)TAILQ_FIRST(msg)((msg)->tqh_first)->seg)->sadb_msg_type); | |||
3197 | } | |||
3198 | pf_key_v2_msg_free(msg); | |||
3199 | } | |||
3200 | ||||
3201 | void | |||
3202 | pf_key_v2_handler(int fd) | |||
3203 | { | |||
3204 | struct pf_key_v2_msg *msg; | |||
3205 | int n; | |||
3206 | ||||
3207 | /* | |||
3208 | * As synchronous read/writes to the socket can have taken place | |||
3209 | * between the select(2) call of the main loop and this handler, we | |||
3210 | * need to recheck the readability. | |||
3211 | */ | |||
3212 | if (ioctl(pf_key_v2_socket, FIONREAD((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) << 16) | ((('f')) << 8) | ((127))), &n) == -1) { | |||
3213 | log_error("pf_key_v2_handler: ioctl (%d, FIONREAD, &n) failed", | |||
3214 | pf_key_v2_socket); | |||
3215 | return; | |||
3216 | } | |||
3217 | if (!n) | |||
3218 | return; | |||
3219 | ||||
3220 | msg = pf_key_v2_read(0); | |||
3221 | if (msg) | |||
3222 | pf_key_v2_notify(msg); | |||
3223 | } | |||
3224 | ||||
3225 | /* | |||
3226 | * Group 2 IPsec SAs given by the PROTO1 and PROTO2 protocols of the SA IKE | |||
3227 | * security association in a chain. | |||
3228 | * XXX Assumes OpenBSD GRPSPIS extension. | |||
3229 | */ | |||
3230 | int | |||
3231 | pf_key_v2_group_spis(struct sa *sa, struct proto *proto1, | |||
3232 | struct proto *proto2, int incoming) | |||
3233 | { | |||
3234 | struct sadb_msg msg; | |||
3235 | struct sadb_sa sa1, sa2; | |||
3236 | struct sadb_address *addr = 0; | |||
3237 | struct sadb_protocol protocol; | |||
3238 | struct pf_key_v2_msg *grpspis = 0, *ret = 0; | |||
3239 | struct sockaddr *saddr; | |||
3240 | int err; | |||
3241 | size_t len; | |||
3242 | ||||
3243 | msg.sadb_msg_type = SADB_X_GRPSPIS14; | |||
3244 | switch (proto1->proto) { | |||
3245 | case IPSEC_PROTO_IPSEC_ESP3: | |||
3246 | msg.sadb_msg_satype = SADB_SATYPE_ESP2; | |||
3247 | break; | |||
3248 | case IPSEC_PROTO_IPSEC_AH2: | |||
3249 | msg.sadb_msg_satype = SADB_SATYPE_AH1; | |||
3250 | break; | |||
3251 | case IPSEC_PROTO_IPCOMP4: | |||
3252 | msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP9; | |||
3253 | break; | |||
3254 | default: | |||
3255 | log_print("pf_key_v2_group_spis: invalid proto %d", | |||
3256 | proto1->proto); | |||
3257 | goto cleanup; | |||
3258 | } | |||
3259 | msg.sadb_msg_seq = 0; | |||
3260 | grpspis = pf_key_v2_msg_new(&msg, 0); | |||
3261 | if (!grpspis) | |||
3262 | goto cleanup; | |||
3263 | ||||
3264 | /* Setup the SA extensions. */ | |||
3265 | sa1.sadb_sa_exttype = SADB_EXT_SA1; | |||
3266 | sa1.sadb_sa_len = sizeof sa1 / PF_KEY_V2_CHUNK8; | |||
3267 | memcpy(&sa1.sadb_sa_spi, proto1->spi[incoming], | |||
3268 | sizeof sa1.sadb_sa_spi); | |||
3269 | sa1.sadb_sa_replay = 0; | |||
3270 | sa1.sadb_sa_state = 0; | |||
3271 | sa1.sadb_sa_auth = 0; | |||
3272 | sa1.sadb_sa_encrypt = 0; | |||
3273 | sa1.sadb_sa_flags = 0; | |||
3274 | if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *)&sa1, 0) == -1) | |||
3275 | goto cleanup; | |||
3276 | ||||
3277 | sa2.sadb_sa_exttype = SADB_X_EXT_SA223; | |||
3278 | sa2.sadb_sa_len = sizeof sa2 / PF_KEY_V2_CHUNK8; | |||
3279 | memcpy(&sa2.sadb_sa_spi, proto2->spi[incoming], | |||
3280 | sizeof sa2.sadb_sa_spi); | |||
3281 | sa2.sadb_sa_replay = 0; | |||
3282 | sa2.sadb_sa_state = 0; | |||
3283 | sa2.sadb_sa_auth = 0; | |||
3284 | sa2.sadb_sa_encrypt = 0; | |||
3285 | sa2.sadb_sa_flags = 0; | |||
3286 | if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *)&sa2, 0) == -1) | |||
3287 | goto cleanup; | |||
3288 | ||||
3289 | /* | |||
3290 | * Setup the ADDRESS extensions. | |||
3291 | */ | |||
3292 | if (incoming) | |||
3293 | sa->transport->vtbl->get_src(sa->transport, &saddr); | |||
3294 | else | |||
3295 | sa->transport->vtbl->get_dst(sa->transport, &saddr); | |||
3296 | len = sizeof *addr + PF_KEY_V2_ROUND(SA_LEN(saddr))(((((saddr)->sa_len)) + 8 - 1) & ~(8 - 1)); | |||
3297 | addr = calloc(1, len); | |||
3298 | if (!addr) | |||
3299 | goto cleanup; | |||
3300 | addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST6; | |||
3301 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
3302 | addr->sadb_address_reserved = 0; | |||
3303 | memcpy(addr + 1, saddr, SA_LEN(saddr)((saddr)->sa_len)); | |||
3304 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
3305 | if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) addr, | |||
3306 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
3307 | goto cleanup; | |||
3308 | addr = 0; | |||
3309 | ||||
3310 | addr = calloc(1, len); | |||
3311 | if (!addr) | |||
3312 | goto cleanup; | |||
3313 | addr->sadb_address_exttype = SADB_X_EXT_DST224; | |||
3314 | addr->sadb_address_len = len / PF_KEY_V2_CHUNK8; | |||
3315 | addr->sadb_address_reserved = 0; | |||
3316 | memcpy(addr + 1, saddr, SA_LEN(saddr)((saddr)->sa_len)); | |||
3317 | ((struct sockaddr_in *) (addr + 1))->sin_port = 0; | |||
3318 | if (pf_key_v2_msg_add(grpspis, (struct sadb_ext *) addr, | |||
3319 | PF_KEY_V2_NODE_MALLOCED1) == -1) | |||
3320 | goto cleanup; | |||
3321 | addr = 0; | |||
3322 | ||||
3323 | /* Setup the sa type extension. */ | |||
3324 | protocol.sadb_protocol_exttype = SADB_X_EXT_SATYPE235; | |||
3325 | protocol.sadb_protocol_len = sizeof protocol / PF_KEY_V2_CHUNK8; | |||
3326 | switch (proto2->proto) { | |||
3327 | case IPSEC_PROTO_IPSEC_ESP3: | |||
3328 | protocol.sadb_protocol_proto = SADB_SATYPE_ESP2; | |||
3329 | break; | |||
3330 | case IPSEC_PROTO_IPSEC_AH2: | |||
3331 | protocol.sadb_protocol_proto = SADB_SATYPE_AH1; | |||
3332 | break; | |||
3333 | case IPSEC_PROTO_IPCOMP4: | |||
3334 | protocol.sadb_protocol_proto = SADB_X_SATYPE_IPCOMP9; | |||
3335 | break; | |||
3336 | default: | |||
3337 | log_print("pf_key_v2_group_spis: invalid proto %d", | |||
3338 | proto2->proto); | |||
3339 | goto cleanup; | |||
3340 | } | |||
3341 | protocol.sadb_protocol_reserved2 = 0; | |||
3342 | if (pf_key_v2_msg_add(grpspis, | |||
3343 | (struct sadb_ext *)&protocol, 0) == -1) | |||
3344 | goto cleanup; | |||
3345 | ||||
3346 | ret = pf_key_v2_call(grpspis); | |||
3347 | pf_key_v2_msg_free(grpspis); | |||
3348 | grpspis = 0; | |||
3349 | if (!ret) | |||
3350 | goto cleanup; | |||
3351 | err = ((struct sadb_msg *)TAILQ_FIRST(ret)((ret)->tqh_first)->seg)->sadb_msg_errno; | |||
3352 | if (err) { | |||
3353 | log_print("pf_key_v2_group_spis: GRPSPIS: %s", strerror(err)); | |||
3354 | goto cleanup; | |||
3355 | } | |||
3356 | pf_key_v2_msg_free(ret); | |||
3357 | ||||
3358 | LOG_DBG((LOG_SYSDEP, 50, "pf_key_v2_group_spis: done"))log_debug (LOG_SYSDEP, 50, "pf_key_v2_group_spis: done"); | |||
3359 | ||||
3360 | return 0; | |||
3361 | ||||
3362 | cleanup: | |||
3363 | free(addr); | |||
3364 | if (grpspis) | |||
3365 | pf_key_v2_msg_free(grpspis); | |||
3366 | if (ret) | |||
3367 | pf_key_v2_msg_free(ret); | |||
3368 | return -1; | |||
3369 | } |