]>
Commit | Line | Data |
---|---|---|
ac2f15b3 | 1 | /* $KAME: isakmp_ident.c,v 1.63 2001/12/12 17:57:26 sakane Exp $ */ |
7ba0088d A |
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 | /* Identity Protecion Exchange (Main Mode) */ | |
33 | ||
34 | #include <sys/types.h> | |
35 | #include <sys/param.h> | |
36 | ||
37 | #include <stdlib.h> | |
38 | #include <stdio.h> | |
39 | #include <string.h> | |
40 | #include <errno.h> | |
ac2f15b3 | 41 | #include <netinet/in.h> |
7ba0088d A |
42 | #if TIME_WITH_SYS_TIME |
43 | # include <sys/time.h> | |
44 | # include <time.h> | |
45 | #else | |
46 | # if HAVE_SYS_TIME_H | |
47 | # include <sys/time.h> | |
48 | # else | |
49 | # include <time.h> | |
50 | # endif | |
51 | #endif | |
52 | ||
53 | #include "var.h" | |
54 | #include "misc.h" | |
55 | #include "vmbuf.h" | |
56 | #include "plog.h" | |
57 | #include "sockmisc.h" | |
58 | #include "schedule.h" | |
59 | #include "debug.h" | |
60 | ||
61 | #include "localconf.h" | |
62 | #include "remoteconf.h" | |
63 | #include "isakmp_var.h" | |
64 | #include "isakmp.h" | |
65 | #include "oakley.h" | |
66 | #include "handler.h" | |
67 | #include "ipsec_doi.h" | |
68 | #include "crypto_openssl.h" | |
69 | #include "pfkey.h" | |
70 | #include "isakmp_ident.h" | |
71 | #include "isakmp_inf.h" | |
ac2f15b3 | 72 | #include "isakmp_natd.h" |
7ba0088d A |
73 | #include "vendorid.h" |
74 | ||
75 | #ifdef HAVE_GSSAPI | |
76 | #include "gssapi.h" | |
77 | #endif | |
78 | ||
79 | static vchar_t *ident_ir2mx __P((struct ph1handle *)); | |
80 | static vchar_t *ident_ir3mx __P((struct ph1handle *)); | |
81 | ||
82 | /* %%% | |
83 | * begin Identity Protection Mode as initiator. | |
84 | */ | |
85 | /* | |
86 | * send to responder | |
87 | * psk: HDR, SA | |
88 | * sig: HDR, SA | |
89 | * rsa: HDR, SA | |
90 | * rev: HDR, SA | |
91 | */ | |
92 | int | |
93 | ident_i1send(iph1, msg) | |
94 | struct ph1handle *iph1; | |
95 | vchar_t *msg; /* must be null */ | |
96 | { | |
97 | struct isakmp_gen *gen; | |
98 | caddr_t p; | |
99 | int tlen; | |
100 | int error = -1; | |
ffda1f4a A |
101 | vchar_t *vid_natt_rfc = NULL; |
102 | vchar_t *vid_natt_apple = NULL; | |
103 | vchar_t *vid_natt_02 = NULL; | |
104 | vchar_t *vid_natt_02N = NULL; | |
7ba0088d A |
105 | |
106 | /* validity check */ | |
107 | if (msg != NULL) { | |
108 | plog(LLV_ERROR, LOCATION, NULL, | |
109 | "msg has to be NULL in this function.\n"); | |
110 | goto end; | |
111 | } | |
112 | if (iph1->status != PHASE1ST_START) { | |
113 | plog(LLV_ERROR, LOCATION, NULL, | |
114 | "status mismatched %d.\n", iph1->status); | |
115 | goto end; | |
116 | } | |
117 | ||
118 | /* create isakmp index */ | |
119 | memset(&iph1->index, 0, sizeof(iph1->index)); | |
120 | isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local); | |
121 | ||
122 | /* create SA payload for my proposal */ | |
123 | iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal); | |
124 | if (iph1->sa == NULL) | |
125 | goto end; | |
126 | ||
127 | /* create buffer to send isakmp payload */ | |
128 | tlen = sizeof(struct isakmp) | |
129 | + sizeof(*gen) + iph1->sa->l; | |
130 | ||
ac2f15b3 | 131 | #ifdef IKE_NAT_T |
ffda1f4a A |
132 | vid_natt_rfc = set_vendorid(VENDORID_NATT_RFC); |
133 | vid_natt_apple = set_vendorid(VENDORID_NATT_APPLE); | |
134 | vid_natt_02 = set_vendorid(VENDORID_NATT_02); | |
135 | vid_natt_02N = set_vendorid(VENDORID_NATT_02N); | |
136 | ||
137 | if (vid_natt_rfc == NULL || | |
138 | vid_natt_apple == NULL || | |
139 | vid_natt_02 == NULL || | |
140 | vid_natt_02N == NULL) { | |
141 | plog(LLV_ERROR, LOCATION, NULL, | |
142 | "failed to get vendor ID buffer.\n"); | |
143 | goto end; | |
144 | } | |
145 | tlen += sizeof(*gen) + vid_natt_rfc->l; | |
146 | tlen += sizeof(*gen) + vid_natt_apple->l; | |
147 | tlen += sizeof(*gen) + vid_natt_02->l; | |
148 | tlen += sizeof(*gen) + vid_natt_02N->l; | |
ac2f15b3 A |
149 | #endif |
150 | ||
7ba0088d A |
151 | iph1->sendbuf = vmalloc(tlen); |
152 | if (iph1->sendbuf == NULL) { | |
153 | plog(LLV_ERROR, LOCATION, NULL, | |
154 | "failed to get buffer to send.\n"); | |
155 | goto end; | |
156 | } | |
157 | ||
158 | /* set isakmp header */ | |
159 | p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA); | |
160 | if (p == NULL) | |
161 | goto end; | |
162 | ||
163 | /* set SA payload to propose */ | |
ffda1f4a | 164 | p = set_isakmp_payload(p, iph1->sa, vid_natt_rfc ? ISAKMP_NPTYPE_VID : ISAKMP_NPTYPE_NONE); |
ac2f15b3 | 165 | |
ffda1f4a A |
166 | if (vid_natt_rfc) { |
167 | p = set_isakmp_payload(p, vid_natt_rfc, ISAKMP_NPTYPE_VID); | |
168 | p = set_isakmp_payload(p, vid_natt_apple, ISAKMP_NPTYPE_VID); | |
169 | p = set_isakmp_payload(p, vid_natt_02, ISAKMP_NPTYPE_VID); | |
170 | p = set_isakmp_payload(p, vid_natt_02N, ISAKMP_NPTYPE_NONE); | |
ac2f15b3 | 171 | } |
7ba0088d A |
172 | |
173 | #ifdef HAVE_PRINT_ISAKMP_C | |
174 | isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0); | |
175 | #endif | |
176 | ||
177 | /* send the packet, add to the schedule to resend */ | |
178 | iph1->retry_counter = iph1->rmconf->retry_counter; | |
179 | if (isakmp_ph1resend(iph1) == -1) | |
180 | goto end; | |
181 | ||
182 | iph1->status = PHASE1ST_MSG1SENT; | |
183 | ||
184 | error = 0; | |
185 | ||
186 | end: | |
ffda1f4a A |
187 | if (vid_natt_rfc) |
188 | vfree(vid_natt_rfc); | |
189 | if (vid_natt_apple) | |
190 | vfree(vid_natt_apple); | |
191 | if (vid_natt_02) | |
192 | vfree(vid_natt_02); | |
193 | if (vid_natt_02N) | |
194 | vfree(vid_natt_02N); | |
7ba0088d A |
195 | |
196 | return error; | |
197 | } | |
198 | ||
199 | /* | |
200 | * receive from responder | |
201 | * psk: HDR, SA | |
202 | * sig: HDR, SA | |
203 | * rsa: HDR, SA | |
204 | * rev: HDR, SA | |
205 | */ | |
206 | int | |
207 | ident_i2recv(iph1, msg) | |
208 | struct ph1handle *iph1; | |
209 | vchar_t *msg; | |
210 | { | |
211 | vchar_t *pbuf = NULL; | |
212 | struct isakmp_parse_t *pa; | |
213 | vchar_t *satmp = NULL; | |
214 | int error = -1; | |
215 | ||
216 | /* validity check */ | |
217 | if (iph1->status != PHASE1ST_MSG1SENT) { | |
218 | plog(LLV_ERROR, LOCATION, NULL, | |
219 | "status mismatched %d.\n", iph1->status); | |
220 | goto end; | |
221 | } | |
222 | ||
223 | /* validate the type of next payload */ | |
224 | /* | |
225 | * NOTE: RedCreek(as responder) attaches N[responder-lifetime] here, | |
226 | * if proposal-lifetime > lifetime-redcreek-wants. | |
227 | * (see doi-08 4.5.4) | |
228 | * => According to the seciton 4.6.3 in RFC 2407, This is illegal. | |
229 | * NOTE: we do not really care about ordering of VID and N. | |
230 | * does it matters? | |
231 | * NOTE: even if there's multiple VID/N, we'll ignore them. | |
232 | */ | |
233 | pbuf = isakmp_parse(msg); | |
234 | if (pbuf == NULL) | |
235 | goto end; | |
236 | pa = (struct isakmp_parse_t *)pbuf->v; | |
237 | ||
238 | /* SA payload is fixed postion */ | |
239 | if (pa->type != ISAKMP_NPTYPE_SA) { | |
240 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
241 | "received invalid next payload type %d, " | |
242 | "expecting %d.\n", | |
243 | pa->type, ISAKMP_NPTYPE_SA); | |
244 | goto end; | |
245 | } | |
246 | if (isakmp_p2ph(&satmp, pa->ptr) < 0) | |
247 | goto end; | |
248 | pa++; | |
249 | ||
250 | for (/*nothing*/; | |
251 | pa->type != ISAKMP_NPTYPE_NONE; | |
252 | pa++) { | |
253 | ||
254 | switch (pa->type) { | |
255 | case ISAKMP_NPTYPE_VID: | |
ac2f15b3 | 256 | #ifdef IKE_NAT_T |
ffda1f4a A |
257 | { |
258 | int vid = check_vendorid(pa->ptr); | |
259 | if (vid == VENDORID_NATT_RFC) | |
260 | iph1->natt_flags |= natt_type_rfc; | |
261 | else if (vid == VENDORID_NATT_APPLE) | |
262 | iph1->natt_flags |= natt_type_apple; | |
263 | else if (vid == VENDORID_NATT_02) | |
264 | iph1->natt_flags |= natt_type_02; | |
265 | else if (vid == VENDORID_NATT_02N) | |
266 | iph1->natt_flags |= natt_type_02N; | |
ac2f15b3 | 267 | } |
ffda1f4a | 268 | #endif |
7ba0088d A |
269 | break; |
270 | default: | |
271 | /* don't send information, see ident_r1recv() */ | |
272 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
273 | "ignore the packet, " | |
274 | "received unexpecting payload type %d.\n", | |
275 | pa->type); | |
276 | goto end; | |
277 | } | |
278 | } | |
279 | ||
ffda1f4a A |
280 | /* if natt vid(s) received - select type to use */ |
281 | natt_select_type(iph1); | |
282 | ||
7ba0088d A |
283 | /* check SA payload and set approval SA for use */ |
284 | if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) { | |
285 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
286 | "failed to get valid proposal.\n"); | |
287 | /* XXX send information */ | |
288 | goto end; | |
289 | } | |
290 | if (iph1->sa_ret) { | |
291 | vfree(iph1->sa_ret); | |
292 | iph1->sa_ret = NULL; | |
293 | } | |
294 | ||
295 | iph1->status = PHASE1ST_MSG2RECEIVED; | |
296 | ||
297 | error = 0; | |
298 | ||
299 | end: | |
300 | if (pbuf) | |
301 | vfree(pbuf); | |
302 | if (satmp) | |
303 | vfree(satmp); | |
304 | return error; | |
305 | } | |
306 | ||
307 | /* | |
308 | * send to responder | |
309 | * psk: HDR, KE, Ni | |
310 | * sig: HDR, KE, Ni | |
311 | * gssapi: HDR, KE, Ni, GSSi | |
312 | * rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r | |
313 | * rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, | |
314 | * <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i] | |
315 | */ | |
316 | int | |
317 | ident_i2send(iph1, msg) | |
318 | struct ph1handle *iph1; | |
319 | vchar_t *msg; | |
320 | { | |
321 | int error = -1; | |
322 | ||
323 | /* validity check */ | |
324 | if (iph1->status != PHASE1ST_MSG2RECEIVED) { | |
325 | plog(LLV_ERROR, LOCATION, NULL, | |
326 | "status mismatched %d.\n", iph1->status); | |
327 | goto end; | |
328 | } | |
329 | ||
330 | /* fix isakmp index */ | |
331 | memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck, | |
332 | sizeof(cookie_t)); | |
333 | ||
334 | /* generate DH public value */ | |
335 | if (oakley_dh_generate(iph1->approval->dhgrp, | |
336 | &iph1->dhpub, &iph1->dhpriv) < 0) | |
337 | goto end; | |
338 | ||
339 | /* generate NONCE value */ | |
340 | iph1->nonce = eay_set_random(iph1->rmconf->nonce_size); | |
341 | if (iph1->nonce == NULL) | |
342 | goto end; | |
343 | ||
344 | #ifdef HAVE_GSSAPI | |
345 | if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB && | |
346 | gssapi_get_itoken(iph1, NULL) < 0) | |
347 | goto end; | |
348 | #endif | |
349 | ||
350 | /* create buffer to send isakmp payload */ | |
351 | iph1->sendbuf = ident_ir2mx(iph1); | |
352 | if (iph1->sendbuf == NULL) | |
353 | goto end; | |
354 | ||
355 | #ifdef HAVE_PRINT_ISAKMP_C | |
356 | isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0); | |
357 | #endif | |
358 | ||
359 | /* send the packet, add to the schedule to resend */ | |
360 | iph1->retry_counter = iph1->rmconf->retry_counter; | |
361 | if (isakmp_ph1resend(iph1) == -1) | |
362 | goto end; | |
363 | ||
364 | /* the sending message is added to the received-list. */ | |
365 | if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) { | |
366 | plog(LLV_ERROR , LOCATION, NULL, | |
367 | "failed to add a response packet to the tree.\n"); | |
368 | goto end; | |
369 | } | |
370 | ||
371 | iph1->status = PHASE1ST_MSG2SENT; | |
372 | ||
373 | error = 0; | |
374 | ||
375 | end: | |
376 | return error; | |
377 | } | |
378 | ||
379 | /* | |
380 | * receive from responder | |
381 | * psk: HDR, KE, Nr | |
382 | * sig: HDR, KE, Nr [, CR ] | |
383 | * gssapi: HDR, KE, Nr, GSSr | |
384 | * rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i | |
385 | * rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r, | |
386 | */ | |
387 | int | |
388 | ident_i3recv(iph1, msg) | |
389 | struct ph1handle *iph1; | |
390 | vchar_t *msg; | |
391 | { | |
392 | vchar_t *pbuf = NULL; | |
393 | struct isakmp_parse_t *pa; | |
394 | int error = -1; | |
395 | #ifdef HAVE_GSSAPI | |
396 | vchar_t *gsstoken = NULL; | |
397 | #endif | |
398 | ||
399 | /* validity check */ | |
400 | if (iph1->status != PHASE1ST_MSG2SENT) { | |
401 | plog(LLV_ERROR, LOCATION, NULL, | |
402 | "status mismatched %d.\n", iph1->status); | |
403 | goto end; | |
404 | } | |
405 | ||
406 | /* validate the type of next payload */ | |
407 | pbuf = isakmp_parse(msg); | |
408 | if (pbuf == NULL) | |
409 | goto end; | |
410 | ||
411 | for (pa = (struct isakmp_parse_t *)pbuf->v; | |
412 | pa->type != ISAKMP_NPTYPE_NONE; | |
413 | pa++) { | |
414 | ||
415 | switch (pa->type) { | |
416 | case ISAKMP_NPTYPE_KE: | |
417 | if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0) | |
418 | goto end; | |
419 | break; | |
420 | case ISAKMP_NPTYPE_NONCE: | |
421 | if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0) | |
422 | goto end; | |
423 | break; | |
424 | case ISAKMP_NPTYPE_VID: | |
425 | (void)check_vendorid(pa->ptr); | |
426 | break; | |
427 | #ifdef HAVE_SIGNING_C | |
428 | case ISAKMP_NPTYPE_CR: | |
429 | if (oakley_savecr(iph1, pa->ptr) < 0) | |
430 | goto end; | |
431 | break; | |
432 | #endif | |
433 | #ifdef HAVE_GSSAPI | |
434 | case ISAKMP_NPTYPE_GSS: | |
435 | if (isakmp_p2ph(&gsstoken, pa->ptr) < 0) | |
436 | goto end; | |
437 | gssapi_save_received_token(iph1, gsstoken); | |
438 | break; | |
439 | #endif | |
ffda1f4a A |
440 | case ISAKMP_NPTYPE_NATD_RFC: |
441 | case ISAKMP_NPTYPE_NATD_DRAFT: | |
442 | case ISAKMP_NPTYPE_NATD_BADDRAFT: | |
ac2f15b3 A |
443 | #ifdef IKE_NAT_T |
444 | { | |
ffda1f4a A |
445 | natd_match_t match; |
446 | ||
447 | if (pa->type != iph1->natd_payload_type) { | |
448 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
449 | "ignore the packet, " | |
450 | "received unexpected natd payload type %d.\n", | |
451 | pa->type); | |
452 | goto end; | |
453 | } | |
454 | match = natd_matches(iph1, pa->ptr); | |
ac2f15b3 A |
455 | iph1->natt_flags |= natt_natd_received; |
456 | if ((match & natd_match_local) != 0) | |
457 | iph1->natt_flags |= natt_no_local_nat; | |
458 | if ((match & natd_match_remote) != 0) | |
459 | iph1->natt_flags |= natt_no_remote_nat; | |
460 | } | |
461 | #endif | |
462 | break; | |
7ba0088d A |
463 | default: |
464 | /* don't send information, see ident_r1recv() */ | |
465 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
466 | "ignore the packet, " | |
467 | "received unexpecting payload type %d.\n", | |
468 | pa->type); | |
469 | goto end; | |
470 | } | |
471 | } | |
ac2f15b3 A |
472 | |
473 | #ifdef IKE_NAT_T | |
474 | /* Determine if we need to switch to port 4500 */ | |
475 | if (natd_hasnat(iph1)) | |
476 | { | |
477 | /* There is a NAT between us! Switch to port 4500. */ | |
478 | if (iph1->remote->sa_family == AF_INET) | |
479 | { | |
480 | struct sockaddr_in *sin = (struct sockaddr_in*)iph1->remote; | |
481 | plog(LLV_INFO, LOCATION, NULL, | |
482 | "detected NAT, switching to port %d for %s", | |
483 | PORT_ISAKMP_NATT, saddr2str(iph1->remote)); | |
484 | sin->sin_port = htons(PORT_ISAKMP_NATT); | |
485 | sin = (struct sockaddr_in*)iph1->local; | |
486 | sin->sin_port = htons(PORT_ISAKMP_NATT); | |
487 | } | |
488 | } | |
489 | #endif | |
7ba0088d A |
490 | |
491 | /* payload existency check */ | |
492 | if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) { | |
493 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
494 | "few isakmp message received.\n"); | |
495 | goto end; | |
496 | } | |
497 | ||
498 | #ifdef HAVE_SIGNING_C | |
499 | if (oakley_checkcr(iph1) < 0) { | |
500 | /* Ignore this error in order to be interoperability. */ | |
501 | ; | |
502 | } | |
503 | #endif | |
504 | ||
505 | iph1->status = PHASE1ST_MSG3RECEIVED; | |
506 | ||
507 | error = 0; | |
508 | ||
509 | end: | |
510 | if (pbuf) | |
511 | vfree(pbuf); | |
512 | if (error) { | |
513 | VPTRINIT(iph1->dhpub_p); | |
514 | VPTRINIT(iph1->nonce_p); | |
515 | VPTRINIT(iph1->id_p); | |
516 | oakley_delcert(iph1->cr_p); | |
517 | iph1->cr_p = NULL; | |
518 | } | |
519 | ||
520 | return error; | |
521 | } | |
522 | ||
523 | /* | |
524 | * send to responder | |
525 | * psk: HDR*, IDi1, HASH_I | |
526 | * sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I | |
527 | * gssapi: HDR*, IDi1, < Gssi(n) | HASH_I > | |
528 | * rsa: HDR*, HASH_I | |
529 | * rev: HDR*, HASH_I | |
530 | */ | |
531 | int | |
532 | ident_i3send(iph1, msg0) | |
533 | struct ph1handle *iph1; | |
534 | vchar_t *msg0; | |
535 | { | |
536 | int error = -1; | |
537 | int dohash = 1; | |
538 | #ifdef HAVE_GSSAPI | |
539 | int len; | |
540 | #endif | |
541 | ||
542 | /* validity check */ | |
543 | if (iph1->status != PHASE1ST_MSG3RECEIVED) { | |
544 | plog(LLV_ERROR, LOCATION, NULL, | |
545 | "status mismatched %d.\n", iph1->status); | |
546 | goto end; | |
547 | } | |
548 | ||
549 | /* compute sharing secret of DH */ | |
550 | if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub, | |
551 | iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0) | |
552 | goto end; | |
553 | ||
554 | /* generate SKEYIDs & IV & final cipher key */ | |
555 | if (oakley_skeyid(iph1) < 0) | |
556 | goto end; | |
557 | if (oakley_skeyid_dae(iph1) < 0) | |
558 | goto end; | |
559 | if (oakley_compute_enckey(iph1) < 0) | |
560 | goto end; | |
561 | if (oakley_newiv(iph1) < 0) | |
562 | goto end; | |
563 | ||
564 | /* make ID payload into isakmp status */ | |
565 | if (ipsecdoi_setid1(iph1) < 0) | |
566 | goto end; | |
567 | ||
568 | #ifdef HAVE_GSSAPI | |
569 | if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB && | |
570 | gssapi_more_tokens(iph1)) { | |
571 | plog(LLV_DEBUG, LOCATION, NULL, "calling get_itoken\n"); | |
572 | if (gssapi_get_itoken(iph1, &len) < 0) | |
573 | goto end; | |
574 | if (len != 0) | |
575 | dohash = 0; | |
576 | } | |
577 | #endif | |
578 | ||
579 | /* generate HASH to send */ | |
580 | if (dohash) { | |
581 | iph1->hash = oakley_ph1hash_common(iph1, GENERATE); | |
582 | if (iph1->hash == NULL) | |
583 | goto end; | |
584 | } else | |
585 | iph1->hash = NULL; | |
586 | ||
587 | /* set encryption flag */ | |
588 | iph1->flags |= ISAKMP_FLAG_E; | |
589 | ||
590 | /* create HDR;ID;HASH payload */ | |
591 | iph1->sendbuf = ident_ir3mx(iph1); | |
592 | if (iph1->sendbuf == NULL) | |
593 | goto end; | |
594 | ||
595 | /* send the packet, add to the schedule to resend */ | |
596 | iph1->retry_counter = iph1->rmconf->retry_counter; | |
597 | if (isakmp_ph1resend(iph1) == -1) | |
598 | goto end; | |
599 | ||
600 | /* the sending message is added to the received-list. */ | |
601 | if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg0) == -1) { | |
602 | plog(LLV_ERROR , LOCATION, NULL, | |
603 | "failed to add a response packet to the tree.\n"); | |
604 | goto end; | |
605 | } | |
606 | ||
607 | /* see handler.h about IV synchronization. */ | |
608 | memcpy(iph1->ivm->ive->v, iph1->ivm->iv->v, iph1->ivm->iv->l); | |
609 | ||
610 | iph1->status = PHASE1ST_MSG3SENT; | |
611 | ||
612 | error = 0; | |
613 | ||
614 | end: | |
615 | return error; | |
616 | } | |
617 | ||
618 | /* | |
619 | * receive from responder | |
620 | * psk: HDR*, IDr1, HASH_R | |
621 | * sig: HDR*, IDr1, [ CERT, ] SIG_R | |
622 | * gssapi: HDR*, IDr1, < GSSr(n) | HASH_R > | |
623 | * rsa: HDR*, HASH_R | |
624 | * rev: HDR*, HASH_R | |
625 | */ | |
626 | int | |
627 | ident_i4recv(iph1, msg0) | |
628 | struct ph1handle *iph1; | |
629 | vchar_t *msg0; | |
630 | { | |
631 | vchar_t *pbuf = NULL; | |
632 | struct isakmp_parse_t *pa; | |
633 | vchar_t *msg = NULL; | |
634 | int error = -1; | |
635 | int type; | |
636 | #ifdef HAVE_GSSAPI | |
637 | vchar_t *gsstoken = NULL; | |
638 | #endif | |
639 | ||
640 | /* validity check */ | |
641 | if (iph1->status != PHASE1ST_MSG3SENT) { | |
642 | plog(LLV_ERROR, LOCATION, NULL, | |
643 | "status mismatched %d.\n", iph1->status); | |
644 | goto end; | |
645 | } | |
646 | ||
647 | /* decrypting */ | |
648 | if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) { | |
649 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
650 | "ignore the packet, " | |
651 | "expecting the packet encrypted.\n"); | |
652 | goto end; | |
653 | } | |
654 | msg = oakley_do_decrypt(iph1, msg0, iph1->ivm->iv, iph1->ivm->ive); | |
655 | if (msg == NULL) | |
656 | goto end; | |
657 | ||
658 | /* validate the type of next payload */ | |
659 | pbuf = isakmp_parse(msg); | |
660 | if (pbuf == NULL) | |
661 | goto end; | |
662 | ||
663 | iph1->pl_hash = NULL; | |
664 | ||
665 | for (pa = (struct isakmp_parse_t *)pbuf->v; | |
666 | pa->type != ISAKMP_NPTYPE_NONE; | |
667 | pa++) { | |
668 | ||
669 | switch (pa->type) { | |
670 | case ISAKMP_NPTYPE_ID: | |
671 | if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0) | |
672 | goto end; | |
673 | break; | |
674 | case ISAKMP_NPTYPE_HASH: | |
675 | iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr; | |
676 | break; | |
677 | #ifdef HAVE_SIGNING_C | |
678 | case ISAKMP_NPTYPE_CERT: | |
679 | if (oakley_savecert(iph1, pa->ptr) < 0) | |
680 | goto end; | |
681 | break; | |
682 | case ISAKMP_NPTYPE_SIG: | |
683 | if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0) | |
684 | goto end; | |
685 | break; | |
686 | #endif | |
687 | #ifdef HAVE_GSSAPI | |
688 | case ISAKMP_NPTYPE_GSS: | |
689 | if (isakmp_p2ph(&gsstoken, pa->ptr) < 0) | |
690 | goto end; | |
691 | gssapi_save_received_token(iph1, gsstoken); | |
692 | break; | |
693 | #endif | |
694 | case ISAKMP_NPTYPE_VID: | |
695 | (void)check_vendorid(pa->ptr); | |
696 | break; | |
697 | case ISAKMP_NPTYPE_N: | |
698 | isakmp_check_notify(pa->ptr, iph1); | |
699 | break; | |
700 | default: | |
701 | /* don't send information, see ident_r1recv() */ | |
702 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
703 | "ignore the packet, " | |
704 | "received unexpecting payload type %d.\n", | |
705 | pa->type); | |
706 | goto end; | |
707 | } | |
708 | } | |
709 | ||
710 | /* payload existency check */ | |
711 | ||
712 | /* see handler.h about IV synchronization. */ | |
713 | memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->ive->l); | |
714 | ||
715 | /* verify identifier */ | |
716 | if (ipsecdoi_checkid1(iph1) != 0) { | |
717 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
718 | "invalid ID payload.\n"); | |
719 | goto end; | |
720 | } | |
721 | ||
722 | /* validate authentication value */ | |
723 | #ifdef HAVE_GSSAPI | |
724 | if (gsstoken == NULL) { | |
725 | #endif | |
726 | type = oakley_validate_auth(iph1); | |
727 | if (type != 0) { | |
728 | if (type == -1) { | |
729 | /* msg printed inner oakley_validate_auth() */ | |
730 | goto end; | |
731 | } | |
732 | isakmp_info_send_n1(iph1, type, NULL); | |
733 | goto end; | |
734 | } | |
735 | #ifdef HAVE_GSSAPI | |
736 | } | |
737 | #endif | |
738 | ||
739 | /* | |
740 | * XXX: Should we do compare two addresses, ph1handle's and ID | |
741 | * payload's. | |
742 | */ | |
743 | ||
744 | plog(LLV_DEBUG, LOCATION, iph1->remote, "peer's ID:"); | |
745 | plogdump(LLV_DEBUG, iph1->id_p->v, iph1->id_p->l); | |
746 | ||
747 | /* | |
748 | * If we got a GSS token, we need to this roundtrip again. | |
749 | */ | |
750 | #ifdef HAVE_GSSAPI | |
751 | iph1->status = gsstoken != 0 ? PHASE1ST_MSG3RECEIVED : | |
752 | PHASE1ST_MSG4RECEIVED; | |
753 | #else | |
754 | iph1->status = PHASE1ST_MSG4RECEIVED; | |
755 | #endif | |
756 | ||
757 | error = 0; | |
758 | ||
759 | end: | |
760 | if (pbuf) | |
761 | vfree(pbuf); | |
762 | if (msg) | |
763 | vfree(msg); | |
764 | #ifdef HAVE_GSSAPI | |
765 | if (gsstoken) | |
766 | vfree(gsstoken); | |
767 | #endif | |
768 | ||
769 | if (error) { | |
770 | VPTRINIT(iph1->id_p); | |
771 | oakley_delcert(iph1->cert_p); | |
772 | iph1->cert_p = NULL; | |
773 | oakley_delcert(iph1->crl_p); | |
774 | iph1->crl_p = NULL; | |
775 | VPTRINIT(iph1->sig_p); | |
776 | } | |
777 | ||
778 | return error; | |
779 | } | |
780 | ||
781 | /* | |
782 | * status update and establish isakmp sa. | |
783 | */ | |
784 | int | |
785 | ident_i4send(iph1, msg) | |
786 | struct ph1handle *iph1; | |
787 | vchar_t *msg; | |
788 | { | |
789 | int error = -1; | |
790 | ||
791 | /* validity check */ | |
792 | if (iph1->status != PHASE1ST_MSG4RECEIVED) { | |
793 | plog(LLV_ERROR, LOCATION, NULL, | |
794 | "status mismatched %d.\n", iph1->status); | |
795 | goto end; | |
796 | } | |
797 | ||
798 | /* see handler.h about IV synchronization. */ | |
799 | memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l); | |
800 | ||
801 | iph1->status = PHASE1ST_ESTABLISHED; | |
802 | ||
803 | error = 0; | |
804 | ||
805 | end: | |
806 | return error; | |
807 | } | |
808 | ||
809 | /* | |
810 | * receive from initiator | |
811 | * psk: HDR, SA | |
812 | * sig: HDR, SA | |
813 | * rsa: HDR, SA | |
814 | * rev: HDR, SA | |
815 | */ | |
816 | int | |
817 | ident_r1recv(iph1, msg) | |
818 | struct ph1handle *iph1; | |
819 | vchar_t *msg; | |
820 | { | |
821 | vchar_t *pbuf = NULL; | |
822 | struct isakmp_parse_t *pa; | |
823 | int error = -1; | |
824 | ||
825 | /* validity check */ | |
826 | if (iph1->status != PHASE1ST_START) { | |
827 | plog(LLV_ERROR, LOCATION, NULL, | |
828 | "status mismatched %d.\n", iph1->status); | |
829 | goto end; | |
830 | } | |
831 | ||
832 | /* validate the type of next payload */ | |
833 | /* | |
834 | * NOTE: XXX even if multiple VID, we'll silently ignore those. | |
835 | */ | |
836 | pbuf = isakmp_parse(msg); | |
837 | if (pbuf == NULL) | |
838 | goto end; | |
839 | pa = (struct isakmp_parse_t *)pbuf->v; | |
840 | ||
841 | /* check the position of SA payload */ | |
842 | if (pa->type != ISAKMP_NPTYPE_SA) { | |
843 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
844 | "received invalid next payload type %d, " | |
845 | "expecting %d.\n", | |
846 | pa->type, ISAKMP_NPTYPE_SA); | |
847 | goto end; | |
848 | } | |
849 | if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0) | |
850 | goto end; | |
851 | pa++; | |
852 | ||
853 | for (/*nothing*/; | |
854 | pa->type != ISAKMP_NPTYPE_NONE; | |
855 | pa++) { | |
856 | ||
857 | switch (pa->type) { | |
858 | case ISAKMP_NPTYPE_VID: | |
ac2f15b3 | 859 | { |
ffda1f4a A |
860 | int vid = check_vendorid(pa->ptr); |
861 | #if IKE_NAT_T | |
862 | if (vid == VENDORID_NATT_RFC) | |
863 | iph1->natt_flags |= natt_type_rfc; | |
864 | else if (vid == VENDORID_NATT_APPLE) | |
865 | iph1->natt_flags |= natt_type_apple; | |
866 | else if (vid == VENDORID_NATT_02) | |
867 | iph1->natt_flags |= natt_type_02; | |
868 | else | |
869 | iph1->natt_flags |= natt_type_02N; | |
870 | #endif | |
ac2f15b3 | 871 | } |
7ba0088d A |
872 | break; |
873 | default: | |
874 | /* | |
875 | * We don't send information to the peer even | |
876 | * if we received malformed packet. Because we | |
877 | * can't distinguish the malformed packet and | |
878 | * the re-sent packet. And we do same behavior | |
879 | * when we expect encrypted packet. | |
880 | */ | |
881 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
882 | "ignore the packet, " | |
883 | "received unexpecting payload type %d.\n", | |
884 | pa->type); | |
885 | goto end; | |
886 | } | |
887 | } | |
888 | ||
ffda1f4a A |
889 | /* if natt vid(s) received - select type to use */ |
890 | natt_select_type(iph1); | |
891 | ||
7ba0088d A |
892 | /* check SA payload and set approval SA for use */ |
893 | if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) { | |
894 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
895 | "failed to get valid proposal.\n"); | |
896 | /* XXX send information */ | |
897 | goto end; | |
898 | } | |
899 | ||
900 | iph1->status = PHASE1ST_MSG1RECEIVED; | |
901 | ||
902 | error = 0; | |
903 | ||
904 | end: | |
905 | if (pbuf) | |
906 | vfree(pbuf); | |
907 | if (error) { | |
908 | VPTRINIT(iph1->sa); | |
909 | } | |
910 | ||
911 | return error; | |
912 | } | |
913 | ||
914 | /* | |
915 | * send to initiator | |
916 | * psk: HDR, SA | |
917 | * sig: HDR, SA | |
918 | * rsa: HDR, SA | |
919 | * rev: HDR, SA | |
920 | */ | |
921 | int | |
922 | ident_r1send(iph1, msg) | |
923 | struct ph1handle *iph1; | |
924 | vchar_t *msg; | |
925 | { | |
926 | struct isakmp_gen *gen; | |
927 | caddr_t p; | |
928 | int tlen; | |
929 | int error = -1; | |
930 | vchar_t *gss_sa = NULL; | |
931 | vchar_t *vid = NULL; | |
ac2f15b3 A |
932 | #ifdef IKE_NAT_T |
933 | vchar_t *nattvid = NULL; | |
934 | #endif | |
7ba0088d A |
935 | |
936 | /* validity check */ | |
937 | if (iph1->status != PHASE1ST_MSG1RECEIVED) { | |
938 | plog(LLV_ERROR, LOCATION, NULL, | |
939 | "status mismatched %d.\n", iph1->status); | |
940 | goto end; | |
941 | } | |
942 | ||
943 | /* set responder's cookie */ | |
944 | isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local); | |
945 | ||
946 | #ifdef HAVE_GSSAPI | |
947 | if (iph1->approval->gssid != NULL) | |
948 | gss_sa = ipsecdoi_setph1proposal(iph1->approval); | |
949 | else | |
950 | #endif | |
951 | gss_sa = iph1->sa_ret; | |
952 | ||
953 | /* create buffer to send isakmp payload */ | |
954 | tlen = sizeof(struct isakmp) | |
955 | + sizeof(*gen) + gss_sa->l; | |
956 | ||
957 | if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL) | |
958 | tlen += sizeof(*gen) + vid->l; | |
959 | ||
ac2f15b3 | 960 | #ifdef IKE_NAT_T |
ac2f15b3 | 961 | { |
ffda1f4a A |
962 | int natt_type = iph1->natt_flags & NATT_TYPE_MASK; |
963 | ||
964 | if (natt_type != 0) { | |
965 | if (natt_type == natt_type_rfc) | |
966 | nattvid = set_vendorid(VENDORID_NATT_RFC); | |
967 | else if (natt_type == natt_type_apple) | |
968 | nattvid = set_vendorid(VENDORID_NATT_APPLE); | |
969 | else if (natt_type == natt_type_02) | |
970 | nattvid = set_vendorid(VENDORID_NATT_02); | |
971 | else if (natt_type == natt_type_02N) | |
972 | nattvid = set_vendorid(VENDORID_NATT_02N); | |
973 | ||
974 | if (nattvid != NULL) | |
975 | tlen += sizeof(*gen) + nattvid->l; | |
976 | } | |
ac2f15b3 A |
977 | } |
978 | #endif | |
979 | ||
7ba0088d A |
980 | iph1->sendbuf = vmalloc(tlen); |
981 | if (iph1->sendbuf == NULL) { | |
982 | plog(LLV_ERROR, LOCATION, NULL, | |
983 | "failed to get buffer to send.\n"); | |
984 | goto end; | |
985 | } | |
986 | ||
987 | /* set isakmp header */ | |
988 | p = set_isakmp_header(iph1->sendbuf, iph1, ISAKMP_NPTYPE_SA); | |
989 | if (p == NULL) | |
990 | goto end; | |
991 | ||
992 | /* set SA payload to reply */ | |
993 | p = set_isakmp_payload(p, gss_sa, | |
ac2f15b3 | 994 | (vid || nattvid) ? ISAKMP_NPTYPE_VID |
7ba0088d A |
995 | : ISAKMP_NPTYPE_NONE); |
996 | ||
997 | /* Set Vendor ID, if necessary. */ | |
998 | if (vid) | |
ffda1f4a | 999 | p = set_isakmp_payload(p, vid, nattvid ? ISAKMP_NPTYPE_VID : ISAKMP_NPTYPE_NONE); |
ac2f15b3 A |
1000 | |
1001 | if (nattvid) | |
1002 | p = set_isakmp_payload(p, nattvid, ISAKMP_NPTYPE_NONE); | |
7ba0088d A |
1003 | |
1004 | #ifdef HAVE_PRINT_ISAKMP_C | |
1005 | isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0); | |
1006 | #endif | |
1007 | ||
1008 | /* send the packet, add to the schedule to resend */ | |
1009 | iph1->retry_counter = iph1->rmconf->retry_counter; | |
1010 | if (isakmp_ph1resend(iph1) == -1) | |
1011 | goto end; | |
1012 | ||
1013 | /* the sending message is added to the received-list. */ | |
1014 | if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) { | |
1015 | plog(LLV_ERROR , LOCATION, NULL, | |
1016 | "failed to add a response packet to the tree.\n"); | |
1017 | goto end; | |
1018 | } | |
1019 | ||
1020 | iph1->status = PHASE1ST_MSG1SENT; | |
1021 | ||
1022 | error = 0; | |
1023 | ||
1024 | end: | |
1025 | #ifdef HAVE_GSSAPI | |
1026 | if (gss_sa != iph1->sa_ret) | |
1027 | vfree(gss_sa); | |
1028 | #endif | |
1029 | if (vid) | |
1030 | vfree(vid); | |
ac2f15b3 A |
1031 | if (nattvid) |
1032 | vfree(nattvid); | |
7ba0088d A |
1033 | return error; |
1034 | } | |
1035 | ||
1036 | /* | |
1037 | * receive from initiator | |
1038 | * psk: HDR, KE, Ni | |
1039 | * sig: HDR, KE, Ni | |
1040 | * gssapi: HDR, KE, Ni, GSSi | |
1041 | * rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r | |
1042 | * rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, | |
1043 | * <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i] | |
1044 | */ | |
1045 | int | |
1046 | ident_r2recv(iph1, msg) | |
1047 | struct ph1handle *iph1; | |
1048 | vchar_t *msg; | |
1049 | { | |
1050 | vchar_t *pbuf = NULL; | |
1051 | struct isakmp_parse_t *pa; | |
1052 | int error = -1; | |
1053 | #ifdef HAVE_GSSAPI | |
1054 | vchar_t *gsstoken = NULL; | |
1055 | #endif | |
1056 | ||
1057 | /* validity check */ | |
1058 | if (iph1->status != PHASE1ST_MSG1SENT) { | |
1059 | plog(LLV_ERROR, LOCATION, NULL, | |
1060 | "status mismatched %d.\n", iph1->status); | |
1061 | goto end; | |
1062 | } | |
1063 | ||
1064 | /* validate the type of next payload */ | |
1065 | pbuf = isakmp_parse(msg); | |
1066 | if (pbuf == NULL) | |
1067 | goto end; | |
1068 | ||
1069 | for (pa = (struct isakmp_parse_t *)pbuf->v; | |
1070 | pa->type != ISAKMP_NPTYPE_NONE; | |
1071 | pa++) { | |
1072 | ||
1073 | switch (pa->type) { | |
1074 | case ISAKMP_NPTYPE_KE: | |
1075 | if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0) | |
1076 | goto end; | |
1077 | break; | |
1078 | case ISAKMP_NPTYPE_NONCE: | |
1079 | if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0) | |
1080 | goto end; | |
1081 | break; | |
1082 | case ISAKMP_NPTYPE_VID: | |
1083 | (void)check_vendorid(pa->ptr); | |
1084 | break; | |
1085 | case ISAKMP_NPTYPE_CR: | |
1086 | plog(LLV_WARNING, LOCATION, iph1->remote, | |
1087 | "CR received, ignore it. " | |
1088 | "It should be in other exchange.\n"); | |
1089 | break; | |
1090 | #ifdef HAVE_GSSAPI | |
1091 | case ISAKMP_NPTYPE_GSS: | |
1092 | if (isakmp_p2ph(&gsstoken, pa->ptr) < 0) | |
1093 | goto end; | |
1094 | gssapi_save_received_token(iph1, gsstoken); | |
1095 | break; | |
1096 | #endif | |
ffda1f4a A |
1097 | case ISAKMP_NPTYPE_NATD_RFC: |
1098 | case ISAKMP_NPTYPE_NATD_DRAFT: | |
1099 | case ISAKMP_NPTYPE_NATD_BADDRAFT: | |
ac2f15b3 A |
1100 | #ifdef IKE_NAT_T |
1101 | { | |
ffda1f4a A |
1102 | natd_match_t match; |
1103 | ||
1104 | if (pa->type != iph1->natd_payload_type) { | |
1105 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1106 | "ignore the packet, " | |
1107 | "received unexpected natd payload type %d.\n", | |
1108 | pa->type); | |
1109 | goto end; | |
1110 | } | |
1111 | match = natd_matches(iph1, pa->ptr); | |
ac2f15b3 A |
1112 | iph1->natt_flags |= natt_natd_received; |
1113 | if ((match & natd_match_local) != 0) | |
1114 | iph1->natt_flags |= natt_no_local_nat; | |
1115 | if ((match & natd_match_remote) != 0) | |
1116 | iph1->natt_flags |= natt_no_remote_nat; | |
1117 | } | |
1118 | #endif | |
1119 | break; | |
7ba0088d A |
1120 | default: |
1121 | /* don't send information, see ident_r1recv() */ | |
1122 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1123 | "ignore the packet, " | |
1124 | "received unexpecting payload type %d.\n", | |
1125 | pa->type); | |
1126 | goto end; | |
1127 | } | |
1128 | } | |
1129 | ||
1130 | /* payload existency check */ | |
1131 | if (iph1->dhpub_p == NULL || iph1->nonce_p == NULL) { | |
1132 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1133 | "few isakmp message received.\n"); | |
1134 | goto end; | |
1135 | } | |
1136 | ||
1137 | iph1->status = PHASE1ST_MSG2RECEIVED; | |
1138 | ||
1139 | error = 0; | |
1140 | ||
1141 | end: | |
1142 | if (pbuf) | |
1143 | vfree(pbuf); | |
1144 | #ifdef HAVE_GSSAPI | |
1145 | if (gsstoken) | |
1146 | vfree(gsstoken); | |
1147 | #endif | |
1148 | ||
1149 | if (error) { | |
1150 | VPTRINIT(iph1->dhpub_p); | |
1151 | VPTRINIT(iph1->nonce_p); | |
1152 | VPTRINIT(iph1->id_p); | |
1153 | } | |
1154 | ||
1155 | return error; | |
1156 | } | |
1157 | ||
1158 | /* | |
1159 | * send to initiator | |
1160 | * psk: HDR, KE, Nr | |
1161 | * sig: HDR, KE, Nr [, CR ] | |
1162 | * gssapi: HDR, KE, Nr, GSSr | |
1163 | * rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i | |
1164 | * rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r, | |
1165 | */ | |
1166 | int | |
1167 | ident_r2send(iph1, msg) | |
1168 | struct ph1handle *iph1; | |
1169 | vchar_t *msg; | |
1170 | { | |
1171 | int error = -1; | |
1172 | ||
1173 | /* validity check */ | |
1174 | if (iph1->status != PHASE1ST_MSG2RECEIVED) { | |
1175 | plog(LLV_ERROR, LOCATION, NULL, | |
1176 | "status mismatched %d.\n", iph1->status); | |
1177 | goto end; | |
1178 | } | |
1179 | ||
1180 | /* generate DH public value */ | |
1181 | if (oakley_dh_generate(iph1->approval->dhgrp, | |
1182 | &iph1->dhpub, &iph1->dhpriv) < 0) | |
1183 | goto end; | |
1184 | ||
1185 | /* generate NONCE value */ | |
1186 | iph1->nonce = eay_set_random(iph1->rmconf->nonce_size); | |
1187 | if (iph1->nonce == NULL) | |
1188 | goto end; | |
1189 | ||
1190 | #ifdef HAVE_GSSAPI | |
1191 | if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) | |
1192 | gssapi_get_rtoken(iph1, NULL); | |
1193 | #endif | |
1194 | ||
1195 | /* create HDR;KE;NONCE payload */ | |
1196 | iph1->sendbuf = ident_ir2mx(iph1); | |
1197 | if (iph1->sendbuf == NULL) | |
1198 | goto end; | |
1199 | ||
1200 | #ifdef HAVE_PRINT_ISAKMP_C | |
1201 | isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0); | |
1202 | #endif | |
1203 | ||
1204 | /* send the packet, add to the schedule to resend */ | |
1205 | iph1->retry_counter = iph1->rmconf->retry_counter; | |
1206 | if (isakmp_ph1resend(iph1) == -1) | |
1207 | goto end; | |
1208 | ||
1209 | /* the sending message is added to the received-list. */ | |
1210 | if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) { | |
1211 | plog(LLV_ERROR , LOCATION, NULL, | |
1212 | "failed to add a response packet to the tree.\n"); | |
1213 | goto end; | |
1214 | } | |
1215 | ||
1216 | /* compute sharing secret of DH */ | |
1217 | if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub, | |
1218 | iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0) | |
1219 | goto end; | |
1220 | ||
1221 | /* generate SKEYIDs & IV & final cipher key */ | |
1222 | if (oakley_skeyid(iph1) < 0) | |
1223 | goto end; | |
1224 | if (oakley_skeyid_dae(iph1) < 0) | |
1225 | goto end; | |
1226 | if (oakley_compute_enckey(iph1) < 0) | |
1227 | goto end; | |
1228 | if (oakley_newiv(iph1) < 0) | |
1229 | goto end; | |
1230 | ||
1231 | iph1->status = PHASE1ST_MSG2SENT; | |
1232 | ||
1233 | error = 0; | |
1234 | ||
1235 | end: | |
1236 | return error; | |
1237 | } | |
1238 | ||
1239 | /* | |
1240 | * receive from initiator | |
1241 | * psk: HDR*, IDi1, HASH_I | |
1242 | * sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I | |
1243 | * gssapi: HDR*, [ IDi1, ] < GSSi(n) | HASH_I > | |
1244 | * rsa: HDR*, HASH_I | |
1245 | * rev: HDR*, HASH_I | |
1246 | */ | |
1247 | int | |
1248 | ident_r3recv(iph1, msg0) | |
1249 | struct ph1handle *iph1; | |
1250 | vchar_t *msg0; | |
1251 | { | |
1252 | vchar_t *msg = NULL; | |
1253 | vchar_t *pbuf = NULL; | |
1254 | struct isakmp_parse_t *pa; | |
1255 | int error = -1; | |
1256 | int type; | |
1257 | #ifdef HAVE_GSSAPI | |
1258 | vchar_t *gsstoken = NULL; | |
1259 | #endif | |
1260 | ||
1261 | /* validity check */ | |
1262 | if (iph1->status != PHASE1ST_MSG2SENT) { | |
1263 | plog(LLV_ERROR, LOCATION, NULL, | |
1264 | "status mismatched %d.\n", iph1->status); | |
1265 | goto end; | |
1266 | } | |
1267 | ||
1268 | /* decrypting */ | |
1269 | if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) { | |
1270 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1271 | "reject the packet, " | |
1272 | "expecting the packet encrypted.\n"); | |
1273 | goto end; | |
1274 | } | |
1275 | msg = oakley_do_decrypt(iph1, msg0, iph1->ivm->iv, iph1->ivm->ive); | |
1276 | if (msg == NULL) | |
1277 | goto end; | |
1278 | ||
1279 | /* validate the type of next payload */ | |
1280 | pbuf = isakmp_parse(msg); | |
1281 | if (pbuf == NULL) | |
1282 | goto end; | |
1283 | ||
1284 | iph1->pl_hash = NULL; | |
1285 | ||
1286 | for (pa = (struct isakmp_parse_t *)pbuf->v; | |
1287 | pa->type != ISAKMP_NPTYPE_NONE; | |
1288 | pa++) { | |
1289 | ||
1290 | switch (pa->type) { | |
1291 | case ISAKMP_NPTYPE_ID: | |
1292 | if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0) | |
1293 | goto end; | |
1294 | break; | |
1295 | case ISAKMP_NPTYPE_HASH: | |
1296 | iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr; | |
1297 | break; | |
1298 | #ifdef HAVE_SIGNING_C | |
1299 | case ISAKMP_NPTYPE_CR: | |
1300 | if (oakley_savecr(iph1, pa->ptr) < 0) | |
1301 | goto end; | |
1302 | break; | |
1303 | case ISAKMP_NPTYPE_CERT: | |
1304 | if (oakley_savecert(iph1, pa->ptr) < 0) | |
1305 | goto end; | |
1306 | break; | |
1307 | case ISAKMP_NPTYPE_SIG: | |
1308 | if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0) | |
1309 | goto end; | |
1310 | break; | |
1311 | #endif | |
1312 | #ifdef HAVE_GSSAPI | |
1313 | case ISAKMP_NPTYPE_GSS: | |
1314 | if (isakmp_p2ph(&gsstoken, pa->ptr) < 0) | |
1315 | goto end; | |
1316 | gssapi_save_received_token(iph1, gsstoken); | |
1317 | break; | |
1318 | #endif | |
1319 | case ISAKMP_NPTYPE_VID: | |
1320 | (void)check_vendorid(pa->ptr); | |
1321 | break; | |
1322 | case ISAKMP_NPTYPE_N: | |
1323 | isakmp_check_notify(pa->ptr, iph1); | |
1324 | break; | |
1325 | default: | |
1326 | /* don't send information, see ident_r1recv() */ | |
1327 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1328 | "ignore the packet, " | |
1329 | "received unexpecting payload type %d.\n", | |
1330 | pa->type); | |
1331 | goto end; | |
1332 | } | |
1333 | } | |
1334 | ||
1335 | /* payload existency check */ | |
1336 | /* XXX same as ident_i4recv(), should be merged. */ | |
1337 | { | |
1338 | int ng = 0; | |
1339 | ||
1340 | switch (iph1->approval->authmethod) { | |
1341 | case OAKLEY_ATTR_AUTH_METHOD_PSKEY: | |
1342 | if (iph1->id_p == NULL || iph1->pl_hash == NULL) | |
1343 | ng++; | |
1344 | break; | |
1345 | case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: | |
1346 | case OAKLEY_ATTR_AUTH_METHOD_RSASIG: | |
1347 | if (iph1->id_p == NULL || iph1->sig_p == NULL) | |
1348 | ng++; | |
1349 | break; | |
1350 | case OAKLEY_ATTR_AUTH_METHOD_RSAENC: | |
1351 | case OAKLEY_ATTR_AUTH_METHOD_RSAREV: | |
1352 | if (iph1->pl_hash == NULL) | |
1353 | ng++; | |
1354 | break; | |
1355 | #ifdef HAVE_GSSAPI | |
1356 | case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: | |
1357 | if (gsstoken == NULL && iph1->pl_hash == NULL) | |
1358 | ng++; | |
1359 | break; | |
1360 | #endif | |
1361 | default: | |
1362 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1363 | "invalid authmethod %d why ?\n", | |
1364 | iph1->approval->authmethod); | |
1365 | goto end; | |
1366 | } | |
1367 | if (ng) { | |
1368 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1369 | "few isakmp message received.\n"); | |
1370 | goto end; | |
1371 | } | |
1372 | } | |
1373 | ||
1374 | /* see handler.h about IV synchronization. */ | |
1375 | memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->ive->l); | |
1376 | ||
1377 | /* verify identifier */ | |
1378 | if (ipsecdoi_checkid1(iph1) != 0) { | |
1379 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1380 | "invalid ID payload.\n"); | |
1381 | goto end; | |
1382 | } | |
1383 | ||
1384 | /* validate authentication value */ | |
1385 | #ifdef HAVE_GSSAPI | |
1386 | if (gsstoken == NULL) { | |
1387 | #endif | |
1388 | type = oakley_validate_auth(iph1); | |
1389 | if (type != 0) { | |
1390 | if (type == -1) { | |
1391 | /* msg printed inner oakley_validate_auth() */ | |
1392 | goto end; | |
1393 | } | |
1394 | isakmp_info_send_n1(iph1, type, NULL); | |
1395 | goto end; | |
1396 | } | |
1397 | #ifdef HAVE_GSSAPI | |
1398 | } | |
1399 | #endif | |
1400 | ||
1401 | #ifdef HAVE_SIGNING_C | |
1402 | if (oakley_checkcr(iph1) < 0) { | |
1403 | /* Ignore this error in order to be interoperability. */ | |
1404 | ; | |
1405 | } | |
1406 | #endif | |
1407 | ||
1408 | /* | |
1409 | * XXX: Should we do compare two addresses, ph1handle's and ID | |
1410 | * payload's. | |
1411 | */ | |
1412 | ||
1413 | plog(LLV_DEBUG, LOCATION, iph1->remote, "peer's ID\n"); | |
1414 | plogdump(LLV_DEBUG, iph1->id_p->v, iph1->id_p->l); | |
1415 | ||
1416 | #ifdef HAVE_GSSAPI | |
1417 | iph1->status = gsstoken != NULL ? PHASE1ST_MSG2RECEIVED : | |
1418 | PHASE1ST_MSG3RECEIVED; | |
1419 | #else | |
1420 | iph1->status = PHASE1ST_MSG3RECEIVED; | |
1421 | #endif | |
1422 | ||
1423 | error = 0; | |
1424 | ||
1425 | end: | |
1426 | if (pbuf) | |
1427 | vfree(pbuf); | |
1428 | if (msg) | |
1429 | vfree(msg); | |
1430 | #ifdef HAVE_GSSAPI | |
1431 | if (gsstoken) | |
1432 | vfree(gsstoken); | |
1433 | #endif | |
1434 | ||
1435 | if (error) { | |
1436 | VPTRINIT(iph1->id_p); | |
1437 | oakley_delcert(iph1->cert_p); | |
1438 | iph1->cert_p = NULL; | |
1439 | oakley_delcert(iph1->crl_p); | |
1440 | iph1->crl_p = NULL; | |
1441 | VPTRINIT(iph1->sig_p); | |
1442 | oakley_delcert(iph1->cr_p); | |
1443 | iph1->cr_p = NULL; | |
1444 | } | |
1445 | ||
1446 | return error; | |
1447 | } | |
1448 | ||
1449 | /* | |
1450 | * send to initiator | |
1451 | * psk: HDR*, IDr1, HASH_R | |
1452 | * sig: HDR*, IDr1, [ CERT, ] SIG_R | |
1453 | * gssapi: HDR*, IDr1, < GSSr(n) | HASH_R > | |
1454 | * rsa: HDR*, HASH_R | |
1455 | * rev: HDR*, HASH_R | |
1456 | */ | |
1457 | int | |
1458 | ident_r3send(iph1, msg) | |
1459 | struct ph1handle *iph1; | |
1460 | vchar_t *msg; | |
1461 | { | |
1462 | int error = -1; | |
1463 | int dohash = 1; | |
1464 | #ifdef HAVE_GSSAPI | |
1465 | int len; | |
1466 | #endif | |
1467 | ||
1468 | /* validity check */ | |
1469 | if (iph1->status != PHASE1ST_MSG3RECEIVED) { | |
1470 | plog(LLV_ERROR, LOCATION, NULL, | |
1471 | "status mismatched %d.\n", iph1->status); | |
1472 | goto end; | |
1473 | } | |
1474 | ||
1475 | /* make ID payload into isakmp status */ | |
1476 | if (ipsecdoi_setid1(iph1) < 0) | |
1477 | goto end; | |
1478 | ||
1479 | #ifdef HAVE_GSSAPI | |
1480 | if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB && | |
1481 | gssapi_more_tokens(iph1)) { | |
1482 | gssapi_get_rtoken(iph1, &len); | |
1483 | if (len != 0) | |
1484 | dohash = 0; | |
1485 | } | |
1486 | #endif | |
1487 | ||
1488 | if (dohash) { | |
1489 | /* generate HASH to send */ | |
1490 | plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_R\n"); | |
1491 | iph1->hash = oakley_ph1hash_common(iph1, GENERATE); | |
1492 | if (iph1->hash == NULL) | |
1493 | goto end; | |
1494 | } else | |
1495 | iph1->hash = NULL; | |
1496 | ||
1497 | /* set encryption flag */ | |
1498 | iph1->flags |= ISAKMP_FLAG_E; | |
1499 | ||
1500 | /* create HDR;ID;HASH payload */ | |
1501 | iph1->sendbuf = ident_ir3mx(iph1); | |
1502 | if (iph1->sendbuf == NULL) | |
1503 | goto end; | |
1504 | ||
1505 | /* send HDR;ID;HASH to responder */ | |
1506 | if (isakmp_send(iph1, iph1->sendbuf) < 0) | |
1507 | goto end; | |
1508 | ||
1509 | /* the sending message is added to the received-list. */ | |
1510 | if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) { | |
1511 | plog(LLV_ERROR , LOCATION, NULL, | |
1512 | "failed to add a response packet to the tree.\n"); | |
1513 | goto end; | |
1514 | } | |
1515 | ||
1516 | /* see handler.h about IV synchronization. */ | |
1517 | memcpy(iph1->ivm->ive->v, iph1->ivm->iv->v, iph1->ivm->iv->l); | |
1518 | ||
1519 | iph1->status = PHASE1ST_ESTABLISHED; | |
1520 | ||
1521 | error = 0; | |
1522 | ||
1523 | end: | |
1524 | ||
1525 | return error; | |
1526 | } | |
1527 | ||
1528 | /* | |
1529 | * This is used in main mode for: | |
1530 | * initiator's 3rd exchange send to responder | |
1531 | * psk: HDR, KE, Ni | |
1532 | * sig: HDR, KE, Ni | |
1533 | * rsa: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r | |
1534 | * rev: HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, | |
1535 | * <IDi1_b>Ke_i, [<<Cert-I_b>Ke_i] | |
1536 | * responders 2nd exchnage send to initiator | |
1537 | * psk: HDR, KE, Nr | |
1538 | * sig: HDR, KE, Nr [, CR ] | |
1539 | * rsa: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i | |
1540 | * rev: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r, | |
1541 | */ | |
1542 | static vchar_t * | |
1543 | ident_ir2mx(iph1) | |
1544 | struct ph1handle *iph1; | |
1545 | { | |
1546 | vchar_t *buf = 0; | |
1547 | struct isakmp_gen *gen; | |
1548 | char *p; | |
1549 | int tlen; | |
1550 | int need_cr = 0; | |
1551 | vchar_t *cr = NULL; | |
1552 | vchar_t *vid = NULL; | |
1553 | int error = -1; | |
1554 | int nptype; | |
1555 | #ifdef HAVE_GSSAPI | |
1556 | vchar_t *gsstoken = NULL; | |
1557 | #endif | |
ffda1f4a | 1558 | int natd_type = 0; |
7ba0088d A |
1559 | |
1560 | #ifdef HAVE_SIGNING_C | |
1561 | /* create CR if need */ | |
1562 | if (iph1->side == RESPONDER | |
1563 | && iph1->rmconf->send_cr | |
1564 | && oakley_needcr(iph1->approval->authmethod) | |
1565 | && iph1->rmconf->peerscertfile == NULL) { | |
1566 | need_cr = 1; | |
1567 | cr = oakley_getcr(iph1); | |
1568 | if (cr == NULL) { | |
1569 | plog(LLV_ERROR, LOCATION, NULL, | |
1570 | "failed to get cr buffer.\n"); | |
1571 | goto end; | |
1572 | } | |
1573 | } | |
1574 | #endif | |
1575 | ||
1576 | #ifdef HAVE_GSSAPI | |
1577 | if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) | |
1578 | gssapi_get_token_to_send(iph1, &gsstoken); | |
1579 | #endif | |
1580 | ||
1581 | /* create buffer */ | |
1582 | tlen = sizeof(struct isakmp) | |
1583 | + sizeof(*gen) + iph1->dhpub->l | |
1584 | + sizeof(*gen) + iph1->nonce->l; | |
1585 | if ((vid = set_vendorid(iph1->approval->vendorid)) != NULL) | |
1586 | tlen += sizeof(*gen) + vid->l; | |
1587 | if (need_cr) | |
1588 | tlen += sizeof(*gen) + cr->l; | |
1589 | #ifdef HAVE_GSSAPI | |
1590 | if (gsstoken) | |
1591 | tlen += sizeof(*gen) + gsstoken->l; | |
1592 | #endif | |
1593 | ||
ac2f15b3 | 1594 | #ifdef IKE_NAT_T |
ffda1f4a A |
1595 | if ((iph1->natt_flags & NATT_TYPE_MASK) != 0) { |
1596 | natd_type = iph1->natd_payload_type; | |
ac2f15b3 A |
1597 | natd_create(iph1); |
1598 | if (iph1->local_natd) | |
1599 | tlen += sizeof(*gen) + iph1->local_natd->l; | |
1600 | if (iph1->remote_natd) | |
1601 | tlen += sizeof(*gen) + iph1->remote_natd->l; | |
1602 | } | |
1603 | #endif | |
1604 | ||
7ba0088d A |
1605 | buf = vmalloc(tlen); |
1606 | if (buf == NULL) { | |
1607 | plog(LLV_ERROR, LOCATION, NULL, | |
1608 | "failed to get buffer to send.\n"); | |
1609 | goto end; | |
1610 | } | |
1611 | ||
1612 | /* set isakmp header */ | |
1613 | p = set_isakmp_header(buf, iph1, ISAKMP_NPTYPE_KE); | |
1614 | if (p == NULL) | |
1615 | goto end; | |
1616 | ||
1617 | /* create isakmp KE payload */ | |
1618 | p = set_isakmp_payload(p, iph1->dhpub, ISAKMP_NPTYPE_NONCE); | |
1619 | ||
1620 | /* create isakmp NONCE payload */ | |
1621 | #ifdef HAVE_GSSAPI | |
1622 | if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) | |
1623 | nptype = ISAKMP_NPTYPE_GSS; | |
1624 | else | |
1625 | #endif | |
1626 | nptype = vid ? ISAKMP_NPTYPE_VID : | |
ac2f15b3 | 1627 | (need_cr ? ISAKMP_NPTYPE_CR : |
ffda1f4a | 1628 | (natd_type ? natd_type : ISAKMP_NPTYPE_NONE)); |
7ba0088d A |
1629 | p = set_isakmp_payload(p, iph1->nonce, nptype); |
1630 | ||
1631 | #ifdef HAVE_GSSAPI | |
1632 | if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) { | |
1633 | p = set_isakmp_payload(p, gsstoken, | |
1634 | vid ? ISAKMP_NPTYPE_VID | |
1635 | : (need_cr ? ISAKMP_NPTYPE_CR | |
ffda1f4a | 1636 | : (natd_type ? natd_type : ISAKMP_NPTYPE_NONE))); |
7ba0088d A |
1637 | } |
1638 | #endif | |
1639 | ||
1640 | /* append vendor id, if needed */ | |
1641 | if (vid) | |
1642 | p = set_isakmp_payload(p, vid, | |
1643 | need_cr ? ISAKMP_NPTYPE_CR | |
ffda1f4a | 1644 | : (natd_type ? natd_type : ISAKMP_NPTYPE_NONE)); |
7ba0088d A |
1645 | |
1646 | /* create isakmp CR payload if needed */ | |
1647 | if (need_cr) | |
ffda1f4a | 1648 | p = set_isakmp_payload(p, cr, natd_type ? natd_type : ISAKMP_NPTYPE_NONE); |
ac2f15b3 A |
1649 | |
1650 | #ifdef IKE_NAT_T | |
ffda1f4a | 1651 | if (natd_type) { |
3a228055 A |
1652 | if ((iph1->natt_flags & NATT_TYPE_MASK) == natt_type_apple) { |
1653 | if (iph1->local_natd) | |
1654 | p = set_isakmp_payload(p, iph1->local_natd, natd_type); | |
1655 | if (iph1->remote_natd) | |
1656 | p = set_isakmp_payload(p, iph1->remote_natd, ISAKMP_NPTYPE_NONE); | |
1657 | } else { | |
1658 | if (iph1->remote_natd) | |
1659 | p = set_isakmp_payload(p, iph1->remote_natd, natd_type); | |
1660 | if (iph1->local_natd) | |
1661 | p = set_isakmp_payload(p, iph1->local_natd, ISAKMP_NPTYPE_NONE); | |
1662 | } | |
ac2f15b3 A |
1663 | } |
1664 | #endif | |
7ba0088d A |
1665 | error = 0; |
1666 | ||
1667 | end: | |
1668 | if (error && buf != NULL) { | |
1669 | vfree(buf); | |
1670 | buf = NULL; | |
1671 | } | |
1672 | if (cr) | |
1673 | vfree(cr); | |
1674 | #ifdef HAVE_GSSAPI | |
1675 | if (gsstoken) | |
1676 | vfree(gsstoken); | |
1677 | #endif | |
1678 | if (vid) | |
1679 | vfree(vid); | |
1680 | ||
1681 | return buf; | |
1682 | } | |
1683 | ||
1684 | /* | |
1685 | * This is used in main mode for: | |
1686 | * initiator's 4th exchange send to responder | |
1687 | * psk: HDR*, IDi1, HASH_I | |
1688 | * sig: HDR*, IDi1, [ CR, ] [ CERT, ] SIG_I | |
1689 | * gssapi: HDR*, [ IDi1, ] < GSSi(n) | HASH_I > | |
1690 | * rsa: HDR*, HASH_I | |
1691 | * rev: HDR*, HASH_I | |
1692 | * responders 3rd exchnage send to initiator | |
1693 | * psk: HDR*, IDr1, HASH_R | |
1694 | * sig: HDR*, IDr1, [ CERT, ] SIG_R | |
1695 | * gssapi: HDR*, [ IDr1, ] < GSSr(n) | HASH_R > | |
1696 | * rsa: HDR*, HASH_R | |
1697 | * rev: HDR*, HASH_R | |
1698 | */ | |
1699 | static vchar_t * | |
1700 | ident_ir3mx(iph1) | |
1701 | struct ph1handle *iph1; | |
1702 | { | |
1703 | vchar_t *buf = NULL, *new = NULL; | |
1704 | char *p; | |
1705 | int tlen; | |
1706 | struct isakmp_gen *gen; | |
1707 | int need_cr = 0; | |
1708 | int need_cert = 0; | |
1709 | vchar_t *cr = NULL; | |
1710 | int error = -1; | |
1711 | #ifdef HAVE_GSSAPI | |
1712 | int nptype; | |
1713 | vchar_t *gsstoken = NULL; | |
1714 | vchar_t *gsshash = NULL; | |
1715 | #endif | |
1716 | ||
1717 | tlen = sizeof(struct isakmp); | |
1718 | ||
1719 | switch (iph1->approval->authmethod) { | |
1720 | case OAKLEY_ATTR_AUTH_METHOD_PSKEY: | |
1721 | tlen += sizeof(*gen) + iph1->id->l | |
1722 | + sizeof(*gen) + iph1->hash->l; | |
1723 | ||
1724 | buf = vmalloc(tlen); | |
1725 | if (buf == NULL) { | |
1726 | plog(LLV_ERROR, LOCATION, NULL, | |
1727 | "failed to get buffer to send.\n"); | |
1728 | goto end; | |
1729 | } | |
1730 | ||
1731 | /* set isakmp header */ | |
1732 | p = set_isakmp_header(buf, iph1, ISAKMP_NPTYPE_ID); | |
1733 | if (p == NULL) | |
1734 | goto end; | |
1735 | ||
1736 | /* create isakmp ID payload */ | |
1737 | p = set_isakmp_payload(p, iph1->id, ISAKMP_NPTYPE_HASH); | |
1738 | ||
1739 | /* create isakmp HASH payload */ | |
1740 | p = set_isakmp_payload(p, iph1->hash, ISAKMP_NPTYPE_NONE); | |
1741 | break; | |
1742 | #ifdef HAVE_SIGNING_C | |
1743 | case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: | |
1744 | case OAKLEY_ATTR_AUTH_METHOD_RSASIG: | |
1745 | if (oakley_getmycert(iph1) < 0) | |
1746 | goto end; | |
1747 | ||
1748 | if (oakley_getsign(iph1) < 0) | |
1749 | goto end; | |
1750 | ||
1751 | /* create CR if need */ | |
1752 | if (iph1->side == INITIATOR | |
1753 | && iph1->rmconf->send_cr | |
1754 | && oakley_needcr(iph1->approval->authmethod) | |
1755 | && iph1->rmconf->peerscertfile == NULL) { | |
1756 | need_cr = 1; | |
1757 | cr = oakley_getcr(iph1); | |
1758 | if (cr == NULL) { | |
1759 | plog(LLV_ERROR, LOCATION, NULL, | |
1760 | "failed to get cr buffer.\n"); | |
1761 | goto end; | |
1762 | } | |
1763 | } | |
1764 | ||
1765 | if (iph1->cert != NULL && iph1->rmconf->send_cert) | |
1766 | need_cert = 1; | |
1767 | ||
1768 | tlen += sizeof(*gen) + iph1->id->l | |
1769 | + sizeof(*gen) + iph1->sig->l; | |
1770 | if (need_cert) | |
1771 | tlen += sizeof(*gen) + iph1->cert->pl->l; | |
1772 | if (need_cr) | |
1773 | tlen += sizeof(*gen) + cr->l; | |
1774 | ||
1775 | buf = vmalloc(tlen); | |
1776 | if (buf == NULL) { | |
1777 | plog(LLV_ERROR, LOCATION, NULL, | |
1778 | "failed to get buffer to send.\n"); | |
1779 | goto end; | |
1780 | } | |
1781 | ||
1782 | /* set isakmp header */ | |
1783 | p = set_isakmp_header(buf, iph1, ISAKMP_NPTYPE_ID); | |
1784 | if (p == NULL) | |
1785 | goto end; | |
1786 | ||
1787 | /* add ID payload */ | |
1788 | p = set_isakmp_payload(p, iph1->id, need_cert | |
1789 | ? ISAKMP_NPTYPE_CERT | |
1790 | : ISAKMP_NPTYPE_SIG); | |
1791 | ||
1792 | /* add CERT payload if there */ | |
1793 | if (need_cert) | |
1794 | p = set_isakmp_payload(p, iph1->cert->pl, ISAKMP_NPTYPE_SIG); | |
1795 | /* add SIG payload */ | |
1796 | p = set_isakmp_payload(p, iph1->sig, | |
1797 | need_cr ? ISAKMP_NPTYPE_CR : ISAKMP_NPTYPE_NONE); | |
1798 | ||
1799 | /* create isakmp CR payload */ | |
1800 | if (need_cr) | |
1801 | p = set_isakmp_payload(p, cr, ISAKMP_NPTYPE_NONE); | |
1802 | break; | |
1803 | #endif | |
1804 | #ifdef HAVE_GSSAPI | |
1805 | case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: | |
1806 | if (!gssapi_id_sent(iph1)) | |
1807 | tlen += sizeof (*gen) + iph1->id->l; | |
1808 | if (iph1->hash != NULL) { | |
1809 | gsshash = gssapi_wraphash(iph1); | |
1810 | if (gsshash == NULL) | |
1811 | goto end; | |
1812 | tlen += sizeof (*gen) + gsshash->l; | |
1813 | } else { | |
1814 | gssapi_get_token_to_send(iph1, &gsstoken); | |
1815 | tlen += sizeof (*gen) + gsstoken->l; | |
1816 | } | |
1817 | ||
1818 | buf = vmalloc(tlen); | |
1819 | if (buf == NULL) { | |
1820 | plog(LLV_ERROR, LOCATION, NULL, | |
1821 | "failed to get buffer to send.\n"); | |
1822 | goto end; | |
1823 | } | |
1824 | ||
1825 | /* set isakmp header */ | |
1826 | if (!gssapi_id_sent(iph1)) | |
1827 | nptype = ISAKMP_NPTYPE_ID; | |
1828 | else | |
1829 | nptype = iph1->hash != NULL ? ISAKMP_NPTYPE_HASH : | |
1830 | ISAKMP_NPTYPE_GSS; | |
1831 | p = set_isakmp_header(buf, iph1, nptype); | |
1832 | if (p == NULL) | |
1833 | goto end; | |
1834 | ||
1835 | if (!gssapi_id_sent(iph1)) { | |
1836 | /* create isakmp ID payload */ | |
1837 | nptype = iph1->hash != NULL ? ISAKMP_NPTYPE_HASH : | |
1838 | ISAKMP_NPTYPE_GSS; | |
1839 | p = set_isakmp_payload(p, iph1->id, nptype); | |
1840 | if (p == NULL) | |
1841 | goto end; | |
1842 | gssapi_set_id_sent(iph1); | |
1843 | } | |
1844 | ||
1845 | if (iph1->hash != NULL) | |
1846 | /* create isakmp HASH payload */ | |
1847 | p = set_isakmp_payload(p, gsshash, | |
1848 | ISAKMP_NPTYPE_NONE); | |
1849 | else | |
1850 | p = set_isakmp_payload(p, gsstoken, ISAKMP_NPTYPE_NONE); | |
1851 | break; | |
1852 | #endif | |
1853 | case OAKLEY_ATTR_AUTH_METHOD_RSAENC: | |
1854 | case OAKLEY_ATTR_AUTH_METHOD_RSAREV: | |
1855 | plog(LLV_ERROR, LOCATION, NULL, | |
1856 | "not supported authentication type %d\n", | |
1857 | iph1->approval->authmethod); | |
1858 | goto end; | |
1859 | default: | |
1860 | plog(LLV_ERROR, LOCATION, NULL, | |
1861 | "invalid authentication type %d\n", | |
1862 | iph1->approval->authmethod); | |
1863 | goto end; | |
1864 | } | |
1865 | ||
1866 | #ifdef HAVE_PRINT_ISAKMP_C | |
1867 | isakmp_printpacket(buf, iph1->local, iph1->remote, 1); | |
1868 | #endif | |
1869 | ||
1870 | /* encoding */ | |
1871 | new = oakley_do_encrypt(iph1, buf, iph1->ivm->ive, iph1->ivm->iv); | |
1872 | if (new == NULL) | |
1873 | goto end; | |
1874 | ||
1875 | vfree(buf); | |
1876 | ||
1877 | buf = new; | |
1878 | ||
1879 | error = 0; | |
1880 | ||
1881 | end: | |
1882 | if (cr) | |
1883 | vfree(cr); | |
1884 | if (error && buf != NULL) { | |
1885 | vfree(buf); | |
1886 | buf = NULL; | |
1887 | } | |
1888 | ||
1889 | return buf; | |
1890 | } |