]>
Commit | Line | Data |
---|---|---|
7ba0088d A |
1 | /* $KAME: isakmp.c,v 1.171 2001/12/12 22:35:37 itojun Exp $ */ |
2 | ||
3 | /* | |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. Neither the name of the project nor the names of its contributors | |
16 | * may be used to endorse or promote products derived from this software | |
17 | * without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
29 | * SUCH DAMAGE. | |
30 | */ | |
31 | ||
32 | #include <sys/types.h> | |
33 | #include <sys/param.h> | |
34 | #include <sys/socket.h> | |
35 | #include <sys/queue.h> | |
36 | ||
37 | #include <netkey/key_var.h> | |
38 | #include <netinet/in.h> | |
39 | ||
40 | #include <stdlib.h> | |
41 | #include <stdio.h> | |
42 | #include <string.h> | |
43 | #include <errno.h> | |
44 | #if TIME_WITH_SYS_TIME | |
45 | # include <sys/time.h> | |
46 | # include <time.h> | |
47 | #else | |
48 | # if HAVE_SYS_TIME_H | |
49 | # include <sys/time.h> | |
50 | # else | |
51 | # include <time.h> | |
52 | # endif | |
53 | #endif | |
54 | #include <netdb.h> | |
55 | #ifdef HAVE_UNISTD_H | |
56 | #include <unistd.h> | |
57 | #endif | |
58 | #include <ctype.h> | |
59 | ||
60 | #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO) | |
61 | #include "addrinfo.h" | |
62 | #endif | |
63 | ||
64 | #include "var.h" | |
65 | #include "misc.h" | |
66 | #include "vmbuf.h" | |
67 | #include "plog.h" | |
68 | #include "sockmisc.h" | |
69 | #include "schedule.h" | |
70 | #include "debug.h" | |
71 | ||
72 | #include "remoteconf.h" | |
73 | #include "localconf.h" | |
74 | #include "grabmyaddr.h" | |
75 | #include "isakmp_var.h" | |
76 | #include "isakmp.h" | |
77 | #include "oakley.h" | |
78 | #include "handler.h" | |
79 | #include "ipsec_doi.h" | |
80 | #include "pfkey.h" | |
81 | #include "crypto_openssl.h" | |
82 | #include "policy.h" | |
83 | #include "isakmp_ident.h" | |
84 | #include "isakmp_agg.h" | |
85 | #include "isakmp_base.h" | |
86 | #include "isakmp_quick.h" | |
87 | #include "isakmp_inf.h" | |
88 | #include "isakmp_newg.h" | |
89 | #include "strnames.h" | |
90 | ||
91 | static int nostate1 __P((struct ph1handle *, vchar_t *)); | |
92 | static int nostate2 __P((struct ph2handle *, vchar_t *)); | |
93 | ||
94 | extern caddr_t val2str(const char *, size_t); | |
95 | ||
96 | static int (*ph1exchange[][2][PHASE1ST_MAX]) | |
97 | __P((struct ph1handle *, vchar_t *)) = { | |
98 | /* error */ | |
99 | { {}, {}, }, | |
100 | /* Identity Protection exchange */ | |
101 | { | |
102 | { nostate1, ident_i1send, nostate1, ident_i2recv, ident_i2send, | |
103 | ident_i3recv, ident_i3send, ident_i4recv, ident_i4send, nostate1, }, | |
104 | { nostate1, ident_r1recv, ident_r1send, ident_r2recv, ident_r2send, | |
105 | ident_r3recv, ident_r3send, nostate1, nostate1, nostate1, }, | |
106 | }, | |
107 | /* Aggressive exchange */ | |
108 | { | |
109 | { nostate1, agg_i1send, nostate1, agg_i2recv, agg_i2send, | |
110 | nostate1, nostate1, nostate1, nostate1, nostate1, }, | |
111 | { nostate1, agg_r1recv, agg_r1send, agg_r2recv, agg_r2send, | |
112 | nostate1, nostate1, nostate1, nostate1, nostate1, }, | |
113 | }, | |
114 | /* Base exchange */ | |
115 | { | |
116 | { nostate1, base_i1send, nostate1, base_i2recv, base_i2send, | |
117 | base_i3recv, base_i3send, nostate1, nostate1, nostate1, }, | |
118 | { nostate1, base_r1recv, base_r1send, base_r2recv, base_r2send, | |
119 | nostate1, nostate1, nostate1, nostate1, nostate1, }, | |
120 | }, | |
121 | }; | |
122 | ||
123 | static int (*ph2exchange[][2][PHASE2ST_MAX]) | |
124 | __P((struct ph2handle *, vchar_t *)) = { | |
125 | /* error */ | |
126 | { {}, {}, }, | |
127 | /* Quick mode for IKE*/ | |
128 | { | |
129 | { nostate2, nostate2, quick_i1prep, nostate2, quick_i1send, | |
130 | quick_i2recv, quick_i2send, quick_i3recv, nostate2, nostate2, }, | |
131 | { nostate2, quick_r1recv, quick_r1prep, nostate2, quick_r2send, | |
132 | quick_r3recv, quick_r3prep, quick_r3send, nostate2, nostate2, } | |
133 | }, | |
134 | }; | |
135 | ||
136 | static u_char r_ck0[] = { 0,0,0,0,0,0,0,0 }; /* used to verify the r_ck. */ | |
137 | ||
138 | static int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *)); | |
139 | static int ph1_main __P((struct ph1handle *, vchar_t *)); | |
140 | static int quick_main __P((struct ph2handle *, vchar_t *)); | |
141 | static int isakmp_ph1begin_r __P((vchar_t *, | |
142 | struct sockaddr *, struct sockaddr *, u_int8_t)); | |
143 | static int isakmp_ph2begin_i __P((struct ph1handle *, struct ph2handle *)); | |
144 | static int isakmp_ph2begin_r __P((struct ph1handle *, vchar_t *)); | |
145 | static int etypesw1 __P((int)); | |
146 | static int etypesw2 __P((int)); | |
147 | ||
148 | /* | |
149 | * isakmp packet handler | |
150 | */ | |
151 | int | |
152 | isakmp_handler(so_isakmp) | |
153 | int so_isakmp; | |
154 | { | |
155 | struct isakmp isakmp; | |
156 | struct sockaddr_storage remote; | |
157 | struct sockaddr_storage local; | |
158 | int remote_len = sizeof(remote); | |
159 | int local_len = sizeof(local); | |
160 | int len; | |
161 | u_short port; | |
162 | vchar_t *buf = NULL; | |
163 | int error = -1; | |
164 | ||
165 | /* read message by MSG_PEEK */ | |
166 | while ((len = recvfromto(so_isakmp, (char *)&isakmp, sizeof(isakmp), | |
167 | MSG_PEEK, (struct sockaddr *)&remote, &remote_len, | |
168 | (struct sockaddr *)&local, &local_len)) < 0) { | |
169 | if (errno == EINTR) | |
170 | continue; | |
171 | plog(LLV_ERROR, LOCATION, NULL, | |
172 | "failed to receive isakmp packet\n"); | |
173 | goto end; | |
174 | } | |
175 | ||
176 | /* check isakmp header length */ | |
177 | if (len < sizeof(isakmp)) { | |
178 | plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote, | |
179 | "packet shorter than isakmp header size.\n"); | |
180 | /* dummy receive */ | |
181 | if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp), | |
182 | 0, (struct sockaddr *)&remote, &remote_len)) < 0) { | |
183 | plog(LLV_ERROR, LOCATION, NULL, | |
184 | "failed to receive isakmp packet\n"); | |
185 | } | |
186 | goto end; | |
187 | } | |
188 | ||
189 | /* read real message */ | |
190 | if ((buf = vmalloc(ntohl(isakmp.len))) == NULL) { | |
191 | plog(LLV_ERROR, LOCATION, NULL, | |
192 | "failed to allocate reading buffer\n"); | |
193 | /* dummy receive */ | |
194 | if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp), | |
195 | 0, (struct sockaddr *)&remote, &remote_len)) < 0) { | |
196 | plog(LLV_ERROR, LOCATION, NULL, | |
197 | "failed to receive isakmp packet\n"); | |
198 | } | |
199 | goto end; | |
200 | } | |
201 | ||
202 | while ((len = recvfromto(so_isakmp, buf->v, buf->l, | |
203 | 0, (struct sockaddr *)&remote, &remote_len, | |
204 | (struct sockaddr *)&local, &local_len)) < 0) { | |
205 | if (errno == EINTR) | |
206 | continue; | |
207 | plog(LLV_ERROR, LOCATION, NULL, | |
208 | "failed to receive isakmp packet\n"); | |
209 | goto end; | |
210 | } | |
211 | ||
212 | if (len != buf->l) { | |
213 | plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote, | |
214 | "received invalid length, why ?\n"); | |
215 | goto end; | |
216 | } | |
217 | ||
218 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
219 | plog(LLV_DEBUG, LOCATION, (struct sockaddr *)&local, | |
220 | "%d bytes message received from %s\n", | |
221 | len, saddr2str((struct sockaddr *)&remote)); | |
222 | plogdump(LLV_DEBUG, buf->v, buf->l); | |
223 | ||
224 | /* avoid packets with malicious port/address */ | |
225 | switch (remote.ss_family) { | |
226 | case AF_INET: | |
227 | port = ((struct sockaddr_in *)&remote)->sin_port; | |
228 | break; | |
229 | #ifdef INET6 | |
230 | case AF_INET6: | |
231 | port = ((struct sockaddr_in6 *)&remote)->sin6_port; | |
232 | break; | |
233 | #endif | |
234 | default: | |
235 | plog(LLV_ERROR, LOCATION, NULL, | |
236 | "invalid family: %d\n", remote.ss_family); | |
237 | goto end; | |
238 | } | |
239 | if (port == 0) { | |
240 | plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote, | |
241 | "src port == 0 (valid as UDP but not with IKE)\n"); | |
242 | goto end; | |
243 | } | |
244 | ||
245 | /* XXX: check sender whether to be allowed or not to accept */ | |
246 | ||
247 | /* XXX: I don't know how to check isakmp half connection attack. */ | |
248 | ||
249 | /* simply reply if the packet was processed. */ | |
250 | if (check_recvdpkt((struct sockaddr *)&remote, | |
251 | (struct sockaddr *)&local, buf)) { | |
252 | plog(LLV_NOTIFY, LOCATION, NULL, | |
253 | "the packet is retransmitted by %s.\n", | |
254 | saddr2str((struct sockaddr *)&remote)); | |
255 | error = 0; | |
256 | goto end; | |
257 | } | |
258 | ||
259 | /* isakmp main routine */ | |
260 | if (isakmp_main(buf, (struct sockaddr *)&remote, | |
261 | (struct sockaddr *)&local) != 0) goto end; | |
262 | ||
263 | error = 0; | |
264 | ||
265 | end: | |
266 | if (buf != NULL) | |
267 | vfree(buf); | |
268 | ||
269 | return(error); | |
270 | } | |
271 | ||
272 | /* | |
273 | * main processing to handle isakmp payload | |
274 | */ | |
275 | static int | |
276 | isakmp_main(msg, remote, local) | |
277 | vchar_t *msg; | |
278 | struct sockaddr *remote, *local; | |
279 | { | |
280 | struct isakmp *isakmp = (struct isakmp *)msg->v; | |
281 | isakmp_index *index = (isakmp_index *)isakmp; | |
282 | u_int32_t msgid = isakmp->msgid; | |
283 | struct ph1handle *iph1; | |
284 | ||
285 | #ifdef HAVE_PRINT_ISAKMP_C | |
286 | isakmp_printpacket(msg, remote, local, 0); | |
287 | #endif | |
288 | ||
289 | /* the initiator's cookie must not be zero */ | |
290 | if (memcmp(&isakmp->i_ck, r_ck0, sizeof(cookie_t)) == 0) { | |
291 | plog(LLV_ERROR, LOCATION, remote, | |
292 | "malformed cookie received.\n"); | |
293 | return -1; | |
294 | } | |
295 | ||
296 | /* Check the Major and Minor Version fields. */ | |
297 | /* | |
298 | * XXX Is is right to check version here ? | |
299 | * I think it may no be here because the version depends | |
300 | * on exchange status. | |
301 | */ | |
302 | if (isakmp->v < ISAKMP_VERSION_NUMBER) { | |
303 | if (ISAKMP_GETMAJORV(isakmp->v) < ISAKMP_MAJOR_VERSION) { | |
304 | plog(LLV_ERROR, LOCATION, remote, | |
305 | "invalid major version %d.\n", | |
306 | ISAKMP_GETMAJORV(isakmp->v)); | |
307 | return -1; | |
308 | } | |
309 | #if ISAKMP_MINOR_VERSION > 0 | |
310 | if (ISAKMP_GETMINORV(isakmp->v) < ISAKMP_MINOR_VERSION) { | |
311 | plog(LLV_ERROR, LOCATION, remote, | |
312 | "invalid minor version %d.\n", | |
313 | ISAKMP_GETMINORV(isakmp->v)); | |
314 | return -1; | |
315 | } | |
316 | #endif | |
317 | } | |
318 | ||
319 | /* check the Flags field. */ | |
320 | /* XXX How is the exclusive check, E and A ? */ | |
321 | if (isakmp->flags & ~(ISAKMP_FLAG_E | ISAKMP_FLAG_C | ISAKMP_FLAG_A)) { | |
322 | plog(LLV_ERROR, LOCATION, remote, | |
323 | "invalid flag 0x%02x.\n", isakmp->flags); | |
324 | return -1; | |
325 | } | |
326 | ||
327 | /* ignore commit bit. */ | |
328 | if (ISSET(isakmp->flags, ISAKMP_FLAG_C)) { | |
329 | if (isakmp->msgid == 0) { | |
330 | isakmp_info_send_nx(isakmp, remote, local, | |
331 | ISAKMP_NTYPE_INVALID_FLAGS, NULL); | |
332 | plog(LLV_ERROR, LOCATION, remote, | |
333 | "Commit bit on phase1 forbidden.\n"); | |
334 | return -1; | |
335 | } | |
336 | } | |
337 | ||
338 | iph1 = getph1byindex(index); | |
339 | if (iph1 != NULL) { | |
340 | /* validity check */ | |
341 | if (memcmp(&isakmp->r_ck, r_ck0, sizeof(cookie_t)) == 0 && | |
342 | iph1->side == INITIATOR) { | |
343 | plog(LLV_DEBUG, LOCATION, remote, | |
344 | "malformed cookie received or " | |
345 | "the initiator's cookies collide.\n"); | |
346 | return -1; | |
347 | } | |
348 | ||
349 | /* must be same addresses in one stream of a phase at least. */ | |
350 | if (cmpsaddrstrict(iph1->remote, remote) != 0) { | |
351 | char *saddr_db, *saddr_act; | |
352 | ||
353 | saddr_db = strdup(saddr2str(iph1->remote)); | |
354 | saddr_act = strdup(saddr2str(remote)); | |
355 | ||
356 | plog(LLV_WARNING, LOCATION, remote, | |
357 | "remote address mismatched. db=%s, act=%s\n", | |
358 | saddr_db, saddr_act); | |
359 | ||
360 | racoon_free(saddr_db); | |
361 | racoon_free(saddr_act); | |
362 | } | |
363 | /* | |
364 | * don't check of exchange type here because other type will be | |
365 | * with same index, for example, informational exchange. | |
366 | */ | |
367 | ||
368 | /* XXX more acceptable check */ | |
369 | } | |
370 | ||
371 | switch (isakmp->etype) { | |
372 | case ISAKMP_ETYPE_IDENT: | |
373 | case ISAKMP_ETYPE_AGG: | |
374 | case ISAKMP_ETYPE_BASE: | |
375 | /* phase 1 validity check */ | |
376 | if (isakmp->msgid != 0) { | |
377 | plog(LLV_ERROR, LOCATION, remote, | |
378 | "message id should be zero in phase1.\n"); | |
379 | return -1; | |
380 | } | |
381 | ||
382 | /* search for isakmp status record of phase 1 */ | |
383 | if (iph1 == NULL) { | |
384 | /* | |
385 | * the packet must be the 1st message from a initiator | |
386 | * or the 2nd message from the responder. | |
387 | */ | |
388 | ||
389 | /* search for phase1 handle by index without r_ck */ | |
390 | iph1 = getph1byindex0(index); | |
391 | if (iph1 == NULL) { | |
392 | /*it must be the 1st message from a initiator.*/ | |
393 | if (memcmp(&isakmp->r_ck, r_ck0, | |
394 | sizeof(cookie_t)) != 0) { | |
395 | ||
396 | plog(LLV_DEBUG, LOCATION, remote, | |
397 | "malformed cookie received " | |
398 | "or the spi expired.\n"); | |
399 | return -1; | |
400 | } | |
401 | ||
402 | /* it must be responder's 1st exchange. */ | |
403 | if (isakmp_ph1begin_r(msg, remote, local, | |
404 | isakmp->etype) < 0) | |
405 | return -1; | |
406 | break; | |
407 | ||
408 | /*NOTREACHED*/ | |
409 | } | |
410 | ||
411 | /* it must be the 2nd message from the responder. */ | |
412 | if (iph1->side != INITIATOR) { | |
413 | plog(LLV_DEBUG, LOCATION, remote, | |
414 | "malformed cookie received. " | |
415 | "it has to be as the initiator. %s\n", | |
416 | isakmp_pindex(&iph1->index, 0)); | |
417 | return -1; | |
418 | } | |
419 | } | |
420 | ||
421 | /* | |
422 | * Don't delete phase 1 handler when the exchange type | |
423 | * in handler is not equal to packet's one because of no | |
424 | * authencication completed. | |
425 | */ | |
426 | if (iph1->etype != isakmp->etype) { | |
427 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
428 | "exchange type is mismatched: " | |
429 | "db=%s packet=%s, ignore it.\n", | |
430 | s_isakmp_etype(iph1->etype), | |
431 | s_isakmp_etype(isakmp->etype)); | |
432 | return -1; | |
433 | } | |
434 | ||
435 | /* call main process of phase 1 */ | |
436 | if (ph1_main(iph1, msg) < 0) { | |
437 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
438 | "phase1 negotiation failed.\n"); | |
439 | remph1(iph1); | |
440 | delph1(iph1); | |
441 | return -1; | |
442 | } | |
443 | break; | |
444 | ||
445 | case ISAKMP_ETYPE_AUTH: | |
446 | plog(LLV_INFO, LOCATION, remote, | |
447 | "unsupported exchange %d received.\n", | |
448 | isakmp->etype); | |
449 | break; | |
450 | ||
451 | case ISAKMP_ETYPE_INFO: | |
452 | case ISAKMP_ETYPE_ACKINFO: | |
453 | /* | |
454 | * iph1 must be present for Information message. | |
455 | * if iph1 is null then trying to get the phase1 status | |
456 | * as the packet from responder againt initiator's 1st | |
457 | * exchange in phase 1. | |
458 | * NOTE: We think such informational exchange should be ignored. | |
459 | */ | |
460 | if (iph1 == NULL) { | |
461 | iph1 = getph1byindex0(index); | |
462 | if (iph1 == NULL) { | |
463 | plog(LLV_ERROR, LOCATION, remote, | |
464 | "unknown Informational " | |
465 | "exchange received.\n"); | |
466 | return -1; | |
467 | } | |
468 | if (cmpsaddrstrict(iph1->remote, remote) != 0) { | |
469 | plog(LLV_WARNING, LOCATION, remote, | |
470 | "remote address mismatched. " | |
471 | "db=%s\n", | |
472 | saddr2str(iph1->remote)); | |
473 | } | |
474 | } | |
475 | ||
476 | if (isakmp_info_recv(iph1, msg) < 0) | |
477 | return -1; | |
478 | break; | |
479 | ||
480 | case ISAKMP_ETYPE_QUICK: | |
481 | { | |
482 | struct ph2handle *iph2; | |
483 | ||
484 | if (iph1 == NULL) { | |
485 | isakmp_info_send_nx(isakmp, remote, local, | |
486 | ISAKMP_NTYPE_INVALID_COOKIE, NULL); | |
487 | plog(LLV_ERROR, LOCATION, remote, | |
488 | "can't start the quick mode, " | |
489 | "there is no ISAKMP-SA, %s\n", | |
490 | isakmp_pindex((isakmp_index *)&isakmp->i_ck, | |
491 | isakmp->msgid)); | |
492 | return -1; | |
493 | } | |
494 | ||
495 | /* check status of phase 1 whether negotiated or not. */ | |
496 | if (iph1->status != PHASE1ST_ESTABLISHED) { | |
497 | plog(LLV_ERROR, LOCATION, remote, | |
498 | "can't start the quick mode, " | |
499 | "there is no valid ISAKMP-SA, %s\n", | |
500 | isakmp_pindex(&iph1->index, iph1->msgid)); | |
501 | return -1; | |
502 | } | |
503 | ||
504 | /* search isakmp phase 2 stauts record. */ | |
505 | iph2 = getph2bymsgid(iph1, msgid); | |
506 | if (iph2 == NULL) { | |
507 | /* it must be new negotiation as responder */ | |
508 | if (isakmp_ph2begin_r(iph1, msg) < 0) | |
509 | return -1; | |
510 | return 0; | |
511 | /*NOTREACHED*/ | |
512 | } | |
513 | ||
514 | /* commit bit. */ | |
515 | /* XXX | |
516 | * we keep to set commit bit during negotiation. | |
517 | * When SA is configured, bit will be reset. | |
518 | * XXX | |
519 | * don't initiate commit bit. should be fixed in the future. | |
520 | */ | |
521 | if (ISSET(isakmp->flags, ISAKMP_FLAG_C)) | |
522 | iph2->flags |= ISAKMP_FLAG_C; | |
523 | ||
524 | /* call main process of quick mode */ | |
525 | if (quick_main(iph2, msg) < 0) { | |
526 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
527 | "phase2 negotiation failed.\n"); | |
528 | unbindph12(iph2); | |
529 | remph2(iph2); | |
530 | delph2(iph2); | |
531 | return -1; | |
532 | } | |
533 | } | |
534 | break; | |
535 | ||
536 | case ISAKMP_ETYPE_NEWGRP: | |
537 | if (iph1 == NULL) { | |
538 | plog(LLV_ERROR, LOCATION, remote, | |
539 | "Unknown new group mode exchange, " | |
540 | "there is no ISAKMP-SA.\n"); | |
541 | return -1; | |
542 | } | |
543 | isakmp_newgroup_r(iph1, msg); | |
544 | break; | |
545 | ||
546 | case ISAKMP_ETYPE_NONE: | |
547 | default: | |
548 | plog(LLV_ERROR, LOCATION, NULL, | |
549 | "Invalid exchange type %d from %s.\n", | |
550 | isakmp->etype, saddr2str(remote)); | |
551 | return -1; | |
552 | } | |
553 | ||
554 | return 0; | |
555 | } | |
556 | ||
557 | /* | |
558 | * main function of phase 1. | |
559 | */ | |
560 | static int | |
561 | ph1_main(iph1, msg) | |
562 | struct ph1handle *iph1; | |
563 | vchar_t *msg; | |
564 | { | |
565 | int error; | |
566 | #ifdef ENABLE_STATS | |
567 | struct timeval start, end; | |
568 | #endif | |
569 | ||
570 | /* ignore a packet */ | |
571 | if (iph1->status == PHASE1ST_ESTABLISHED) | |
572 | return 0; | |
573 | ||
574 | #ifdef ENABLE_STATS | |
575 | gettimeofday(&start, NULL); | |
576 | #endif | |
577 | /* receive */ | |
578 | if (ph1exchange[etypesw1(iph1->etype)] | |
579 | [iph1->side] | |
580 | [iph1->status] == NULL) { | |
581 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
582 | "why isn't the function defined.\n"); | |
583 | return -1; | |
584 | } | |
585 | error = (ph1exchange[etypesw1(iph1->etype)] | |
586 | [iph1->side] | |
587 | [iph1->status])(iph1, msg); | |
588 | if (error != 0) { | |
589 | #if 0 | |
590 | /* XXX | |
591 | * When an invalid packet is received on phase1, it should | |
592 | * be selected to process this packet. That is to respond | |
593 | * with a notify and delete phase 1 handler, OR not to respond | |
594 | * and keep phase 1 handler. | |
595 | */ | |
596 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
597 | "failed to pre-process packet.\n"); | |
598 | return -1; | |
599 | #else | |
600 | /* ignore the error and keep phase 1 handler */ | |
601 | return 0; | |
602 | #endif | |
603 | } | |
604 | ||
605 | /* free resend buffer */ | |
606 | if (iph1->sendbuf == NULL) { | |
607 | plog(LLV_ERROR, LOCATION, NULL, | |
608 | "no buffer found as sendbuf\n"); | |
609 | return -1; | |
610 | } | |
611 | vfree(iph1->sendbuf); | |
612 | iph1->sendbuf = NULL; | |
613 | ||
614 | /* turn off schedule */ | |
615 | if (iph1->scr) | |
616 | SCHED_KILL(iph1->scr); | |
617 | ||
618 | /* send */ | |
619 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
620 | if ((ph1exchange[etypesw1(iph1->etype)] | |
621 | [iph1->side] | |
622 | [iph1->status])(iph1, msg) != 0) { | |
623 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
624 | "failed to process packet.\n"); | |
625 | return -1; | |
626 | } | |
627 | ||
628 | #ifdef ENABLE_STATS | |
629 | gettimeofday(&end, NULL); | |
630 | syslog(LOG_NOTICE, "%s(%s): %8.6f", | |
631 | "phase1", s_isakmp_state(iph1->etype, iph1->side, iph1->status), | |
632 | timedelta(&start, &end)); | |
633 | #endif | |
634 | if (iph1->status == PHASE1ST_ESTABLISHED) { | |
635 | ||
636 | #ifdef ENABLE_STATS | |
637 | gettimeofday(&iph1->end, NULL); | |
638 | syslog(LOG_NOTICE, "%s(%s): %8.6f", | |
639 | "phase1", s_isakmp_etype(iph1->etype), | |
640 | timedelta(&iph1->start, &iph1->end)); | |
641 | #endif | |
642 | ||
643 | /* save created date. */ | |
644 | (void)time(&iph1->created); | |
645 | ||
646 | /* add to the schedule to expire, and seve back pointer. */ | |
647 | iph1->sce = sched_new(iph1->approval->lifetime, | |
648 | isakmp_ph1expire_stub, iph1); | |
649 | ||
650 | /* INITIAL-CONTACT processing */ | |
651 | /* don't anything if local test mode. */ | |
652 | if (!f_local | |
653 | && iph1->rmconf->ini_contact && !getcontacted(iph1->remote)) { | |
654 | /* send INITIAL-CONTACT */ | |
655 | isakmp_info_send_n1(iph1, | |
656 | ISAKMP_NTYPE_INITIAL_CONTACT, NULL); | |
657 | /* insert a node into contacted list. */ | |
658 | if (inscontacted(iph1->remote) == -1) { | |
659 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
660 | "failed to add contacted list.\n"); | |
661 | /* ignore */ | |
662 | } | |
663 | } | |
664 | ||
665 | log_ph1established(iph1); | |
666 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
667 | } | |
668 | ||
669 | return 0; | |
670 | } | |
671 | ||
672 | /* | |
673 | * main function of quick mode. | |
674 | */ | |
675 | static int | |
676 | quick_main(iph2, msg) | |
677 | struct ph2handle *iph2; | |
678 | vchar_t *msg; | |
679 | { | |
680 | struct isakmp *isakmp = (struct isakmp *)msg->v; | |
681 | int error; | |
682 | #ifdef ENABLE_STATS | |
683 | struct timeval start, end; | |
684 | #endif | |
685 | ||
686 | /* ignore a packet */ | |
687 | if (iph2->status == PHASE2ST_ESTABLISHED | |
688 | || iph2->status == PHASE2ST_GETSPISENT) | |
689 | return 0; | |
690 | ||
691 | #ifdef ENABLE_STATS | |
692 | gettimeofday(&start, NULL); | |
693 | #endif | |
694 | ||
695 | /* receive */ | |
696 | if (ph2exchange[etypesw2(isakmp->etype)] | |
697 | [iph2->side] | |
698 | [iph2->status] == NULL) { | |
699 | plog(LLV_ERROR, LOCATION, iph2->ph1->remote, | |
700 | "why isn't the function defined.\n"); | |
701 | return -1; | |
702 | } | |
703 | error = (ph2exchange[etypesw2(isakmp->etype)] | |
704 | [iph2->side] | |
705 | [iph2->status])(iph2, msg); | |
706 | if (error != 0) { | |
707 | plog(LLV_ERROR, LOCATION, iph2->ph1->remote, | |
708 | "failed to pre-process packet.\n"); | |
709 | if (error == ISAKMP_INTERNAL_ERROR) | |
710 | return 0; | |
711 | isakmp_info_send_n1(iph2->ph1, error, NULL); | |
712 | return -1; | |
713 | } | |
714 | ||
715 | /* when using commit bit, status will be reached here. */ | |
716 | if (iph2->status == PHASE2ST_ADDSA) | |
717 | return 0; | |
718 | ||
719 | /* free resend buffer */ | |
720 | if (iph2->sendbuf == NULL) { | |
721 | plog(LLV_ERROR, LOCATION, NULL, | |
722 | "no buffer found as sendbuf\n"); | |
723 | return -1; | |
724 | } | |
725 | vfree(iph2->sendbuf); | |
726 | iph2->sendbuf = NULL; | |
727 | ||
728 | /* turn off schedule */ | |
729 | if (iph2->scr) | |
730 | SCHED_KILL(iph2->scr); | |
731 | ||
732 | /* send */ | |
733 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
734 | if ((ph2exchange[etypesw2(isakmp->etype)] | |
735 | [iph2->side] | |
736 | [iph2->status])(iph2, msg) != 0) { | |
737 | plog(LLV_ERROR, LOCATION, iph2->ph1->remote, | |
738 | "failed to process packet.\n"); | |
739 | return -1; | |
740 | } | |
741 | ||
742 | #ifdef ENABLE_STATS | |
743 | gettimeofday(&end, NULL); | |
744 | syslog(LOG_NOTICE, "%s(%s): %8.6f", | |
745 | "phase2", | |
746 | s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status), | |
747 | timedelta(&start, &end)); | |
748 | #endif | |
749 | ||
750 | return 0; | |
751 | } | |
752 | ||
753 | /* new negotiation of phase 1 for initiator */ | |
754 | int | |
755 | isakmp_ph1begin_i(rmconf, remote) | |
756 | struct remoteconf *rmconf; | |
757 | struct sockaddr *remote; | |
758 | { | |
759 | struct ph1handle *iph1; | |
760 | #ifdef ENABLE_STATS | |
761 | struct timeval start, end; | |
762 | #endif | |
763 | ||
764 | /* get new entry to isakmp status table. */ | |
765 | iph1 = newph1(); | |
766 | if (iph1 == NULL) | |
767 | return -1; | |
768 | ||
769 | iph1->status = PHASE1ST_START; | |
770 | iph1->rmconf = rmconf; | |
771 | iph1->side = INITIATOR; | |
772 | iph1->version = ISAKMP_VERSION_NUMBER; | |
773 | iph1->msgid = 0; | |
774 | iph1->flags = 0; | |
775 | iph1->ph2cnt = 0; | |
776 | #ifdef HAVE_GSSAPI | |
777 | iph1->gssapi_state = NULL; | |
778 | #endif | |
779 | iph1->approval = NULL; | |
780 | ||
781 | /* XXX copy remote address */ | |
782 | if (copy_ph1addresses(iph1, rmconf, remote, NULL) < 0) | |
783 | return -1; | |
784 | ||
785 | (void)insph1(iph1); | |
786 | ||
787 | /* start phase 1 exchange */ | |
788 | iph1->etype = rmconf->etypes->type; | |
789 | ||
790 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
791 | { | |
792 | char *a; | |
793 | ||
794 | a = strdup(saddr2str(iph1->local)); | |
795 | plog(LLV_INFO, LOCATION, NULL, | |
796 | "initiate new phase 1 negotiation: %s<=>%s\n", | |
797 | a, saddr2str(iph1->remote)); | |
798 | racoon_free(a); | |
799 | } | |
800 | plog(LLV_INFO, LOCATION, NULL, | |
801 | "begin %s mode.\n", | |
802 | s_isakmp_etype(iph1->etype)); | |
803 | ||
804 | #ifdef ENABLE_STATS | |
805 | gettimeofday(&iph1->start, NULL); | |
806 | gettimeofday(&start, NULL); | |
807 | #endif | |
808 | /* start exchange */ | |
809 | if ((ph1exchange[etypesw1(iph1->etype)] | |
810 | [iph1->side] | |
811 | [iph1->status])(iph1, NULL) != 0) { | |
812 | /* failed to start phase 1 negotiation */ | |
813 | remph1(iph1); | |
814 | delph1(iph1); | |
815 | ||
816 | return -1; | |
817 | } | |
818 | ||
819 | #ifdef ENABLE_STATS | |
820 | gettimeofday(&end, NULL); | |
821 | syslog(LOG_NOTICE, "%s(%s): %8.6f", | |
822 | "phase1", | |
823 | s_isakmp_state(iph1->etype, iph1->side, iph1->status), | |
824 | timedelta(&start, &end)); | |
825 | #endif | |
826 | ||
827 | return 0; | |
828 | } | |
829 | ||
830 | /* new negotiation of phase 1 for responder */ | |
831 | static int | |
832 | isakmp_ph1begin_r(msg, remote, local, etype) | |
833 | vchar_t *msg; | |
834 | struct sockaddr *remote, *local; | |
835 | u_int8_t etype; | |
836 | { | |
837 | struct isakmp *isakmp = (struct isakmp *)msg->v; | |
838 | struct remoteconf *rmconf; | |
839 | struct ph1handle *iph1; | |
840 | struct etypes *etypeok; | |
841 | #ifdef ENABLE_STATS | |
842 | struct timeval start, end; | |
843 | #endif | |
844 | ||
845 | /* look for my configuration */ | |
846 | rmconf = getrmconf(remote); | |
847 | if (rmconf == NULL) { | |
848 | plog(LLV_ERROR, LOCATION, remote, | |
849 | "couldn't find " | |
850 | "configuration.\n"); | |
851 | return -1; | |
852 | } | |
853 | ||
854 | /* check to be acceptable exchange type */ | |
855 | etypeok = check_etypeok(rmconf, etype); | |
856 | if (etypeok == NULL) { | |
857 | plog(LLV_ERROR, LOCATION, remote, | |
858 | "not acceptable %s mode\n", s_isakmp_etype(etype)); | |
859 | return -1; | |
860 | } | |
861 | ||
862 | /* get new entry to isakmp status table. */ | |
863 | iph1 = newph1(); | |
864 | if (iph1 == NULL) | |
865 | return -1; | |
866 | ||
867 | memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(iph1->index.i_ck)); | |
868 | iph1->status = PHASE1ST_START; | |
869 | iph1->rmconf = rmconf; | |
870 | iph1->flags = 0; | |
871 | iph1->side = RESPONDER; | |
872 | iph1->etype = etypeok->type; | |
873 | iph1->version = isakmp->v; | |
874 | iph1->msgid = 0; | |
875 | #ifdef HAVE_GSSAPI | |
876 | iph1->gssapi_state = NULL; | |
877 | #endif | |
878 | iph1->approval = NULL; | |
879 | ||
880 | /* copy remote address */ | |
881 | if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) | |
882 | return -1; | |
883 | ||
884 | (void)insph1(iph1); | |
885 | ||
886 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
887 | { | |
888 | char *a; | |
889 | ||
890 | a = strdup(saddr2str(iph1->local)); | |
891 | plog(LLV_INFO, LOCATION, NULL, | |
892 | "respond new phase 1 negotiation: %s<=>%s\n", | |
893 | a, saddr2str(iph1->remote)); | |
894 | racoon_free(a); | |
895 | } | |
896 | plog(LLV_INFO, LOCATION, NULL, | |
897 | "begin %s mode.\n", s_isakmp_etype(etype)); | |
898 | ||
899 | #ifdef ENABLE_STATS | |
900 | gettimeofday(&iph1->start, NULL); | |
901 | gettimeofday(&start, NULL); | |
902 | #endif | |
903 | /* start exchange */ | |
904 | if ((ph1exchange[etypesw1(iph1->etype)] | |
905 | [iph1->side] | |
906 | [iph1->status])(iph1, msg) < 0 | |
907 | || (ph1exchange[etypesw1(iph1->etype)] | |
908 | [iph1->side] | |
909 | [iph1->status])(iph1, msg) < 0) { | |
910 | plog(LLV_ERROR, LOCATION, remote, | |
911 | "failed to process packet.\n"); | |
912 | remph1(iph1); | |
913 | delph1(iph1); | |
914 | return -1; | |
915 | } | |
916 | #ifdef ENABLE_STATS | |
917 | gettimeofday(&end, NULL); | |
918 | syslog(LOG_NOTICE, "%s(%s): %8.6f", | |
919 | "phase1", | |
920 | s_isakmp_state(iph1->etype, iph1->side, iph1->status), | |
921 | timedelta(&start, &end)); | |
922 | #endif | |
923 | ||
924 | return 0; | |
925 | } | |
926 | ||
927 | /* new negotiation of phase 2 for initiator */ | |
928 | static int | |
929 | isakmp_ph2begin_i(iph1, iph2) | |
930 | struct ph1handle *iph1; | |
931 | struct ph2handle *iph2; | |
932 | { | |
933 | /* found ISAKMP-SA. */ | |
934 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
935 | plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n"); | |
936 | { | |
937 | char *a; | |
938 | a = strdup(saddr2str(iph2->src)); | |
939 | plog(LLV_INFO, LOCATION, NULL, | |
940 | "initiate new phase 2 negotiation: %s<=>%s\n", | |
941 | a, saddr2str(iph2->dst)); | |
942 | racoon_free(a); | |
943 | } | |
944 | ||
945 | #ifdef ENABLE_STATS | |
946 | gettimeofday(&iph2->start, NULL); | |
947 | #endif | |
948 | /* found isakmp-sa */ | |
949 | bindph12(iph1, iph2); | |
950 | iph2->status = PHASE2ST_STATUS2; | |
951 | ||
952 | if ((ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)] | |
953 | [iph2->side] | |
954 | [iph2->status])(iph2, NULL) < 0) { | |
955 | unbindph12(iph2); | |
956 | /* release ipsecsa handler due to internal error. */ | |
957 | remph2(iph2); | |
958 | delph2(iph2); | |
959 | return -1; | |
960 | } | |
961 | return 0; | |
962 | } | |
963 | ||
964 | /* new negotiation of phase 2 for responder */ | |
965 | static int | |
966 | isakmp_ph2begin_r(iph1, msg) | |
967 | struct ph1handle *iph1; | |
968 | vchar_t *msg; | |
969 | { | |
970 | struct isakmp *isakmp = (struct isakmp *)msg->v; | |
971 | struct ph2handle *iph2 = 0; | |
972 | int error; | |
973 | #ifdef ENABLE_STATS | |
974 | struct timeval start, end; | |
975 | #endif | |
976 | ||
977 | iph2 = newph2(); | |
978 | if (iph2 == NULL) { | |
979 | plog(LLV_ERROR, LOCATION, NULL, | |
980 | "failed to allocate phase2 entry.\n"); | |
981 | return -1; | |
982 | } | |
983 | ||
984 | iph2->ph1 = iph1; | |
985 | iph2->side = RESPONDER; | |
986 | iph2->status = PHASE2ST_START; | |
987 | iph2->flags = isakmp->flags; | |
988 | iph2->msgid = isakmp->msgid; | |
989 | iph2->seq = pk_getseq(); | |
990 | iph2->ivm = oakley_newiv2(iph1, iph2->msgid); | |
991 | if (iph2->ivm == NULL) { | |
992 | delph2(iph2); | |
993 | return -1; | |
994 | } | |
995 | iph2->dst = dupsaddr(iph1->remote); /* XXX should be considered */ | |
996 | if (iph2->dst == NULL) { | |
997 | delph2(iph2); | |
998 | return -1; | |
999 | } | |
1000 | switch (iph2->dst->sa_family) { | |
1001 | case AF_INET: | |
1002 | ((struct sockaddr_in *)iph2->dst)->sin_port = 0; | |
1003 | break; | |
1004 | #ifdef INET6 | |
1005 | case AF_INET6: | |
1006 | ((struct sockaddr_in6 *)iph2->dst)->sin6_port = 0; | |
1007 | break; | |
1008 | #endif | |
1009 | default: | |
1010 | plog(LLV_ERROR, LOCATION, NULL, | |
1011 | "invalid family: %d\n", iph2->dst->sa_family); | |
1012 | delph2(iph2); | |
1013 | return -1; | |
1014 | } | |
1015 | ||
1016 | iph2->src = dupsaddr(iph1->local); /* XXX should be considered */ | |
1017 | if (iph2->src == NULL) { | |
1018 | delph2(iph2); | |
1019 | return -1; | |
1020 | } | |
1021 | switch (iph2->src->sa_family) { | |
1022 | case AF_INET: | |
1023 | ((struct sockaddr_in *)iph2->src)->sin_port = 0; | |
1024 | break; | |
1025 | #ifdef INET6 | |
1026 | case AF_INET6: | |
1027 | ((struct sockaddr_in6 *)iph2->src)->sin6_port = 0; | |
1028 | break; | |
1029 | #endif | |
1030 | default: | |
1031 | plog(LLV_ERROR, LOCATION, NULL, | |
1032 | "invalid family: %d\n", iph2->src->sa_family); | |
1033 | delph2(iph2); | |
1034 | return -1; | |
1035 | } | |
1036 | ||
1037 | /* add new entry to isakmp status table */ | |
1038 | insph2(iph2); | |
1039 | bindph12(iph1, iph2); | |
1040 | ||
1041 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
1042 | { | |
1043 | char *a; | |
1044 | ||
1045 | a = strdup(saddr2str(iph2->src)); | |
1046 | plog(LLV_INFO, LOCATION, NULL, | |
1047 | "respond new phase 2 negotiation: %s<=>%s\n", | |
1048 | a, saddr2str(iph2->dst)); | |
1049 | racoon_free(a); | |
1050 | } | |
1051 | ||
1052 | #ifdef ENABLE_STATS | |
1053 | gettimeofday(&start, NULL); | |
1054 | #endif | |
1055 | ||
1056 | error = (ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)] | |
1057 | [iph2->side] | |
1058 | [iph2->status])(iph2, msg); | |
1059 | if (error != 0) { | |
1060 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1061 | "failed to pre-process packet.\n"); | |
1062 | if (error != ISAKMP_INTERNAL_ERROR) | |
1063 | isakmp_info_send_n1(iph2->ph1, error, NULL); | |
1064 | /* | |
1065 | * release handler because it's wrong that ph2handle is kept | |
1066 | * after failed to check message for responder's. | |
1067 | */ | |
1068 | unbindph12(iph2); | |
1069 | remph2(iph2); | |
1070 | delph2(iph2); | |
1071 | return -1; | |
1072 | } | |
1073 | ||
1074 | /* send */ | |
1075 | plog(LLV_DEBUG, LOCATION, NULL, "===\n"); | |
1076 | if ((ph2exchange[etypesw2(isakmp->etype)] | |
1077 | [iph2->side] | |
1078 | [iph2->status])(iph2, msg) < 0) { | |
1079 | plog(LLV_ERROR, LOCATION, iph2->ph1->remote, | |
1080 | "failed to process packet.\n"); | |
1081 | /* don't release handler */ | |
1082 | return -1; | |
1083 | } | |
1084 | #ifdef ENABLE_STATS | |
1085 | gettimeofday(&end, NULL); | |
1086 | syslog(LOG_NOTICE, "%s(%s): %8.6f", | |
1087 | "phase2", | |
1088 | s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status), | |
1089 | timedelta(&start, &end)); | |
1090 | #endif | |
1091 | ||
1092 | return 0; | |
1093 | } | |
1094 | ||
1095 | /* | |
1096 | * parse ISAKMP payloads, without ISAKMP base header. | |
1097 | */ | |
1098 | vchar_t * | |
1099 | isakmp_parsewoh(np0, gen, len) | |
1100 | int np0; | |
1101 | struct isakmp_gen *gen; | |
1102 | int len; | |
1103 | { | |
1104 | u_char np = np0 & 0xff; | |
1105 | int tlen, plen; | |
1106 | vchar_t *result; | |
1107 | struct isakmp_parse_t *p, *ep; | |
1108 | ||
1109 | plog(LLV_DEBUG, LOCATION, NULL, "begin.\n"); | |
1110 | ||
1111 | /* | |
1112 | * 5 is a magic number, but any value larger than 2 should be fine | |
1113 | * as we do vrealloc() in the following loop. | |
1114 | */ | |
1115 | result = vmalloc(sizeof(struct isakmp_parse_t) * 5); | |
1116 | if (result == NULL) { | |
1117 | plog(LLV_ERROR, LOCATION, NULL, | |
1118 | "failed to get buffer.\n"); | |
1119 | return NULL; | |
1120 | } | |
1121 | p = (struct isakmp_parse_t *)result->v; | |
1122 | ep = (struct isakmp_parse_t *)(result->v + result->l - sizeof(*ep)); | |
1123 | ||
1124 | tlen = len; | |
1125 | ||
1126 | /* parse through general headers */ | |
1127 | while (0 < tlen && np != ISAKMP_NPTYPE_NONE) { | |
1128 | if (tlen <= sizeof(struct isakmp_gen)) { | |
1129 | /* don't send information, see isakmp_ident_r1() */ | |
1130 | plog(LLV_ERROR, LOCATION, NULL, | |
1131 | "invalid length of payload\n"); | |
1132 | vfree(result); | |
1133 | return NULL; | |
1134 | } | |
1135 | ||
1136 | plog(LLV_DEBUG, LOCATION, NULL, | |
1137 | "seen nptype=%u(%s)\n", np, s_isakmp_nptype(np)); | |
1138 | ||
1139 | p->type = np; | |
1140 | p->len = ntohs(gen->len); | |
1141 | if (p->len == 0 || p->len > tlen) { | |
1142 | plog(LLV_DEBUG, LOCATION, NULL, | |
1143 | "invalid length of payload\n"); | |
1144 | vfree(result); | |
1145 | return NULL; | |
1146 | } | |
1147 | p->ptr = gen; | |
1148 | p++; | |
1149 | if (ep <= p) { | |
1150 | int off; | |
1151 | ||
1152 | off = p - (struct isakmp_parse_t *)result->v; | |
1153 | result = vrealloc(result, result->l * 2); | |
1154 | if (result == NULL) { | |
1155 | plog(LLV_DEBUG, LOCATION, NULL, | |
1156 | "failed to realloc buffer.\n"); | |
1157 | vfree(result); | |
1158 | return NULL; | |
1159 | } | |
1160 | ep = (struct isakmp_parse_t *) | |
1161 | (result->v + result->l - sizeof(*ep)); | |
1162 | p = (struct isakmp_parse_t *)result->v; | |
1163 | p += off; | |
1164 | } | |
1165 | ||
1166 | np = gen->np; | |
1167 | plen = ntohs(gen->len); | |
1168 | gen = (struct isakmp_gen *)((caddr_t)gen + plen); | |
1169 | tlen -= plen; | |
1170 | } | |
1171 | p->type = ISAKMP_NPTYPE_NONE; | |
1172 | p->len = 0; | |
1173 | p->ptr = NULL; | |
1174 | ||
1175 | plog(LLV_DEBUG, LOCATION, NULL, "succeed.\n"); | |
1176 | ||
1177 | return result; | |
1178 | } | |
1179 | ||
1180 | /* | |
1181 | * parse ISAKMP payloads, including ISAKMP base header. | |
1182 | */ | |
1183 | vchar_t * | |
1184 | isakmp_parse(buf) | |
1185 | vchar_t *buf; | |
1186 | { | |
1187 | struct isakmp *isakmp = (struct isakmp *)buf->v; | |
1188 | struct isakmp_gen *gen; | |
1189 | int tlen; | |
1190 | vchar_t *result; | |
1191 | u_char np; | |
1192 | ||
1193 | np = isakmp->np; | |
1194 | gen = (struct isakmp_gen *)(buf->v + sizeof(*isakmp)); | |
1195 | tlen = buf->l - sizeof(struct isakmp); | |
1196 | result = isakmp_parsewoh(np, gen, tlen); | |
1197 | ||
1198 | return result; | |
1199 | } | |
1200 | ||
1201 | /* %%% */ | |
1202 | int | |
1203 | isakmp_init() | |
1204 | { | |
1205 | /* initialize a isakmp status table */ | |
1206 | initph1tree(); | |
1207 | initph2tree(); | |
1208 | initctdtree(); | |
1209 | init_recvdpkt(); | |
1210 | ||
1211 | srandom(time(0)); | |
1212 | ||
1213 | if (isakmp_open() < 0) | |
1214 | goto err; | |
1215 | ||
1216 | return(0); | |
1217 | ||
1218 | err: | |
1219 | isakmp_close(); | |
1220 | return(-1); | |
1221 | } | |
1222 | ||
1223 | /* | |
1224 | * make strings containing i_cookie + r_cookie + msgid | |
1225 | */ | |
1226 | const char * | |
1227 | isakmp_pindex(index, msgid) | |
1228 | const isakmp_index *index; | |
1229 | const u_int32_t msgid; | |
1230 | { | |
1231 | static char buf[64]; | |
1232 | const u_char *p; | |
1233 | int i, j; | |
1234 | ||
1235 | memset(buf, 0, sizeof(buf)); | |
1236 | ||
1237 | /* copy index */ | |
1238 | p = (const u_char *)index; | |
1239 | for (j = 0, i = 0; i < sizeof(isakmp_index); i++) { | |
1240 | snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]); | |
1241 | j += 2; | |
1242 | switch (i) { | |
1243 | case 7: | |
1244 | buf[j++] = ':'; | |
1245 | } | |
1246 | } | |
1247 | ||
1248 | if (msgid == 0) | |
1249 | return buf; | |
1250 | ||
1251 | /* copy msgid */ | |
1252 | snprintf((char *)&buf[j], sizeof(buf) - j, ":%08x", ntohs(msgid)); | |
1253 | ||
1254 | return buf; | |
1255 | } | |
1256 | ||
1257 | /* open ISAKMP sockets. */ | |
1258 | int | |
1259 | isakmp_open() | |
1260 | { | |
1261 | const int yes = 1; | |
1262 | int ifnum; | |
1263 | #ifdef INET6 | |
1264 | int pktinfo; | |
1265 | #endif | |
1266 | struct myaddrs *p; | |
1267 | ||
1268 | ifnum = 0; | |
1269 | for (p = lcconf->myaddrs; p; p = p->next) { | |
1270 | if (!p->addr) | |
1271 | continue; | |
1272 | ||
1273 | /* warn if wildcard address - should we forbid this? */ | |
1274 | switch (p->addr->sa_family) { | |
1275 | case AF_INET: | |
1276 | if (((struct sockaddr_in *)p->addr)->sin_addr.s_addr == 0) | |
1277 | plog(LLV_WARNING, LOCATION, NULL, | |
1278 | "listening to wildcard address," | |
1279 | "broadcast IKE packet may kill you\n"); | |
1280 | break; | |
1281 | #ifdef INET6 | |
1282 | case AF_INET6: | |
1283 | if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)p->addr)->sin6_addr)) | |
1284 | plog(LLV_WARNING, LOCATION, NULL, | |
1285 | "listening to wildcard address, " | |
1286 | "broadcast IKE packet may kill you\n"); | |
1287 | break; | |
1288 | #endif | |
1289 | default: | |
1290 | plog(LLV_ERROR, LOCATION, NULL, | |
1291 | "unsupported address family %d\n", | |
1292 | lcconf->default_af); | |
1293 | goto err_and_next; | |
1294 | } | |
1295 | ||
1296 | if ((p->sock = socket(p->addr->sa_family, SOCK_DGRAM, 0)) < 0) { | |
1297 | plog(LLV_ERROR, LOCATION, NULL, | |
1298 | "socket (%s)\n", strerror(errno)); | |
1299 | goto err_and_next; | |
1300 | } | |
1301 | ||
1302 | /* receive my interface address on inbound packets. */ | |
1303 | switch (p->addr->sa_family) { | |
1304 | case AF_INET: | |
1305 | if (setsockopt(p->sock, IPPROTO_IP, IP_RECVDSTADDR, | |
1306 | (const void *)&yes, sizeof(yes)) < 0) { | |
1307 | plog(LLV_ERROR, LOCATION, NULL, | |
1308 | "setsockopt (%s)\n", strerror(errno)); | |
1309 | goto err_and_next; | |
1310 | } | |
1311 | break; | |
1312 | #ifdef INET6 | |
1313 | case AF_INET6: | |
1314 | #ifdef ADVAPI | |
1315 | #ifdef IPV6_RECVPKTINFO | |
1316 | pktinfo = IPV6_RECVPKTINFO; | |
1317 | #else /* old adv. API */ | |
1318 | pktinfo = IPV6_PKTINFO; | |
1319 | #endif /* IPV6_RECVPKTINFO */ | |
1320 | #else | |
1321 | pktinfo = IPV6_RECVDSTADDR; | |
1322 | #endif | |
1323 | if (setsockopt(p->sock, IPPROTO_IPV6, pktinfo, | |
1324 | (const void *)&yes, sizeof(yes)) < 0) | |
1325 | { | |
1326 | plog(LLV_ERROR, LOCATION, NULL, | |
1327 | "setsockopt(%d): %s\n", | |
1328 | pktinfo, strerror(errno)); | |
1329 | goto err_and_next; | |
1330 | } | |
1331 | break; | |
1332 | #endif | |
1333 | } | |
1334 | ||
1335 | #ifdef IPV6_USE_MIN_MTU | |
1336 | if (p->addr->sa_family == AF_INET6 && | |
1337 | setsockopt(p->sock, IPPROTO_IPV6, IPV6_USE_MIN_MTU, | |
1338 | (void *)&yes, sizeof(yes)) < 0) { | |
1339 | plog(LLV_ERROR, LOCATION, NULL, | |
1340 | "setsockopt (%s)\n", strerror(errno)); | |
1341 | return -1; | |
1342 | } | |
1343 | #endif | |
1344 | ||
1345 | if (setsockopt_bypass(p->sock, p->addr->sa_family) < 0) | |
1346 | goto err_and_next; | |
1347 | ||
1348 | if (bind(p->sock, p->addr, p->addr->sa_len) < 0) { | |
1349 | plog(LLV_ERROR, LOCATION, p->addr, | |
1350 | "failed to bind (%s).\n", strerror(errno)); | |
1351 | close(p->sock); | |
1352 | goto err_and_next; | |
1353 | } | |
1354 | ||
1355 | ifnum++; | |
1356 | ||
1357 | plog(LLV_INFO, LOCATION, NULL, | |
1358 | "%s used as isakmp port (fd=%d)\n", | |
1359 | saddr2str(p->addr), p->sock); | |
1360 | ||
1361 | continue; | |
1362 | ||
1363 | err_and_next: | |
1364 | racoon_free(p->addr); | |
1365 | p->addr = NULL; | |
1366 | if (! lcconf->autograbaddr && lcconf->strict_address) | |
1367 | return -1; | |
1368 | continue; | |
1369 | } | |
1370 | ||
1371 | if (!ifnum) { | |
1372 | plog(LLV_ERROR, LOCATION, NULL, | |
1373 | "no address could be bound.\n"); | |
1374 | return -1; | |
1375 | } | |
1376 | ||
1377 | return 0; | |
1378 | } | |
1379 | ||
1380 | void | |
1381 | isakmp_close() | |
1382 | { | |
1383 | struct myaddrs *p, *next; | |
1384 | ||
1385 | for (p = lcconf->myaddrs; p; p = next) { | |
1386 | next = p->next; | |
1387 | ||
1388 | if (!p->addr) | |
1389 | continue; | |
1390 | close(p->sock); | |
1391 | racoon_free(p->addr); | |
1392 | racoon_free(p); | |
1393 | } | |
1394 | ||
1395 | lcconf->myaddrs = NULL; | |
1396 | } | |
1397 | ||
1398 | int | |
1399 | isakmp_send(iph1, sbuf) | |
1400 | struct ph1handle *iph1; | |
1401 | vchar_t *sbuf; | |
1402 | { | |
1403 | int len = 0; | |
1404 | int s; | |
1405 | ||
1406 | /* select the socket to be sent */ | |
1407 | s = getsockmyaddr(iph1->local); | |
1408 | if (s == -1) | |
1409 | return -1; | |
1410 | ||
1411 | len = sendfromto(s, sbuf->v, sbuf->l, | |
1412 | iph1->local, iph1->remote, lcconf->count_persend); | |
1413 | if (len == -1) { | |
1414 | plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n"); | |
1415 | return -1; | |
1416 | } | |
1417 | ||
1418 | return 0; | |
1419 | } | |
1420 | ||
1421 | /* called from scheduler */ | |
1422 | void | |
1423 | isakmp_ph1resend_stub(p) | |
1424 | void *p; | |
1425 | { | |
1426 | (void)isakmp_ph1resend((struct ph1handle *)p); | |
1427 | } | |
1428 | ||
1429 | int | |
1430 | isakmp_ph1resend(iph1) | |
1431 | struct ph1handle *iph1; | |
1432 | { | |
1433 | if (iph1->retry_counter < 0) { | |
1434 | plog(LLV_ERROR, LOCATION, NULL, | |
1435 | "phase1 negotiation failed due to time up. %s\n", | |
1436 | isakmp_pindex(&iph1->index, iph1->msgid)); | |
1437 | ||
1438 | remph1(iph1); | |
1439 | delph1(iph1); | |
1440 | return -1; | |
1441 | } | |
1442 | ||
1443 | if (isakmp_send(iph1, iph1->sendbuf) < 0) | |
1444 | return -1; | |
1445 | ||
1446 | plog(LLV_DEBUG, LOCATION, NULL, | |
1447 | "resend phase1 packet %s\n", | |
1448 | isakmp_pindex(&iph1->index, iph1->msgid)); | |
1449 | ||
1450 | iph1->retry_counter--; | |
1451 | ||
1452 | iph1->scr = sched_new(iph1->rmconf->retry_interval, | |
1453 | isakmp_ph1resend_stub, iph1); | |
1454 | ||
1455 | return 0; | |
1456 | } | |
1457 | ||
1458 | /* called from scheduler */ | |
1459 | void | |
1460 | isakmp_ph2resend_stub(p) | |
1461 | void *p; | |
1462 | { | |
1463 | ||
1464 | (void)isakmp_ph2resend((struct ph2handle *)p); | |
1465 | } | |
1466 | ||
1467 | int | |
1468 | isakmp_ph2resend(iph2) | |
1469 | struct ph2handle *iph2; | |
1470 | { | |
1471 | if (iph2->retry_counter < 0) { | |
1472 | plog(LLV_ERROR, LOCATION, NULL, | |
1473 | "phase2 negotiation failed due to time up. %s\n", | |
1474 | isakmp_pindex(&iph2->ph1->index, iph2->msgid)); | |
1475 | unbindph12(iph2); | |
1476 | remph2(iph2); | |
1477 | delph2(iph2); | |
1478 | return -1; | |
1479 | } | |
1480 | ||
1481 | if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) | |
1482 | return -1; | |
1483 | ||
1484 | plog(LLV_DEBUG, LOCATION, NULL, | |
1485 | "resend phase2 packet %s\n", | |
1486 | isakmp_pindex(&iph2->ph1->index, iph2->msgid)); | |
1487 | ||
1488 | iph2->retry_counter--; | |
1489 | ||
1490 | iph2->scr = sched_new(iph2->ph1->rmconf->retry_interval, | |
1491 | isakmp_ph2resend_stub, iph2); | |
1492 | ||
1493 | return 0; | |
1494 | } | |
1495 | ||
1496 | /* called from scheduler */ | |
1497 | void | |
1498 | isakmp_ph1expire_stub(p) | |
1499 | void *p; | |
1500 | { | |
1501 | ||
1502 | isakmp_ph1expire((struct ph1handle *)p); | |
1503 | } | |
1504 | ||
1505 | void | |
1506 | isakmp_ph1expire(iph1) | |
1507 | struct ph1handle *iph1; | |
1508 | { | |
1509 | char *src, *dst; | |
1510 | ||
1511 | src = strdup(saddr2str(iph1->local)); | |
1512 | dst = strdup(saddr2str(iph1->remote)); | |
1513 | plog(LLV_INFO, LOCATION, NULL, | |
1514 | "ISAKMP-SA expired %s-%s spi:%s\n", | |
1515 | src, dst, | |
1516 | isakmp_pindex(&iph1->index, 0)); | |
1517 | racoon_free(src); | |
1518 | racoon_free(dst); | |
1519 | ||
1520 | SCHED_KILL(iph1->sce); | |
1521 | ||
1522 | iph1->status = PHASE1ST_EXPIRED; | |
1523 | ||
1524 | /* | |
1525 | * the phase1 deletion is postponed until there is no phase2. | |
1526 | */ | |
1527 | if (LIST_FIRST(&iph1->ph2tree) != NULL) { | |
1528 | iph1->sce = sched_new(1, isakmp_ph1expire_stub, iph1); | |
1529 | return; | |
1530 | } | |
1531 | ||
1532 | iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1); | |
1533 | } | |
1534 | ||
1535 | /* called from scheduler */ | |
1536 | void | |
1537 | isakmp_ph1delete_stub(p) | |
1538 | void *p; | |
1539 | { | |
1540 | ||
1541 | isakmp_ph1delete((struct ph1handle *)p); | |
1542 | } | |
1543 | ||
1544 | void | |
1545 | isakmp_ph1delete(iph1) | |
1546 | struct ph1handle *iph1; | |
1547 | { | |
1548 | char *src, *dst; | |
1549 | ||
1550 | SCHED_KILL(iph1->sce); | |
1551 | ||
1552 | if (LIST_FIRST(&iph1->ph2tree) != NULL) { | |
1553 | iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1); | |
1554 | return; | |
1555 | } | |
1556 | ||
1557 | /* don't re-negosiation when the phase 1 SA expires. */ | |
1558 | ||
1559 | src = strdup(saddr2str(iph1->local)); | |
1560 | dst = strdup(saddr2str(iph1->remote)); | |
1561 | plog(LLV_INFO, LOCATION, NULL, | |
1562 | "ISAKMP-SA deleted %s-%s spi:%s\n", | |
1563 | src, dst, isakmp_pindex(&iph1->index, 0)); | |
1564 | racoon_free(src); | |
1565 | racoon_free(dst); | |
1566 | ||
1567 | remph1(iph1); | |
1568 | delph1(iph1); | |
1569 | ||
1570 | return; | |
1571 | } | |
1572 | ||
1573 | /* called from scheduler. | |
1574 | * this function will call only isakmp_ph2delete(). | |
1575 | * phase 2 handler remain forever if kernel doesn't cry a expire of phase 2 SA | |
1576 | * by something cause. That's why this function is called after phase 2 SA | |
1577 | * expires in the userland. | |
1578 | */ | |
1579 | void | |
1580 | isakmp_ph2expire_stub(p) | |
1581 | void *p; | |
1582 | { | |
1583 | ||
1584 | isakmp_ph2expire((struct ph2handle *)p); | |
1585 | } | |
1586 | ||
1587 | void | |
1588 | isakmp_ph2expire(iph2) | |
1589 | struct ph2handle *iph2; | |
1590 | { | |
1591 | char *src, *dst; | |
1592 | ||
1593 | SCHED_KILL(iph2->sce); | |
1594 | ||
1595 | src = strdup(saddrwop2str(iph2->src)); | |
1596 | dst = strdup(saddrwop2str(iph2->dst)); | |
1597 | plog(LLV_INFO, LOCATION, NULL, | |
1598 | "phase2 sa expired %s-%s\n", src, dst); | |
1599 | racoon_free(src); | |
1600 | racoon_free(dst); | |
1601 | ||
1602 | iph2->status = PHASE2ST_EXPIRED; | |
1603 | ||
1604 | iph2->sce = sched_new(1, isakmp_ph2delete_stub, iph2); | |
1605 | ||
1606 | return; | |
1607 | } | |
1608 | ||
1609 | /* called from scheduler */ | |
1610 | void | |
1611 | isakmp_ph2delete_stub(p) | |
1612 | void *p; | |
1613 | { | |
1614 | ||
1615 | isakmp_ph2delete((struct ph2handle *)p); | |
1616 | } | |
1617 | ||
1618 | void | |
1619 | isakmp_ph2delete(iph2) | |
1620 | struct ph2handle *iph2; | |
1621 | { | |
1622 | char *src, *dst; | |
1623 | ||
1624 | SCHED_KILL(iph2->sce); | |
1625 | ||
1626 | src = strdup(saddrwop2str(iph2->src)); | |
1627 | dst = strdup(saddrwop2str(iph2->dst)); | |
1628 | plog(LLV_INFO, LOCATION, NULL, | |
1629 | "phase2 sa deleted %s-%s\n", src, dst); | |
1630 | racoon_free(src); | |
1631 | racoon_free(dst); | |
1632 | ||
1633 | unbindph12(iph2); | |
1634 | remph2(iph2); | |
1635 | delph2(iph2); | |
1636 | ||
1637 | return; | |
1638 | } | |
1639 | ||
1640 | /* \f%%% | |
1641 | * Interface between PF_KEYv2 and ISAKMP | |
1642 | */ | |
1643 | /* | |
1644 | * receive ACQUIRE from kernel, and begin either phase1 or phase2. | |
1645 | * if phase1 has been finished, begin phase2. | |
1646 | */ | |
1647 | int | |
1648 | isakmp_post_acquire(iph2) | |
1649 | struct ph2handle *iph2; | |
1650 | { | |
1651 | struct remoteconf *rmconf; | |
1652 | struct ph1handle *iph1 = NULL; | |
1653 | ||
1654 | /* search appropreate configuration with masking port. */ | |
1655 | rmconf = getrmconf(iph2->dst); | |
1656 | if (rmconf == NULL) { | |
1657 | plog(LLV_ERROR, LOCATION, NULL, | |
1658 | "no configuration found for %s.\n", | |
1659 | saddrwop2str(iph2->dst)); | |
1660 | return -1; | |
1661 | } | |
1662 | ||
1663 | /* if passive mode, ignore the acquire message */ | |
1664 | if (rmconf->passive) { | |
1665 | plog(LLV_DEBUG, LOCATION, NULL, | |
1666 | "because of passive mode, " | |
1667 | "ignore the acquire message for %s.\n", | |
1668 | saddrwop2str(iph2->dst)); | |
1669 | return 0; | |
1670 | } | |
1671 | ||
1672 | /* search isakmp status table by address with masking port */ | |
1673 | iph1 = getph1byaddr(iph2->src, iph2->dst); | |
1674 | ||
1675 | /* no ISAKMP-SA found. */ | |
1676 | if (iph1 == NULL) { | |
1677 | struct sched *sc; | |
1678 | ||
1679 | iph2->retry_checkph1 = lcconf->retry_checkph1; | |
1680 | sc = sched_new(1, isakmp_chkph1there_stub, iph2); | |
1681 | plog(LLV_INFO, LOCATION, NULL, | |
1682 | "IPsec-SA request for %s queued " | |
1683 | "due to no phase1 found.\n", | |
1684 | saddrwop2str(iph2->dst)); | |
1685 | ||
1686 | /* start phase 1 negotiation as a initiator. */ | |
1687 | if (isakmp_ph1begin_i(rmconf, iph2->dst) < 0) { | |
1688 | SCHED_KILL(sc); | |
1689 | return -1; | |
1690 | } | |
1691 | ||
1692 | return 0; | |
1693 | /*NOTREACHED*/ | |
1694 | } | |
1695 | ||
1696 | /* found ISAKMP-SA, but on negotiation. */ | |
1697 | if (iph1->status != PHASE1ST_ESTABLISHED) { | |
1698 | iph2->retry_checkph1 = lcconf->retry_checkph1; | |
1699 | sched_new(1, isakmp_chkph1there_stub, iph2); | |
1700 | plog(LLV_INFO, LOCATION, iph2->dst, | |
1701 | "request for establishing IPsec-SA was queued " | |
1702 | "due to no phase1 found.\n"); | |
1703 | return 0; | |
1704 | /*NOTREACHED*/ | |
1705 | } | |
1706 | ||
1707 | /* found established ISAKMP-SA */ | |
1708 | /* i.e. iph1->status == PHASE1ST_ESTABLISHED */ | |
1709 | ||
1710 | /* found ISAKMP-SA. */ | |
1711 | plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n"); | |
1712 | ||
1713 | /* begin quick mode */ | |
1714 | if (isakmp_ph2begin_i(iph1, iph2)) | |
1715 | return -1; | |
1716 | ||
1717 | return 0; | |
1718 | } | |
1719 | ||
1720 | /* | |
1721 | * receive GETSPI from kernel. | |
1722 | */ | |
1723 | int | |
1724 | isakmp_post_getspi(iph2) | |
1725 | struct ph2handle *iph2; | |
1726 | { | |
1727 | #ifdef ENABLE_STATS | |
1728 | struct timeval start, end; | |
1729 | #endif | |
1730 | ||
1731 | /* don't process it because there is no suitable phase1-sa. */ | |
1732 | if (iph2->ph1->status == PHASE2ST_EXPIRED) { | |
1733 | plog(LLV_ERROR, LOCATION, iph2->ph1->remote, | |
1734 | "the negotiation is stopped, " | |
1735 | "because there is no suitable ISAKMP-SA.\n"); | |
1736 | return -1; | |
1737 | } | |
1738 | ||
1739 | #ifdef ENABLE_STATS | |
1740 | gettimeofday(&start, NULL); | |
1741 | #endif | |
1742 | if ((ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)] | |
1743 | [iph2->side] | |
1744 | [iph2->status])(iph2, NULL) != 0) | |
1745 | return -1; | |
1746 | #ifdef ENABLE_STATS | |
1747 | gettimeofday(&end, NULL); | |
1748 | syslog(LOG_NOTICE, "%s(%s): %8.6f", | |
1749 | "phase2", | |
1750 | s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status), | |
1751 | timedelta(&start, &end)); | |
1752 | #endif | |
1753 | ||
1754 | return 0; | |
1755 | } | |
1756 | ||
1757 | /* called by scheduler */ | |
1758 | void | |
1759 | isakmp_chkph1there_stub(p) | |
1760 | void *p; | |
1761 | { | |
1762 | isakmp_chkph1there((struct ph2handle *)p); | |
1763 | } | |
1764 | ||
1765 | void | |
1766 | isakmp_chkph1there(iph2) | |
1767 | struct ph2handle *iph2; | |
1768 | { | |
1769 | struct ph1handle *iph1; | |
1770 | ||
1771 | iph2->retry_checkph1--; | |
1772 | if (iph2->retry_checkph1 < 0) { | |
1773 | plog(LLV_ERROR, LOCATION, iph2->dst, | |
1774 | "phase2 negotiation failed " | |
1775 | "due to time up waiting for phase1. %s\n", | |
1776 | sadbsecas2str(iph2->dst, iph2->src, | |
1777 | iph2->satype, 0, 0)); | |
1778 | plog(LLV_INFO, LOCATION, NULL, | |
1779 | "delete phase 2 handler.\n"); | |
1780 | ||
1781 | /* send acquire to kernel as error */ | |
1782 | pk_sendeacquire(iph2); | |
1783 | ||
1784 | unbindph12(iph2); | |
1785 | remph2(iph2); | |
1786 | delph2(iph2); | |
1787 | ||
1788 | return; | |
1789 | } | |
1790 | ||
1791 | iph1 = getph1byaddr(iph2->src, iph2->dst); | |
1792 | ||
1793 | /* XXX Even if ph1 as responder is there, should we not start | |
1794 | * phase 2 negotiation ? */ | |
1795 | if (iph1 != NULL | |
1796 | && iph1->status == PHASE1ST_ESTABLISHED) { | |
1797 | /* found isakmp-sa */ | |
1798 | /* begin quick mode */ | |
1799 | (void)isakmp_ph2begin_i(iph1, iph2); | |
1800 | return; | |
1801 | } | |
1802 | ||
1803 | /* no isakmp-sa found */ | |
1804 | sched_new(1, isakmp_chkph1there_stub, iph2); | |
1805 | ||
1806 | return; | |
1807 | } | |
1808 | ||
1809 | /* copy variable data into ALLOCATED buffer. */ | |
1810 | caddr_t | |
1811 | isakmp_set_attr_v(buf, type, val, len) | |
1812 | caddr_t buf; | |
1813 | int type; | |
1814 | caddr_t val; | |
1815 | int len; | |
1816 | { | |
1817 | struct isakmp_data *data; | |
1818 | ||
1819 | data = (struct isakmp_data *)buf; | |
1820 | data->type = htons((u_int16_t)type | ISAKMP_GEN_TLV); | |
1821 | data->lorv = htons((u_int16_t)len); | |
1822 | memcpy(data + 1, val, len); | |
1823 | ||
1824 | return buf + sizeof(*data) + len; | |
1825 | } | |
1826 | ||
1827 | /* copy fixed length data into ALLOCATED buffer. */ | |
1828 | caddr_t | |
1829 | isakmp_set_attr_l(buf, type, val) | |
1830 | caddr_t buf; | |
1831 | int type; | |
1832 | u_int32_t val; | |
1833 | { | |
1834 | struct isakmp_data *data; | |
1835 | ||
1836 | data = (struct isakmp_data *)buf; | |
1837 | data->type = htons((u_int16_t)type | ISAKMP_GEN_TV); | |
1838 | data->lorv = htons((u_int16_t)val); | |
1839 | ||
1840 | return buf + sizeof(*data); | |
1841 | } | |
1842 | ||
1843 | /* add a variable data attribute to the buffer by reallocating it. */ | |
1844 | vchar_t * | |
1845 | isakmp_add_attr_v(buf0, type, val, len) | |
1846 | vchar_t *buf0; | |
1847 | int type; | |
1848 | caddr_t val; | |
1849 | int len; | |
1850 | { | |
1851 | vchar_t *buf = NULL; | |
1852 | struct isakmp_data *data; | |
1853 | int tlen; | |
1854 | int oldlen = 0; | |
1855 | ||
1856 | tlen = sizeof(*data) + len; | |
1857 | ||
1858 | if (buf0) { | |
1859 | oldlen = buf0->l; | |
1860 | buf = vrealloc(buf0, oldlen + tlen); | |
1861 | } else | |
1862 | buf = vmalloc(tlen); | |
1863 | if (!buf) { | |
1864 | plog(LLV_ERROR, LOCATION, NULL, | |
1865 | "failed to get a attribute buffer.\n"); | |
1866 | return NULL; | |
1867 | } | |
1868 | ||
1869 | data = (struct isakmp_data *)(buf->v + oldlen); | |
1870 | data->type = htons((u_int16_t)type | ISAKMP_GEN_TLV); | |
1871 | data->lorv = htons((u_int16_t)len); | |
1872 | memcpy(data + 1, val, len); | |
1873 | ||
1874 | return buf; | |
1875 | } | |
1876 | ||
1877 | /* add a fixed data attribute to the buffer by reallocating it. */ | |
1878 | vchar_t * | |
1879 | isakmp_add_attr_l(buf0, type, val) | |
1880 | vchar_t *buf0; | |
1881 | int type; | |
1882 | u_int32_t val; | |
1883 | { | |
1884 | vchar_t *buf = NULL; | |
1885 | struct isakmp_data *data; | |
1886 | int tlen; | |
1887 | int oldlen = 0; | |
1888 | ||
1889 | tlen = sizeof(*data); | |
1890 | ||
1891 | if (buf0) { | |
1892 | oldlen = buf0->l; | |
1893 | buf = vrealloc(buf0, oldlen + tlen); | |
1894 | } else | |
1895 | buf = vmalloc(tlen); | |
1896 | if (!buf) { | |
1897 | plog(LLV_ERROR, LOCATION, NULL, | |
1898 | "failed to get a attribute buffer.\n"); | |
1899 | return NULL; | |
1900 | } | |
1901 | ||
1902 | data = (struct isakmp_data *)(buf->v + oldlen); | |
1903 | data->type = htons((u_int16_t)type | ISAKMP_GEN_TV); | |
1904 | data->lorv = htons((u_int16_t)val); | |
1905 | ||
1906 | return buf; | |
1907 | } | |
1908 | ||
1909 | /* | |
1910 | * calculate cookie and set. | |
1911 | */ | |
1912 | int | |
1913 | isakmp_newcookie(place, remote, local) | |
1914 | caddr_t place; | |
1915 | struct sockaddr *remote; | |
1916 | struct sockaddr *local; | |
1917 | { | |
1918 | vchar_t *buf = NULL, *buf2 = NULL; | |
1919 | char *p; | |
1920 | int blen; | |
1921 | int alen; | |
1922 | caddr_t sa1, sa2; | |
1923 | time_t t; | |
1924 | int error = -1; | |
1925 | u_short port; | |
1926 | ||
1927 | ||
1928 | if (remote->sa_family != local->sa_family) { | |
1929 | plog(LLV_ERROR, LOCATION, NULL, | |
1930 | "address family mismatch, remote:%d local:%d\n", | |
1931 | remote->sa_family, local->sa_family); | |
1932 | goto end; | |
1933 | } | |
1934 | switch (remote->sa_family) { | |
1935 | case AF_INET: | |
1936 | alen = sizeof(struct in_addr); | |
1937 | sa1 = (caddr_t)&((struct sockaddr_in *)remote)->sin_addr; | |
1938 | sa2 = (caddr_t)&((struct sockaddr_in *)local)->sin_addr; | |
1939 | break; | |
1940 | #ifdef INET6 | |
1941 | case AF_INET6: | |
1942 | alen = sizeof(struct in_addr); | |
1943 | sa1 = (caddr_t)&((struct sockaddr_in6 *)remote)->sin6_addr; | |
1944 | sa2 = (caddr_t)&((struct sockaddr_in6 *)local)->sin6_addr; | |
1945 | break; | |
1946 | #endif | |
1947 | default: | |
1948 | plog(LLV_ERROR, LOCATION, NULL, | |
1949 | "invalid family: %d\n", remote->sa_family); | |
1950 | goto end; | |
1951 | } | |
1952 | blen = (alen + sizeof(u_short)) * 2 | |
1953 | + sizeof(time_t) + lcconf->secret_size; | |
1954 | buf = vmalloc(blen); | |
1955 | if (buf == NULL) { | |
1956 | plog(LLV_ERROR, LOCATION, NULL, | |
1957 | "failed to get a cookie.\n"); | |
1958 | goto end; | |
1959 | } | |
1960 | p = buf->v; | |
1961 | ||
1962 | /* copy my address */ | |
1963 | memcpy(p, sa1, alen); | |
1964 | p += alen; | |
1965 | port = ((struct sockaddr_in *)remote)->sin_port; | |
1966 | memcpy(p, &port, sizeof(u_short)); | |
1967 | p += sizeof(u_short); | |
1968 | ||
1969 | /* copy target address */ | |
1970 | memcpy(p, sa2, alen); | |
1971 | p += alen; | |
1972 | port = ((struct sockaddr_in *)local)->sin_port; | |
1973 | memcpy(p, &port, sizeof(u_short)); | |
1974 | p += sizeof(u_short); | |
1975 | ||
1976 | /* copy time */ | |
1977 | t = time(0); | |
1978 | memcpy(p, (caddr_t)&t, sizeof(t)); | |
1979 | p += sizeof(t); | |
1980 | ||
1981 | /* copy random value */ | |
1982 | buf2 = eay_set_random(lcconf->secret_size); | |
1983 | if (buf2 == NULL) | |
1984 | goto end; | |
1985 | memcpy(p, buf2->v, lcconf->secret_size); | |
1986 | p += lcconf->secret_size; | |
1987 | vfree(buf2); | |
1988 | ||
1989 | buf2 = eay_sha1_one(buf); | |
1990 | memcpy(place, buf2->v, sizeof(cookie_t)); | |
1991 | ||
1992 | sa1 = val2str(place, sizeof (cookie_t)); | |
1993 | plog(LLV_DEBUG, LOCATION, NULL, "new cookie:\n%s\n", sa1); | |
1994 | racoon_free(sa1); | |
1995 | ||
1996 | error = 0; | |
1997 | end: | |
1998 | if (buf != NULL) | |
1999 | vfree(buf); | |
2000 | if (buf2 != NULL) | |
2001 | vfree(buf2); | |
2002 | return error; | |
2003 | } | |
2004 | ||
2005 | /* | |
2006 | * save partner's(payload) data into phhandle. | |
2007 | */ | |
2008 | int | |
2009 | isakmp_p2ph(buf, gen) | |
2010 | vchar_t **buf; | |
2011 | struct isakmp_gen *gen; | |
2012 | { | |
2013 | /* XXX to be checked in each functions for logging. */ | |
2014 | if (*buf) { | |
2015 | plog(LLV_WARNING, LOCATION, NULL, | |
2016 | "ignore this payload, same payload type exist.\n"); | |
2017 | return -1; | |
2018 | } | |
2019 | ||
2020 | *buf = vmalloc(ntohs(gen->len) - sizeof(*gen)); | |
2021 | if (*buf == NULL) { | |
2022 | plog(LLV_ERROR, LOCATION, NULL, | |
2023 | "failed to get buffer.\n"); | |
2024 | return -1; | |
2025 | } | |
2026 | memcpy((*buf)->v, gen + 1, (*buf)->l); | |
2027 | ||
2028 | return 0; | |
2029 | } | |
2030 | ||
2031 | u_int32_t | |
2032 | isakmp_newmsgid2(iph1) | |
2033 | struct ph1handle *iph1; | |
2034 | { | |
2035 | u_int32_t msgid2; | |
2036 | ||
2037 | do { | |
2038 | msgid2 = random(); | |
2039 | } while (getph2bymsgid(iph1, msgid2)); | |
2040 | ||
2041 | return msgid2; | |
2042 | } | |
2043 | ||
2044 | /* | |
2045 | * set values into allocated buffer of isakmp header for phase 1 | |
2046 | */ | |
2047 | caddr_t | |
2048 | set_isakmp_header(vbuf, iph1, nptype) | |
2049 | vchar_t *vbuf; | |
2050 | struct ph1handle *iph1; | |
2051 | int nptype; | |
2052 | { | |
2053 | struct isakmp *isakmp; | |
2054 | ||
2055 | if (vbuf->l < sizeof(*isakmp)) | |
2056 | return NULL; | |
2057 | ||
2058 | isakmp = (struct isakmp *)vbuf->v; | |
2059 | memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t)); | |
2060 | memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t)); | |
2061 | isakmp->np = nptype; | |
2062 | isakmp->v = iph1->version; | |
2063 | isakmp->etype = iph1->etype; | |
2064 | isakmp->flags = iph1->flags; | |
2065 | isakmp->msgid = iph1->msgid; | |
2066 | isakmp->len = htonl(vbuf->l); | |
2067 | ||
2068 | return vbuf->v + sizeof(*isakmp); | |
2069 | } | |
2070 | ||
2071 | /* | |
2072 | * set values into allocated buffer of isakmp header for phase 2 | |
2073 | */ | |
2074 | caddr_t | |
2075 | set_isakmp_header2(vbuf, iph2, nptype) | |
2076 | vchar_t *vbuf; | |
2077 | struct ph2handle *iph2; | |
2078 | int nptype; | |
2079 | { | |
2080 | struct isakmp *isakmp; | |
2081 | ||
2082 | if (vbuf->l < sizeof(*isakmp)) | |
2083 | return NULL; | |
2084 | ||
2085 | isakmp = (struct isakmp *)vbuf->v; | |
2086 | memcpy(&isakmp->i_ck, &iph2->ph1->index.i_ck, sizeof(cookie_t)); | |
2087 | memcpy(&isakmp->r_ck, &iph2->ph1->index.r_ck, sizeof(cookie_t)); | |
2088 | isakmp->np = nptype; | |
2089 | isakmp->v = iph2->ph1->version; | |
2090 | isakmp->etype = ISAKMP_ETYPE_QUICK; | |
2091 | isakmp->flags = iph2->flags; | |
2092 | memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid)); | |
2093 | isakmp->len = htonl(vbuf->l); | |
2094 | ||
2095 | return vbuf->v + sizeof(*isakmp); | |
2096 | } | |
2097 | ||
2098 | /* | |
2099 | * set values into allocated buffer of isakmp payload. | |
2100 | */ | |
2101 | caddr_t | |
2102 | set_isakmp_payload(buf, src, nptype) | |
2103 | caddr_t buf; | |
2104 | vchar_t *src; | |
2105 | int nptype; | |
2106 | { | |
2107 | struct isakmp_gen *gen; | |
2108 | caddr_t p = buf; | |
2109 | ||
2110 | plog(LLV_DEBUG, LOCATION, NULL, "add payload of len %d, next type %d\n", | |
2111 | src->l, nptype); | |
2112 | ||
2113 | gen = (struct isakmp_gen *)p; | |
2114 | gen->np = nptype; | |
2115 | gen->len = htons(sizeof(*gen) + src->l); | |
2116 | p += sizeof(*gen); | |
2117 | memcpy(p, src->v, src->l); | |
2118 | p += src->l; | |
2119 | ||
2120 | return p; | |
2121 | } | |
2122 | ||
2123 | static int | |
2124 | etypesw1(etype) | |
2125 | int etype; | |
2126 | { | |
2127 | switch (etype) { | |
2128 | case ISAKMP_ETYPE_IDENT: | |
2129 | return 1; | |
2130 | case ISAKMP_ETYPE_AGG: | |
2131 | return 2; | |
2132 | case ISAKMP_ETYPE_BASE: | |
2133 | return 3; | |
2134 | default: | |
2135 | return 0; | |
2136 | } | |
2137 | /*NOTREACHED*/ | |
2138 | } | |
2139 | ||
2140 | static int | |
2141 | etypesw2(etype) | |
2142 | int etype; | |
2143 | { | |
2144 | switch (etype) { | |
2145 | case ISAKMP_ETYPE_QUICK: | |
2146 | return 1; | |
2147 | default: | |
2148 | return 0; | |
2149 | } | |
2150 | /*NOTREACHED*/ | |
2151 | } | |
2152 | ||
2153 | #ifdef HAVE_PRINT_ISAKMP_C | |
2154 | /* for print-isakmp.c */ | |
2155 | char *snapend; | |
2156 | extern void isakmp_print __P((const u_char *, u_int, const u_char *)); | |
2157 | ||
2158 | char *getname __P((const u_char *)); | |
2159 | #ifdef INET6 | |
2160 | char *getname6 __P((const u_char *)); | |
2161 | #endif | |
2162 | int safeputchar __P((int)); | |
2163 | ||
2164 | /* | |
2165 | * Return a name for the IP address pointed to by ap. This address | |
2166 | * is assumed to be in network byte order. | |
2167 | */ | |
2168 | char * | |
2169 | getname(ap) | |
2170 | const u_char *ap; | |
2171 | { | |
2172 | struct sockaddr_in addr; | |
2173 | static char ntop_buf[NI_MAXHOST]; | |
2174 | ||
2175 | memset(&addr, 0, sizeof(addr)); | |
2176 | addr.sin_len = sizeof(struct sockaddr_in); | |
2177 | addr.sin_family = AF_INET; | |
2178 | memcpy(&addr.sin_addr, ap, sizeof(addr.sin_addr)); | |
2179 | if (getnameinfo((struct sockaddr *)&addr, addr.sin_len, | |
2180 | ntop_buf, sizeof(ntop_buf), NULL, 0, | |
2181 | NI_NUMERICHOST | niflags)) | |
2182 | strncpy(ntop_buf, "?", sizeof(ntop_buf)); | |
2183 | ||
2184 | return ntop_buf; | |
2185 | } | |
2186 | ||
2187 | #ifdef INET6 | |
2188 | /* | |
2189 | * Return a name for the IP6 address pointed to by ap. This address | |
2190 | * is assumed to be in network byte order. | |
2191 | */ | |
2192 | char * | |
2193 | getname6(ap) | |
2194 | const u_char *ap; | |
2195 | { | |
2196 | struct sockaddr_in6 addr; | |
2197 | static char ntop_buf[NI_MAXHOST]; | |
2198 | ||
2199 | memset(&addr, 0, sizeof(addr)); | |
2200 | addr.sin6_len = sizeof(struct sockaddr_in6); | |
2201 | addr.sin6_family = AF_INET6; | |
2202 | memcpy(&addr.sin6_addr, ap, sizeof(addr.sin6_addr)); | |
2203 | if (getnameinfo((struct sockaddr *)&addr, addr.sin6_len, | |
2204 | ntop_buf, sizeof(ntop_buf), NULL, 0, | |
2205 | NI_NUMERICHOST | niflags)) | |
2206 | strncpy(ntop_buf, "?", sizeof(ntop_buf)); | |
2207 | ||
2208 | return ntop_buf; | |
2209 | } | |
2210 | #endif /* INET6 */ | |
2211 | ||
2212 | int | |
2213 | safeputchar(c) | |
2214 | int c; | |
2215 | { | |
2216 | unsigned char ch; | |
2217 | ||
2218 | ch = (unsigned char)(c & 0xff); | |
2219 | if (c < 0x80 && isprint(c)) | |
2220 | return printf("%c", c & 0xff); | |
2221 | else | |
2222 | return printf("\\%03o", c & 0xff); | |
2223 | } | |
2224 | ||
2225 | void | |
2226 | isakmp_printpacket(msg, from, my, decoded) | |
2227 | vchar_t *msg; | |
2228 | struct sockaddr *from; | |
2229 | struct sockaddr *my; | |
2230 | int decoded; | |
2231 | { | |
2232 | #ifdef YIPS_DEBUG | |
2233 | struct timeval tv; | |
2234 | int s; | |
2235 | char hostbuf[NI_MAXHOST]; | |
2236 | char portbuf[NI_MAXSERV]; | |
2237 | struct isakmp *isakmp; | |
2238 | vchar_t *buf; | |
2239 | #endif | |
2240 | ||
2241 | if (loglevel < LLV_DEBUG) | |
2242 | return; | |
2243 | ||
2244 | #ifdef YIPS_DEBUG | |
2245 | plog(LLV_DEBUG, LOCATION, NULL, "begin.\n"); | |
2246 | ||
2247 | gettimeofday(&tv, NULL); | |
2248 | s = tv.tv_sec % 3600; | |
2249 | printf("%02d:%02d.%06u ", s / 60, s % 60, (u_int32_t)tv.tv_usec); | |
2250 | ||
2251 | if (from) { | |
2252 | if (getnameinfo(from, from->sa_len, hostbuf, sizeof(hostbuf), | |
2253 | portbuf, sizeof(portbuf), | |
2254 | NI_NUMERICHOST | NI_NUMERICSERV | niflags)) { | |
2255 | strncpy(hostbuf, "?", sizeof(hostbuf)); | |
2256 | strncpy(portbuf, "?", sizeof(portbuf)); | |
2257 | } | |
2258 | printf("%s:%s", hostbuf, portbuf); | |
2259 | } else | |
2260 | printf("?"); | |
2261 | printf(" -> "); | |
2262 | if (my) { | |
2263 | if (getnameinfo(my, my->sa_len, hostbuf, sizeof(hostbuf), | |
2264 | portbuf, sizeof(portbuf), | |
2265 | NI_NUMERICHOST | NI_NUMERICSERV | niflags)) { | |
2266 | strncpy(hostbuf, "?", sizeof(hostbuf)); | |
2267 | strncpy(portbuf, "?", sizeof(portbuf)); | |
2268 | } | |
2269 | printf("%s:%s", hostbuf, portbuf); | |
2270 | } else | |
2271 | printf("?"); | |
2272 | printf(": "); | |
2273 | ||
2274 | buf = vdup(msg); | |
2275 | if (!buf) { | |
2276 | printf("(malloc fail)\n"); | |
2277 | return; | |
2278 | } | |
2279 | if (decoded) { | |
2280 | isakmp = (struct isakmp *)buf->v; | |
2281 | if (isakmp->flags & ISAKMP_FLAG_E) { | |
2282 | #if 0 | |
2283 | int pad; | |
2284 | pad = *(u_char *)(buf->v + buf->l - 1); | |
2285 | if (buf->l < pad && 2 < vflag) | |
2286 | printf("(wrong padding)"); | |
2287 | #endif | |
2288 | isakmp->flags &= ~ISAKMP_FLAG_E; | |
2289 | } | |
2290 | } | |
2291 | ||
2292 | snapend = buf->v + buf->l; | |
2293 | isakmp_print(buf->v, buf->l, NULL); | |
2294 | vfree(buf); | |
2295 | printf("\n"); | |
2296 | fflush(stdout); | |
2297 | ||
2298 | return; | |
2299 | #endif | |
2300 | } | |
2301 | #endif /*HAVE_PRINT_ISAKMP_C*/ | |
2302 | ||
2303 | int | |
2304 | copy_ph1addresses(iph1, rmconf, remote, local) | |
2305 | struct ph1handle *iph1; | |
2306 | struct remoteconf *rmconf; | |
2307 | struct sockaddr *remote, *local; | |
2308 | { | |
2309 | u_short *port = NULL; | |
2310 | ||
2311 | /* address portion must be grabbed from real remote address "remote" */ | |
2312 | iph1->remote = dupsaddr(remote); | |
2313 | if (iph1->remote == NULL) { | |
2314 | delph1(iph1); | |
2315 | return -1; | |
2316 | } | |
2317 | ||
2318 | /* | |
2319 | * if remote has no port # (in case of initiator - from ACQUIRE msg) | |
2320 | * - if remote.conf specifies port #, use that | |
2321 | * - if remote.conf does not, use 500 | |
2322 | * if remote has port # (in case of responder - from recvfrom(2)) | |
2323 | * respect content of "remote". | |
2324 | */ | |
2325 | switch (iph1->remote->sa_family) { | |
2326 | case AF_INET: | |
2327 | port = &((struct sockaddr_in *)iph1->remote)->sin_port; | |
2328 | if (*port) | |
2329 | break; | |
2330 | *port = ((struct sockaddr_in *)rmconf->remote)->sin_port; | |
2331 | if (*port) | |
2332 | break; | |
2333 | *port = htons(PORT_ISAKMP); | |
2334 | break; | |
2335 | #ifdef INET6 | |
2336 | case AF_INET6: | |
2337 | port = &((struct sockaddr_in6 *)iph1->remote)->sin6_port; | |
2338 | if (*port) | |
2339 | break; | |
2340 | *port = ((struct sockaddr_in6 *)rmconf->remote)->sin6_port; | |
2341 | if (*port) | |
2342 | break; | |
2343 | *port = htons(PORT_ISAKMP); | |
2344 | break; | |
2345 | #endif | |
2346 | default: | |
2347 | plog(LLV_ERROR, LOCATION, NULL, | |
2348 | "invalid family: %d\n", iph1->remote->sa_family); | |
2349 | return -1; | |
2350 | } | |
2351 | ||
2352 | if (local == NULL) | |
2353 | iph1->local = getlocaladdr(iph1->remote); | |
2354 | else | |
2355 | iph1->local = dupsaddr(local); | |
2356 | if (iph1->local == NULL) { | |
2357 | delph1(iph1); | |
2358 | return -1; | |
2359 | } | |
2360 | switch (iph1->local->sa_family) { | |
2361 | case AF_INET: | |
2362 | ((struct sockaddr_in *)iph1->local)->sin_port | |
2363 | = getmyaddrsport(iph1->local); | |
2364 | break; | |
2365 | #ifdef INET6 | |
2366 | case AF_INET6: | |
2367 | ((struct sockaddr_in6 *)iph1->local)->sin6_port | |
2368 | = getmyaddrsport(iph1->local); | |
2369 | break; | |
2370 | #endif | |
2371 | default: | |
2372 | plog(LLV_ERROR, LOCATION, NULL, | |
2373 | "invalid family: %d\n", iph1->remote->sa_family); | |
2374 | delph1(iph1); | |
2375 | return -1; | |
2376 | } | |
2377 | ||
2378 | return 0; | |
2379 | } | |
2380 | ||
2381 | static int | |
2382 | nostate1(iph1, msg) | |
2383 | struct ph1handle *iph1; | |
2384 | vchar_t *msg; | |
2385 | { | |
2386 | plog(LLV_ERROR, LOCATION, iph1->remote, "wrong state %u.\n", | |
2387 | iph1->status); | |
2388 | return -1; | |
2389 | } | |
2390 | ||
2391 | static int | |
2392 | nostate2(iph2, msg) | |
2393 | struct ph2handle *iph2; | |
2394 | vchar_t *msg; | |
2395 | { | |
2396 | plog(LLV_ERROR, LOCATION, iph2->ph1->remote, "wrong state %u.\n", | |
2397 | iph2->status); | |
2398 | return -1; | |
2399 | } | |
2400 | ||
2401 | void | |
2402 | log_ph1established(iph1) | |
2403 | const struct ph1handle *iph1; | |
2404 | { | |
2405 | char *src, *dst; | |
2406 | ||
2407 | src = strdup(saddr2str(iph1->local)); | |
2408 | dst = strdup(saddr2str(iph1->remote)); | |
2409 | plog(LLV_INFO, LOCATION, NULL, | |
2410 | "ISAKMP-SA established %s-%s spi:%s\n", | |
2411 | src, dst, | |
2412 | isakmp_pindex(&iph1->index, 0)); | |
2413 | racoon_free(src); | |
2414 | racoon_free(dst); | |
2415 | ||
2416 | return; | |
2417 | } | |
2418 |