]>
Commit | Line | Data |
---|---|---|
52b7d2ce A |
1 | /* $KAME: isakmp_base.c,v 1.49 2003/11/13 02:30:20 sakane 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 | /* Base Exchange (Base Mode) */ | |
33 | ||
34 | #include "config.h" | |
35 | ||
36 | #include <sys/types.h> | |
37 | #include <sys/param.h> | |
38 | ||
39 | #include <stdlib.h> | |
40 | #include <stdio.h> | |
41 | #include <string.h> | |
42 | #include <errno.h> | |
43 | #if TIME_WITH_SYS_TIME | |
44 | # include <sys/time.h> | |
45 | # include <time.h> | |
46 | #else | |
47 | # if HAVE_SYS_TIME_H | |
48 | # include <sys/time.h> | |
49 | # else | |
50 | # include <time.h> | |
51 | # endif | |
52 | #endif | |
53 | ||
54 | #include "var.h" | |
55 | #include "misc.h" | |
56 | #include "vmbuf.h" | |
57 | #include "plog.h" | |
58 | #include "sockmisc.h" | |
59 | #include "schedule.h" | |
60 | #include "debug.h" | |
61 | ||
62 | #include "localconf.h" | |
63 | #include "remoteconf.h" | |
64 | #include "isakmp_var.h" | |
65 | #include "isakmp.h" | |
66 | #include "evt.h" | |
67 | #include "oakley.h" | |
68 | #include "handler.h" | |
69 | #include "ipsec_doi.h" | |
70 | #include "crypto_openssl.h" | |
71 | #include "pfkey.h" | |
72 | #include "isakmp_base.h" | |
73 | #include "isakmp_inf.h" | |
74 | #include "vendorid.h" | |
75 | #ifdef ENABLE_NATT | |
76 | #include "nattraversal.h" | |
77 | #endif | |
78 | #ifdef ENABLE_FRAG | |
79 | #include "isakmp_frag.h" | |
80 | #endif | |
81 | #include "vpn_control.h" | |
82 | #include "vpn_control_var.h" | |
83 | ||
84 | /* %%% | |
85 | * begin Identity Protection Mode as initiator. | |
86 | */ | |
87 | /* | |
88 | * send to responder | |
89 | * psk: HDR, SA, Idii, Ni_b | |
90 | * sig: HDR, SA, Idii, Ni_b | |
91 | * rsa: HDR, SA, [HASH(1),] <IDii_b>Pubkey_r, <Ni_b>Pubkey_r | |
92 | * rev: HDR, SA, [HASH(1),] <Ni_b>Pubkey_r, <IDii_b>Ke_i | |
93 | */ | |
94 | int | |
95 | base_i1send(iph1, msg) | |
96 | struct ph1handle *iph1; | |
97 | vchar_t *msg; /* must be null */ | |
98 | { | |
99 | struct payload_list *plist = NULL; | |
100 | int error = -1; | |
101 | #ifdef ENABLE_NATT | |
102 | vchar_t *vid_natt[MAX_NATT_VID_COUNT] = { NULL }; | |
103 | int i, vid_natt_i = 0; | |
104 | #endif | |
105 | #ifdef ENABLE_FRAG | |
106 | vchar_t *vid_frag = NULL; | |
107 | #endif | |
108 | ||
109 | /* validity check */ | |
110 | if (msg != NULL) { | |
111 | plog(LLV_ERROR, LOCATION, NULL, | |
112 | "msg has to be NULL in this function.\n"); | |
113 | goto end; | |
114 | } | |
115 | if (iph1->status != PHASE1ST_START) { | |
116 | plog(LLV_ERROR, LOCATION, NULL, | |
117 | "status mismatched %d.\n", iph1->status); | |
118 | goto end; | |
119 | } | |
120 | ||
121 | /* create isakmp index */ | |
122 | memset(&iph1->index, 0, sizeof(iph1->index)); | |
123 | isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local); | |
124 | ||
125 | /* make ID payload into isakmp status */ | |
126 | if (ipsecdoi_setid1(iph1) < 0) | |
127 | goto end; | |
128 | ||
129 | /* create SA payload for my proposal */ | |
130 | iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal); | |
131 | if (iph1->sa == NULL) | |
132 | goto end; | |
133 | ||
134 | /* generate NONCE value */ | |
135 | iph1->nonce = eay_set_random(iph1->rmconf->nonce_size); | |
136 | if (iph1->nonce == NULL) | |
137 | goto end; | |
138 | ||
139 | #ifdef ENABLE_FRAG | |
140 | if (iph1->rmconf->ike_frag) { | |
141 | vid_frag = set_vendorid(VENDORID_FRAG); | |
142 | if (vid_frag != NULL) | |
143 | vid_frag = isakmp_frag_addcap(vid_frag, | |
144 | VENDORID_FRAG_BASE); | |
145 | if (vid_frag == NULL) | |
146 | plog(LLV_ERROR, LOCATION, NULL, | |
147 | "Frag vendorID construction failed\n"); | |
148 | } | |
149 | #endif | |
150 | #ifdef ENABLE_NATT | |
151 | /* Is NAT-T support allowed in the config file? */ | |
152 | if (iph1->rmconf->nat_traversal) { | |
153 | /* Advertise NAT-T capability */ | |
154 | memset (vid_natt, 0, sizeof (vid_natt)); | |
155 | #ifdef VENDORID_NATT_00 | |
156 | if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_00)) != NULL) | |
157 | vid_natt_i++; | |
158 | #endif | |
159 | #ifdef VENDORID_NATT_02 | |
160 | if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02)) != NULL) | |
161 | vid_natt_i++; | |
162 | #endif | |
163 | #ifdef VENDORID_NATT_02_N | |
164 | if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_02_N)) != NULL) | |
165 | vid_natt_i++; | |
166 | #endif | |
167 | #ifdef VENDORID_NATT_RFC | |
168 | if ((vid_natt[vid_natt_i] = set_vendorid(VENDORID_NATT_RFC)) != NULL) | |
169 | vid_natt_i++; | |
170 | #endif | |
171 | } | |
172 | #endif | |
173 | ||
174 | /* set SA payload to propose */ | |
175 | plist = isakmp_plist_append(plist, iph1->sa, ISAKMP_NPTYPE_SA); | |
176 | ||
177 | /* create isakmp ID payload */ | |
178 | plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID); | |
179 | ||
180 | /* create isakmp NONCE payload */ | |
181 | plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE); | |
182 | ||
183 | #ifdef ENABLE_FRAG | |
184 | if (vid_frag) | |
185 | plist = isakmp_plist_append(plist, vid_frag, ISAKMP_NPTYPE_VID); | |
186 | #endif | |
187 | #ifdef ENABLE_NATT | |
188 | /* set VID payload for NAT-T */ | |
189 | for (i = 0; i < vid_natt_i; i++) | |
190 | plist = isakmp_plist_append(plist, vid_natt[i], ISAKMP_NPTYPE_VID); | |
191 | ||
192 | iph1->sendbuf = isakmp_plist_set_all (&plist, iph1); | |
193 | #endif | |
194 | ||
195 | #ifdef HAVE_PRINT_ISAKMP_C | |
196 | isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0); | |
197 | #endif | |
198 | ||
199 | /* send the packet, add to the schedule to resend */ | |
200 | iph1->retry_counter = iph1->rmconf->retry_counter; | |
201 | if (isakmp_ph1resend(iph1) == -1) | |
202 | goto end; | |
203 | ||
204 | iph1->status = PHASE1ST_MSG1SENT; | |
205 | ||
206 | error = 0; | |
207 | ||
208 | end: | |
209 | #ifdef ENABLE_FRAG | |
210 | if (vid_frag) | |
211 | vfree(vid_frag); | |
212 | #endif | |
213 | #ifdef ENABLE_NATT | |
214 | for (i = 0; i < vid_natt_i; i++) | |
215 | vfree(vid_natt[i]); | |
216 | #endif | |
217 | ||
218 | return error; | |
219 | } | |
220 | ||
221 | /* | |
222 | * receive from responder | |
223 | * psk: HDR, SA, Idir, Nr_b | |
224 | * sig: HDR, SA, Idir, Nr_b, [ CR ] | |
225 | * rsa: HDR, SA, <IDir_b>PubKey_i, <Nr_b>PubKey_i | |
226 | * rev: HDR, SA, <Nr_b>PubKey_i, <IDir_b>Ke_r | |
227 | */ | |
228 | int | |
229 | base_i2recv(iph1, msg) | |
230 | struct ph1handle *iph1; | |
231 | vchar_t *msg; | |
232 | { | |
233 | vchar_t *pbuf = NULL; | |
234 | struct isakmp_parse_t *pa; | |
235 | vchar_t *satmp = NULL; | |
236 | int error = -1; | |
237 | int vid_numeric; | |
238 | ||
239 | /* validity check */ | |
240 | if (iph1->status != PHASE1ST_MSG1SENT) { | |
241 | plog(LLV_ERROR, LOCATION, NULL, | |
242 | "status mismatched %d.\n", iph1->status); | |
243 | goto end; | |
244 | } | |
245 | ||
246 | /* validate the type of next payload */ | |
247 | pbuf = isakmp_parse(msg); | |
248 | if (pbuf == NULL) | |
249 | goto end; | |
250 | pa = (struct isakmp_parse_t *)pbuf->v; | |
251 | ||
252 | /* SA payload is fixed postion */ | |
253 | if (pa->type != ISAKMP_NPTYPE_SA) { | |
254 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
255 | "received invalid next payload type %d, " | |
256 | "expecting %d.\n", | |
257 | pa->type, ISAKMP_NPTYPE_SA); | |
258 | goto end; | |
259 | } | |
260 | if (isakmp_p2ph(&satmp, pa->ptr) < 0) | |
261 | goto end; | |
262 | pa++; | |
263 | ||
264 | for (/*nothing*/; | |
265 | pa->type != ISAKMP_NPTYPE_NONE; | |
266 | pa++) { | |
267 | ||
268 | switch (pa->type) { | |
269 | case ISAKMP_NPTYPE_NONCE: | |
270 | if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0) | |
271 | goto end; | |
272 | break; | |
273 | case ISAKMP_NPTYPE_ID: | |
274 | if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0) | |
275 | goto end; | |
276 | break; | |
277 | case ISAKMP_NPTYPE_VID: | |
278 | vid_numeric = check_vendorid(pa->ptr); | |
279 | #ifdef ENABLE_NATT | |
280 | if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric)) | |
281 | natt_handle_vendorid(iph1, vid_numeric); | |
282 | #endif | |
283 | break; | |
284 | default: | |
285 | /* don't send information, see ident_r1recv() */ | |
286 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
287 | "ignore the packet, " | |
288 | "received unexpecting payload type %d.\n", | |
289 | pa->type); | |
290 | goto end; | |
291 | } | |
292 | } | |
293 | ||
294 | if (iph1->nonce_p == NULL || iph1->id_p == NULL) { | |
295 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
296 | "few isakmp message received.\n"); | |
297 | goto end; | |
298 | } | |
299 | ||
300 | /* verify identifier */ | |
301 | if (ipsecdoi_checkid1(iph1) != 0) { | |
302 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
303 | "invalid ID payload.\n"); | |
304 | goto end; | |
305 | } | |
306 | ||
307 | #ifdef ENABLE_NATT | |
308 | if (NATT_AVAILABLE(iph1)) | |
309 | plog(LLV_INFO, LOCATION, iph1->remote, | |
310 | "Selected NAT-T version: %s\n", | |
311 | vid_string_by_id(iph1->natt_options->version)); | |
312 | #endif | |
313 | ||
314 | /* check SA payload and set approval SA for use */ | |
315 | if (ipsecdoi_checkph1proposal(satmp, iph1) < 0) { | |
316 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
317 | "failed to get valid proposal.\n"); | |
318 | /* XXX send information */ | |
319 | goto end; | |
320 | } | |
321 | VPTRINIT(iph1->sa_ret); | |
322 | ||
323 | iph1->status = PHASE1ST_MSG2RECEIVED; | |
324 | ||
325 | #ifdef ENABLE_VPNCONTROL_PORT | |
326 | vpncontrol_notify_phase_change(1, FROM_REMOTE, iph1, NULL); | |
327 | #endif | |
328 | ||
329 | error = 0; | |
330 | ||
331 | end: | |
332 | if (pbuf) | |
333 | vfree(pbuf); | |
334 | if (satmp) | |
335 | vfree(satmp); | |
336 | ||
337 | if (error) { | |
338 | VPTRINIT(iph1->nonce_p); | |
339 | VPTRINIT(iph1->id_p); | |
340 | } | |
341 | ||
342 | return error; | |
343 | } | |
344 | ||
345 | /* | |
346 | * send to responder | |
347 | * psk: HDR, KE, HASH_I | |
348 | * sig: HDR, KE, [ CR, ] [CERT,] SIG_I | |
349 | * rsa: HDR, KE, HASH_I | |
350 | * rev: HDR, <KE>Ke_i, HASH_I | |
351 | */ | |
352 | int | |
353 | base_i2send(iph1, msg) | |
354 | struct ph1handle *iph1; | |
355 | vchar_t *msg; | |
356 | { | |
357 | struct payload_list *plist = NULL; | |
358 | vchar_t *vid = NULL; | |
359 | int need_cert = 0; | |
360 | int error = -1; | |
361 | ||
362 | /* validity check */ | |
363 | if (iph1->status != PHASE1ST_MSG2RECEIVED) { | |
364 | plog(LLV_ERROR, LOCATION, NULL, | |
365 | "status mismatched %d.\n", iph1->status); | |
366 | goto end; | |
367 | } | |
368 | ||
369 | /* fix isakmp index */ | |
370 | memcpy(&iph1->index.r_ck, &((struct isakmp *)msg->v)->r_ck, | |
371 | sizeof(cookie_t)); | |
372 | ||
373 | /* generate DH public value */ | |
374 | if (oakley_dh_generate(iph1->approval->dhgrp, | |
375 | &iph1->dhpub, &iph1->dhpriv) < 0) | |
376 | goto end; | |
377 | ||
378 | /* generate SKEYID to compute hash if not signature mode */ | |
379 | if (iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_RSASIG | |
380 | && iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_DSSSIG) { | |
381 | if (oakley_skeyid(iph1) < 0) | |
382 | goto end; | |
383 | } | |
384 | ||
385 | /* generate HASH to send */ | |
386 | plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n"); | |
387 | iph1->hash = oakley_ph1hash_base_i(iph1, GENERATE); | |
388 | if (iph1->hash == NULL) | |
389 | goto end; | |
390 | ||
391 | switch (iph1->approval->authmethod) { | |
392 | case OAKLEY_ATTR_AUTH_METHOD_PSKEY: | |
393 | vid = set_vendorid(iph1->approval->vendorid); | |
394 | ||
395 | /* create isakmp KE payload */ | |
396 | plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE); | |
397 | ||
398 | /* create isakmp HASH payload */ | |
399 | plist = isakmp_plist_append(plist, iph1->hash, ISAKMP_NPTYPE_HASH); | |
400 | ||
401 | /* append vendor id, if needed */ | |
402 | if (vid) | |
403 | plist = isakmp_plist_append(plist, vid, ISAKMP_NPTYPE_VID); | |
404 | break; | |
405 | case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: | |
406 | case OAKLEY_ATTR_AUTH_METHOD_RSASIG: | |
407 | /* XXX if there is CR or not ? */ | |
408 | ||
409 | if (oakley_getmycert(iph1) < 0) | |
410 | goto end; | |
411 | ||
412 | if (oakley_getsign(iph1) < 0) | |
413 | goto end; | |
414 | ||
415 | if (iph1->cert && iph1->rmconf->send_cert) | |
416 | need_cert = 1; | |
417 | ||
418 | /* create isakmp KE payload */ | |
419 | plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE); | |
420 | ||
421 | /* add CERT payload if there */ | |
422 | if (need_cert) | |
423 | plist = isakmp_plist_append(plist, iph1->cert->pl, ISAKMP_NPTYPE_CERT); | |
424 | ||
425 | /* add SIG payload */ | |
426 | plist = isakmp_plist_append(plist, iph1->sig, ISAKMP_NPTYPE_SIG); | |
427 | break; | |
428 | case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: | |
429 | /* ... */ | |
430 | break; | |
431 | case OAKLEY_ATTR_AUTH_METHOD_RSAENC: | |
432 | case OAKLEY_ATTR_AUTH_METHOD_RSAREV: | |
433 | break; | |
434 | default: | |
435 | plog(LLV_ERROR, LOCATION, NULL, "invalid authmethod %d\n", | |
436 | iph1->approval->authmethod); | |
437 | goto end; | |
438 | break; | |
439 | } | |
440 | ||
441 | #ifdef ENABLE_NATT | |
442 | /* generate NAT-D payloads */ | |
443 | if (NATT_AVAILABLE(iph1)) | |
444 | { | |
445 | vchar_t *natd[2] = { NULL, NULL }; | |
446 | ||
447 | plog (LLV_INFO, LOCATION, NULL, "Adding remote and local NAT-D payloads.\n"); | |
448 | if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) { | |
449 | plog(LLV_ERROR, LOCATION, NULL, | |
450 | "NAT-D hashing failed for %s\n", saddr2str(iph1->remote)); | |
451 | goto end; | |
452 | } | |
453 | ||
454 | if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) { | |
455 | plog(LLV_ERROR, LOCATION, NULL, | |
456 | "NAT-D hashing failed for %s\n", saddr2str(iph1->local)); | |
457 | goto end; | |
458 | } | |
459 | ||
460 | #ifdef __APPLE__ | |
461 | /* old Apple version sends natd payloads in the wrong order */ | |
462 | if (iph1->natt_options->version == VENDORID_NATT_APPLE) { | |
463 | plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d); | |
464 | plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d); | |
465 | } else | |
466 | #endif | |
467 | { | |
468 | plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d); | |
469 | plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d); | |
470 | } | |
471 | } | |
472 | #endif | |
473 | ||
474 | iph1->sendbuf = isakmp_plist_set_all (&plist, iph1); | |
475 | ||
476 | #ifdef HAVE_PRINT_ISAKMP_C | |
477 | isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0); | |
478 | #endif | |
479 | ||
480 | /* send the packet, add to the schedule to resend */ | |
481 | iph1->retry_counter = iph1->rmconf->retry_counter; | |
482 | if (isakmp_ph1resend(iph1) == -1) | |
483 | goto end; | |
484 | ||
485 | /* the sending message is added to the received-list. */ | |
486 | if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) { | |
487 | plog(LLV_ERROR , LOCATION, NULL, | |
488 | "failed to add a response packet to the tree.\n"); | |
489 | goto end; | |
490 | } | |
491 | ||
492 | iph1->status = PHASE1ST_MSG2SENT; | |
493 | ||
494 | error = 0; | |
495 | ||
496 | end: | |
497 | if (vid) | |
498 | vfree(vid); | |
499 | return error; | |
500 | } | |
501 | ||
502 | /* | |
503 | * receive from responder | |
504 | * psk: HDR, KE, HASH_R | |
505 | * sig: HDR, KE, [CERT,] SIG_R | |
506 | * rsa: HDR, KE, HASH_R | |
507 | * rev: HDR, <KE>_Ke_r, HASH_R | |
508 | */ | |
509 | int | |
510 | base_i3recv(iph1, msg) | |
511 | struct ph1handle *iph1; | |
512 | vchar_t *msg; | |
513 | { | |
514 | vchar_t *pbuf = NULL; | |
515 | struct isakmp_parse_t *pa; | |
516 | int error = -1; | |
517 | int ptype; | |
518 | #ifdef ENABLE_NATT | |
519 | vchar_t *natd_received; | |
520 | int natd_seq = 0, natd_verified; | |
521 | #endif | |
522 | ||
523 | /* validity check */ | |
524 | if (iph1->status != PHASE1ST_MSG2SENT) { | |
525 | plog(LLV_ERROR, LOCATION, NULL, | |
526 | "status mismatched %d.\n", iph1->status); | |
527 | goto end; | |
528 | } | |
529 | ||
530 | /* validate the type of next payload */ | |
531 | pbuf = isakmp_parse(msg); | |
532 | if (pbuf == NULL) | |
533 | goto end; | |
534 | ||
535 | for (pa = (struct isakmp_parse_t *)pbuf->v; | |
536 | pa->type != ISAKMP_NPTYPE_NONE; | |
537 | pa++) { | |
538 | ||
539 | switch (pa->type) { | |
540 | case ISAKMP_NPTYPE_KE: | |
541 | if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0) | |
542 | goto end; | |
543 | break; | |
544 | case ISAKMP_NPTYPE_HASH: | |
545 | iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr; | |
546 | break; | |
547 | case ISAKMP_NPTYPE_CERT: | |
548 | if (oakley_savecert(iph1, pa->ptr) < 0) | |
549 | goto end; | |
550 | break; | |
551 | case ISAKMP_NPTYPE_SIG: | |
552 | if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0) | |
553 | goto end; | |
554 | break; | |
555 | case ISAKMP_NPTYPE_VID: | |
556 | (void)check_vendorid(pa->ptr); | |
557 | break; | |
558 | ||
559 | #ifdef ENABLE_NATT | |
560 | case ISAKMP_NPTYPE_NATD_DRAFT: | |
561 | case ISAKMP_NPTYPE_NATD_RFC: | |
562 | #ifdef __APPLE__ | |
563 | case ISAKMP_NPTYPE_NATD_BADDRAFT: | |
564 | #endif | |
565 | if (NATT_AVAILABLE(iph1) && iph1->natt_options && | |
566 | pa->type == iph1->natt_options->payload_nat_d) { | |
567 | natd_received = NULL; | |
568 | if (isakmp_p2ph (&natd_received, pa->ptr) < 0) | |
569 | goto end; | |
570 | ||
571 | /* set both bits first so that we can clear them | |
572 | upon verifying hashes */ | |
573 | if (natd_seq == 0) | |
574 | iph1->natt_flags |= NAT_DETECTED; | |
575 | ||
576 | /* this function will clear appropriate bits bits | |
577 | from iph1->natt_flags */ | |
578 | natd_verified = natt_compare_addr_hash (iph1, | |
579 | natd_received, natd_seq++); | |
580 | ||
581 | plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n", | |
582 | natd_seq - 1, | |
583 | natd_verified ? "verified" : "doesn't match"); | |
584 | ||
585 | vfree (natd_received); | |
586 | break; | |
587 | } | |
588 | /* %%%% Be lenient here - some servers send natd payloads */ | |
589 | /* when no nat is detected */ | |
590 | break; | |
591 | #endif | |
592 | ||
593 | default: | |
594 | /* don't send information, see ident_r1recv() */ | |
595 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
596 | "ignore the packet, " | |
597 | "received unexpecting payload type %d.\n", | |
598 | pa->type); | |
599 | goto end; | |
600 | } | |
601 | } | |
602 | ||
603 | #ifdef ENABLE_NATT | |
604 | if (NATT_AVAILABLE(iph1)) { | |
605 | plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n", | |
606 | iph1->natt_flags & NAT_DETECTED ? | |
607 | "detected:" : "not detected", | |
608 | iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "", | |
609 | iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : ""); | |
610 | if (iph1->natt_flags & NAT_DETECTED) | |
611 | natt_float_ports (iph1); | |
612 | } | |
613 | #endif | |
614 | ||
615 | /* payload existency check */ | |
616 | /* validate authentication value */ | |
617 | ptype = oakley_validate_auth(iph1); | |
618 | if (ptype != 0) { | |
619 | if (ptype == -1) { | |
620 | /* message printed inner oakley_validate_auth() */ | |
621 | goto end; | |
622 | } | |
623 | EVT_PUSH(iph1->local, iph1->remote, | |
624 | EVTT_PEERPH1AUTH_FAILED, NULL); | |
625 | isakmp_info_send_n1(iph1, ptype, NULL); | |
626 | goto end; | |
627 | } | |
628 | ||
629 | /* compute sharing secret of DH */ | |
630 | if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub, | |
631 | iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0) | |
632 | goto end; | |
633 | ||
634 | /* generate SKEYID to compute hash if signature mode */ | |
635 | if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_RSASIG | |
636 | || iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_DSSSIG) { | |
637 | if (oakley_skeyid(iph1) < 0) | |
638 | goto end; | |
639 | } | |
640 | ||
641 | /* generate SKEYIDs & IV & final cipher key */ | |
642 | if (oakley_skeyid_dae(iph1) < 0) | |
643 | goto end; | |
644 | if (oakley_compute_enckey(iph1) < 0) | |
645 | goto end; | |
646 | if (oakley_newiv(iph1) < 0) | |
647 | goto end; | |
648 | ||
649 | /* see handler.h about IV synchronization. */ | |
650 | memcpy(iph1->ivm->iv->v, iph1->ivm->ive->v, iph1->ivm->iv->l); | |
651 | ||
652 | /* set encryption flag */ | |
653 | iph1->flags |= ISAKMP_FLAG_E; | |
654 | ||
655 | iph1->status = PHASE1ST_MSG3RECEIVED; | |
656 | ||
657 | error = 0; | |
658 | ||
659 | end: | |
660 | if (pbuf) | |
661 | vfree(pbuf); | |
662 | ||
663 | if (error) { | |
664 | VPTRINIT(iph1->dhpub_p); | |
665 | oakley_delcert(iph1->cert_p); | |
666 | iph1->cert_p = NULL; | |
667 | oakley_delcert(iph1->crl_p); | |
668 | iph1->crl_p = NULL; | |
669 | VPTRINIT(iph1->sig_p); | |
670 | } | |
671 | ||
672 | return error; | |
673 | } | |
674 | ||
675 | /* | |
676 | * status update and establish isakmp sa. | |
677 | */ | |
678 | int | |
679 | base_i3send(iph1, msg) | |
680 | struct ph1handle *iph1; | |
681 | vchar_t *msg; | |
682 | { | |
683 | int error = -1; | |
684 | ||
685 | /* validity check */ | |
686 | if (iph1->status != PHASE1ST_MSG3RECEIVED) { | |
687 | plog(LLV_ERROR, LOCATION, NULL, | |
688 | "status mismatched %d.\n", iph1->status); | |
689 | goto end; | |
690 | } | |
691 | ||
692 | iph1->status = PHASE1ST_ESTABLISHED; | |
693 | ||
694 | error = 0; | |
695 | ||
696 | end: | |
697 | return error; | |
698 | } | |
699 | ||
700 | /* | |
701 | * receive from initiator | |
702 | * psk: HDR, SA, Idii, Ni_b | |
703 | * sig: HDR, SA, Idii, Ni_b | |
704 | * rsa: HDR, SA, [HASH(1),] <IDii_b>Pubkey_r, <Ni_b>Pubkey_r | |
705 | * rev: HDR, SA, [HASH(1),] <Ni_b>Pubkey_r, <IDii_b>Ke_i | |
706 | */ | |
707 | int | |
708 | base_r1recv(iph1, msg) | |
709 | struct ph1handle *iph1; | |
710 | vchar_t *msg; | |
711 | { | |
712 | vchar_t *pbuf = NULL; | |
713 | struct isakmp_parse_t *pa; | |
714 | int error = -1; | |
715 | int vid_numeric; | |
716 | ||
717 | /* validity check */ | |
718 | if (iph1->status != PHASE1ST_START) { | |
719 | plog(LLV_ERROR, LOCATION, NULL, | |
720 | "status mismatched %d.\n", iph1->status); | |
721 | goto end; | |
722 | } | |
723 | ||
724 | /* validate the type of next payload */ | |
725 | /* | |
726 | * NOTE: XXX even if multiple VID, we'll silently ignore those. | |
727 | */ | |
728 | pbuf = isakmp_parse(msg); | |
729 | if (pbuf == NULL) | |
730 | goto end; | |
731 | pa = (struct isakmp_parse_t *)pbuf->v; | |
732 | ||
733 | /* check the position of SA payload */ | |
734 | if (pa->type != ISAKMP_NPTYPE_SA) { | |
735 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
736 | "received invalid next payload type %d, " | |
737 | "expecting %d.\n", | |
738 | pa->type, ISAKMP_NPTYPE_SA); | |
739 | goto end; | |
740 | } | |
741 | if (isakmp_p2ph(&iph1->sa, pa->ptr) < 0) | |
742 | goto end; | |
743 | pa++; | |
744 | ||
745 | for (/*nothing*/; | |
746 | pa->type != ISAKMP_NPTYPE_NONE; | |
747 | pa++) { | |
748 | ||
749 | switch (pa->type) { | |
750 | case ISAKMP_NPTYPE_NONCE: | |
751 | if (isakmp_p2ph(&iph1->nonce_p, pa->ptr) < 0) | |
752 | goto end; | |
753 | break; | |
754 | case ISAKMP_NPTYPE_ID: | |
755 | if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0) | |
756 | goto end; | |
757 | break; | |
758 | case ISAKMP_NPTYPE_VID: | |
759 | vid_numeric = check_vendorid(pa->ptr); | |
760 | #ifdef ENABLE_NATT | |
761 | if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric)) | |
762 | natt_handle_vendorid(iph1, vid_numeric); | |
763 | #endif | |
764 | #ifdef ENABLE_FRAG | |
765 | if ((vid_numeric == VENDORID_FRAG) && | |
766 | (vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_BASE)) | |
767 | iph1->frag = 1; | |
768 | #endif | |
769 | break; | |
770 | default: | |
771 | /* don't send information, see ident_r1recv() */ | |
772 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
773 | "ignore the packet, " | |
774 | "received unexpecting payload type %d.\n", | |
775 | pa->type); | |
776 | goto end; | |
777 | } | |
778 | } | |
779 | ||
780 | if (iph1->nonce_p == NULL || iph1->id_p == NULL) { | |
781 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
782 | "few isakmp message received.\n"); | |
783 | goto end; | |
784 | } | |
785 | ||
786 | /* verify identifier */ | |
787 | if (ipsecdoi_checkid1(iph1) != 0) { | |
788 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
789 | "invalid ID payload.\n"); | |
790 | goto end; | |
791 | } | |
792 | ||
793 | #ifdef ENABLE_NATT | |
794 | if (NATT_AVAILABLE(iph1)) | |
795 | plog(LLV_INFO, LOCATION, iph1->remote, | |
796 | "Selected NAT-T version: %s\n", | |
797 | vid_string_by_id(iph1->natt_options->version)); | |
798 | #endif | |
799 | ||
800 | /* check SA payload and set approval SA for use */ | |
801 | if (ipsecdoi_checkph1proposal(iph1->sa, iph1) < 0) { | |
802 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
803 | "failed to get valid proposal.\n"); | |
804 | /* XXX send information */ | |
805 | goto end; | |
806 | } | |
807 | ||
808 | iph1->status = PHASE1ST_MSG1RECEIVED; | |
809 | ||
810 | error = 0; | |
811 | ||
812 | end: | |
813 | if (pbuf) | |
814 | vfree(pbuf); | |
815 | ||
816 | if (error) { | |
817 | VPTRINIT(iph1->sa); | |
818 | VPTRINIT(iph1->nonce_p); | |
819 | VPTRINIT(iph1->id_p); | |
820 | } | |
821 | ||
822 | return error; | |
823 | } | |
824 | ||
825 | /* | |
826 | * send to initiator | |
827 | * psk: HDR, SA, Idir, Nr_b | |
828 | * sig: HDR, SA, Idir, Nr_b, [ CR ] | |
829 | * rsa: HDR, SA, <IDir_b>PubKey_i, <Nr_b>PubKey_i | |
830 | * rev: HDR, SA, <Nr_b>PubKey_i, <IDir_b>Ke_r | |
831 | */ | |
832 | int | |
833 | base_r1send(iph1, msg) | |
834 | struct ph1handle *iph1; | |
835 | vchar_t *msg; | |
836 | { | |
837 | struct payload_list *plist = NULL; | |
838 | int error = -1; | |
839 | #ifdef ENABLE_NATT | |
840 | vchar_t *vid_natt = NULL; | |
841 | #endif | |
842 | ||
843 | /* validity check */ | |
844 | if (iph1->status != PHASE1ST_MSG1RECEIVED) { | |
845 | plog(LLV_ERROR, LOCATION, NULL, | |
846 | "status mismatched %d.\n", iph1->status); | |
847 | goto end; | |
848 | } | |
849 | ||
850 | /* set responder's cookie */ | |
851 | isakmp_newcookie((caddr_t)&iph1->index.r_ck, iph1->remote, iph1->local); | |
852 | ||
853 | /* make ID payload into isakmp status */ | |
854 | if (ipsecdoi_setid1(iph1) < 0) | |
855 | goto end; | |
856 | ||
857 | /* generate NONCE value */ | |
858 | iph1->nonce = eay_set_random(iph1->rmconf->nonce_size); | |
859 | if (iph1->nonce == NULL) | |
860 | goto end; | |
861 | ||
862 | /* set SA payload to reply */ | |
863 | plist = isakmp_plist_append(plist, iph1->sa_ret, ISAKMP_NPTYPE_SA); | |
864 | ||
865 | /* create isakmp ID payload */ | |
866 | plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID); | |
867 | ||
868 | /* create isakmp NONCE payload */ | |
869 | plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE); | |
870 | ||
871 | #ifdef ENABLE_NATT | |
872 | /* has the peer announced nat-t? */ | |
873 | if (NATT_AVAILABLE(iph1)) | |
874 | vid_natt = set_vendorid(iph1->natt_options->version); | |
875 | if (vid_natt) | |
876 | plist = isakmp_plist_append(plist, vid_natt, ISAKMP_NPTYPE_VID); | |
877 | #endif | |
878 | ||
879 | iph1->sendbuf = isakmp_plist_set_all (&plist, iph1); | |
880 | ||
881 | #ifdef HAVE_PRINT_ISAKMP_C | |
882 | isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0); | |
883 | #endif | |
884 | ||
885 | /* send the packet, add to the schedule to resend */ | |
886 | iph1->retry_counter = iph1->rmconf->retry_counter; | |
887 | if (isakmp_ph1resend(iph1) == -1) | |
888 | goto end; | |
889 | ||
890 | /* the sending message is added to the received-list. */ | |
891 | if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) { | |
892 | plog(LLV_ERROR , LOCATION, NULL, | |
893 | "failed to add a response packet to the tree.\n"); | |
894 | goto end; | |
895 | } | |
896 | ||
897 | iph1->status = PHASE1ST_MSG1SENT; | |
898 | ||
899 | #ifdef ENABLE_VPNCONTROL_PORT | |
900 | vpncontrol_notify_phase_change(1, FROM_LOCAL, iph1, NULL); | |
901 | #endif | |
902 | ||
903 | error = 0; | |
904 | ||
905 | end: | |
906 | #ifdef ENABLE_NATT | |
907 | if (vid_natt) | |
908 | vfree(vid_natt); | |
909 | #endif | |
910 | ||
911 | VPTRINIT(iph1->sa_ret); | |
912 | ||
913 | return error; | |
914 | } | |
915 | ||
916 | /* | |
917 | * receive from initiator | |
918 | * psk: HDR, KE, HASH_I | |
919 | * sig: HDR, KE, [ CR, ] [CERT,] SIG_I | |
920 | * rsa: HDR, KE, HASH_I | |
921 | * rev: HDR, <KE>Ke_i, HASH_I | |
922 | */ | |
923 | int | |
924 | base_r2recv(iph1, msg) | |
925 | struct ph1handle *iph1; | |
926 | vchar_t *msg; | |
927 | { | |
928 | vchar_t *pbuf = NULL; | |
929 | struct isakmp_parse_t *pa; | |
930 | int error = -1; | |
931 | int ptype; | |
932 | #ifdef ENABLE_NATT | |
933 | int natd_seq = 0; | |
934 | #endif | |
935 | ||
936 | /* validity check */ | |
937 | if (iph1->status != PHASE1ST_MSG1SENT) { | |
938 | plog(LLV_ERROR, LOCATION, NULL, | |
939 | "status mismatched %d.\n", iph1->status); | |
940 | goto end; | |
941 | } | |
942 | ||
943 | /* validate the type of next payload */ | |
944 | pbuf = isakmp_parse(msg); | |
945 | if (pbuf == NULL) | |
946 | goto end; | |
947 | ||
948 | iph1->pl_hash = NULL; | |
949 | ||
950 | for (pa = (struct isakmp_parse_t *)pbuf->v; | |
951 | pa->type != ISAKMP_NPTYPE_NONE; | |
952 | pa++) { | |
953 | ||
954 | switch (pa->type) { | |
955 | case ISAKMP_NPTYPE_KE: | |
956 | if (isakmp_p2ph(&iph1->dhpub_p, pa->ptr) < 0) | |
957 | goto end; | |
958 | break; | |
959 | case ISAKMP_NPTYPE_HASH: | |
960 | iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr; | |
961 | break; | |
962 | case ISAKMP_NPTYPE_CERT: | |
963 | if (oakley_savecert(iph1, pa->ptr) < 0) | |
964 | goto end; | |
965 | break; | |
966 | case ISAKMP_NPTYPE_SIG: | |
967 | if (isakmp_p2ph(&iph1->sig_p, pa->ptr) < 0) | |
968 | goto end; | |
969 | break; | |
970 | case ISAKMP_NPTYPE_VID: | |
971 | (void)check_vendorid(pa->ptr); | |
972 | break; | |
973 | ||
974 | #ifdef ENABLE_NATT | |
975 | case ISAKMP_NPTYPE_NATD_DRAFT: | |
976 | case ISAKMP_NPTYPE_NATD_RFC: | |
977 | #ifdef __APPLE__ | |
978 | case ISAKMP_NPTYPE_NATD_BADDRAFT: | |
979 | #endif | |
980 | if (pa->type == iph1->natt_options->payload_nat_d) | |
981 | { | |
982 | vchar_t *natd_received = NULL; | |
983 | int natd_verified; | |
984 | ||
985 | if (isakmp_p2ph (&natd_received, pa->ptr) < 0) | |
986 | goto end; | |
987 | ||
988 | if (natd_seq == 0) | |
989 | iph1->natt_flags |= NAT_DETECTED; | |
990 | ||
991 | natd_verified = natt_compare_addr_hash (iph1, | |
992 | natd_received, natd_seq++); | |
993 | ||
994 | plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n", | |
995 | natd_seq - 1, | |
996 | natd_verified ? "verified" : "doesn't match"); | |
997 | ||
998 | vfree (natd_received); | |
999 | break; | |
1000 | } | |
1001 | /* %%%% Be lenient here - some servers send natd payloads */ | |
1002 | /* when no nat is detected */ | |
1003 | break; | |
1004 | #endif | |
1005 | ||
1006 | default: | |
1007 | /* don't send information, see ident_r1recv() */ | |
1008 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1009 | "ignore the packet, " | |
1010 | "received unexpecting payload type %d.\n", | |
1011 | pa->type); | |
1012 | goto end; | |
1013 | } | |
1014 | } | |
1015 | ||
1016 | /* generate DH public value */ | |
1017 | if (oakley_dh_generate(iph1->approval->dhgrp, | |
1018 | &iph1->dhpub, &iph1->dhpriv) < 0) | |
1019 | goto end; | |
1020 | ||
1021 | /* compute sharing secret of DH */ | |
1022 | if (oakley_dh_compute(iph1->approval->dhgrp, iph1->dhpub, | |
1023 | iph1->dhpriv, iph1->dhpub_p, &iph1->dhgxy) < 0) | |
1024 | goto end; | |
1025 | ||
1026 | /* generate SKEYID */ | |
1027 | if (oakley_skeyid(iph1) < 0) | |
1028 | goto end; | |
1029 | ||
1030 | #ifdef ENABLE_NATT | |
1031 | if (NATT_AVAILABLE(iph1)) | |
1032 | plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n", | |
1033 | iph1->natt_flags & NAT_DETECTED ? | |
1034 | "detected:" : "not detected", | |
1035 | iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "", | |
1036 | iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : ""); | |
1037 | #endif | |
1038 | ||
1039 | /* payload existency check */ | |
1040 | /* validate authentication value */ | |
1041 | ptype = oakley_validate_auth(iph1); | |
1042 | if (ptype != 0) { | |
1043 | if (ptype == -1) { | |
1044 | /* message printed inner oakley_validate_auth() */ | |
1045 | goto end; | |
1046 | } | |
1047 | EVT_PUSH(iph1->local, iph1->remote, | |
1048 | EVTT_PEERPH1AUTH_FAILED, NULL); | |
1049 | isakmp_info_send_n1(iph1, ptype, NULL); | |
1050 | goto end; | |
1051 | } | |
1052 | ||
1053 | iph1->status = PHASE1ST_MSG2RECEIVED; | |
1054 | ||
1055 | error = 0; | |
1056 | ||
1057 | end: | |
1058 | if (pbuf) | |
1059 | vfree(pbuf); | |
1060 | ||
1061 | if (error) { | |
1062 | VPTRINIT(iph1->dhpub_p); | |
1063 | oakley_delcert(iph1->cert_p); | |
1064 | iph1->cert_p = NULL; | |
1065 | oakley_delcert(iph1->crl_p); | |
1066 | iph1->crl_p = NULL; | |
1067 | VPTRINIT(iph1->sig_p); | |
1068 | } | |
1069 | ||
1070 | return error; | |
1071 | } | |
1072 | ||
1073 | /* | |
1074 | * send to initiator | |
1075 | * psk: HDR, KE, HASH_R | |
1076 | * sig: HDR, KE, [CERT,] SIG_R | |
1077 | * rsa: HDR, KE, HASH_R | |
1078 | * rev: HDR, <KE>_Ke_r, HASH_R | |
1079 | */ | |
1080 | int | |
1081 | base_r2send(iph1, msg) | |
1082 | struct ph1handle *iph1; | |
1083 | vchar_t *msg; | |
1084 | { | |
1085 | struct payload_list *plist = NULL; | |
1086 | vchar_t *vid = NULL; | |
1087 | int need_cert = 0; | |
1088 | int error = -1; | |
1089 | ||
1090 | /* validity check */ | |
1091 | if (iph1->status != PHASE1ST_MSG2RECEIVED) { | |
1092 | plog(LLV_ERROR, LOCATION, NULL, | |
1093 | "status mismatched %d.\n", iph1->status); | |
1094 | goto end; | |
1095 | } | |
1096 | ||
1097 | /* generate HASH to send */ | |
1098 | plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n"); | |
1099 | switch (iph1->approval->authmethod) { | |
1100 | case OAKLEY_ATTR_AUTH_METHOD_PSKEY: | |
1101 | case OAKLEY_ATTR_AUTH_METHOD_RSAENC: | |
1102 | case OAKLEY_ATTR_AUTH_METHOD_RSAREV: | |
1103 | iph1->hash = oakley_ph1hash_common(iph1, GENERATE); | |
1104 | break; | |
1105 | case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: | |
1106 | case OAKLEY_ATTR_AUTH_METHOD_RSASIG: | |
1107 | case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: | |
1108 | iph1->hash = oakley_ph1hash_base_r(iph1, GENERATE); | |
1109 | break; | |
1110 | default: | |
1111 | plog(LLV_ERROR, LOCATION, NULL, | |
1112 | "invalid authentication method %d\n", | |
1113 | iph1->approval->authmethod); | |
1114 | goto end; | |
1115 | } | |
1116 | if (iph1->hash == NULL) | |
1117 | goto end; | |
1118 | ||
1119 | switch (iph1->approval->authmethod) { | |
1120 | case OAKLEY_ATTR_AUTH_METHOD_PSKEY: | |
1121 | vid = set_vendorid(iph1->approval->vendorid); | |
1122 | ||
1123 | /* create isakmp KE payload */ | |
1124 | plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE); | |
1125 | ||
1126 | /* create isakmp HASH payload */ | |
1127 | plist = isakmp_plist_append(plist, iph1->hash, ISAKMP_NPTYPE_HASH); | |
1128 | ||
1129 | /* append vendor id, if needed */ | |
1130 | if (vid) | |
1131 | plist = isakmp_plist_append(plist, vid, ISAKMP_NPTYPE_VID); | |
1132 | break; | |
1133 | case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: | |
1134 | case OAKLEY_ATTR_AUTH_METHOD_RSASIG: | |
1135 | /* XXX if there is CR or not ? */ | |
1136 | ||
1137 | if (oakley_getmycert(iph1) < 0) | |
1138 | goto end; | |
1139 | ||
1140 | if (oakley_getsign(iph1) < 0) | |
1141 | goto end; | |
1142 | ||
1143 | if (iph1->cert && iph1->rmconf->send_cert) | |
1144 | need_cert = 1; | |
1145 | ||
1146 | /* create isakmp KE payload */ | |
1147 | plist = isakmp_plist_append(plist, iph1->dhpub, ISAKMP_NPTYPE_KE); | |
1148 | ||
1149 | /* add CERT payload if there */ | |
1150 | if (need_cert) | |
1151 | plist = isakmp_plist_append(plist, iph1->cert->pl, ISAKMP_NPTYPE_CERT); | |
1152 | /* add SIG payload */ | |
1153 | plist = isakmp_plist_append(plist, iph1->sig, ISAKMP_NPTYPE_SIG); | |
1154 | break; | |
1155 | case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: | |
1156 | /* ... */ | |
1157 | break; | |
1158 | case OAKLEY_ATTR_AUTH_METHOD_RSAENC: | |
1159 | case OAKLEY_ATTR_AUTH_METHOD_RSAREV: | |
1160 | break; | |
1161 | default: | |
1162 | plog(LLV_ERROR, LOCATION, NULL, "invalid authmethod %d\n", | |
1163 | iph1->approval->authmethod); | |
1164 | goto end; | |
1165 | break; | |
1166 | } | |
1167 | ||
1168 | #ifdef ENABLE_NATT | |
1169 | /* generate NAT-D payloads */ | |
1170 | if (NATT_AVAILABLE(iph1)) | |
1171 | { | |
1172 | vchar_t *natd[2] = { NULL, NULL }; | |
1173 | ||
1174 | plog (LLV_INFO, LOCATION, NULL, "Adding remote and local NAT-D payloads.\n"); | |
1175 | if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) { | |
1176 | plog(LLV_ERROR, LOCATION, NULL, | |
1177 | "NAT-D hashing failed for %s\n", saddr2str(iph1->remote)); | |
1178 | goto end; | |
1179 | } | |
1180 | ||
1181 | if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) { | |
1182 | plog(LLV_ERROR, LOCATION, NULL, | |
1183 | "NAT-D hashing failed for %s\n", saddr2str(iph1->local)); | |
1184 | goto end; | |
1185 | } | |
1186 | ||
1187 | #ifdef __APPLE__ | |
1188 | /* old Apple version sends natd payloads in the wrong order */ | |
1189 | if (iph1->natt_options->version == VENDORID_NATT_APPLE) { | |
1190 | plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d); | |
1191 | plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d); | |
1192 | } else | |
1193 | #endif | |
1194 | { | |
1195 | plist = isakmp_plist_append(plist, natd[0], iph1->natt_options->payload_nat_d); | |
1196 | plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d); | |
1197 | } | |
1198 | } | |
1199 | #endif | |
1200 | ||
1201 | iph1->sendbuf = isakmp_plist_set_all (&plist, iph1); | |
1202 | ||
1203 | #ifdef HAVE_PRINT_ISAKMP_C | |
1204 | isakmp_printpacket(iph1->sendbuf, iph1->local, iph1->remote, 0); | |
1205 | #endif | |
1206 | ||
1207 | /* send HDR;KE;NONCE to responder */ | |
1208 | if (isakmp_send(iph1, iph1->sendbuf) < 0) | |
1209 | goto end; | |
1210 | ||
1211 | /* the sending message is added to the received-list. */ | |
1212 | if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) { | |
1213 | plog(LLV_ERROR , LOCATION, NULL, | |
1214 | "failed to add a response packet to the tree.\n"); | |
1215 | goto end; | |
1216 | } | |
1217 | ||
1218 | /* generate SKEYIDs & IV & final cipher key */ | |
1219 | if (oakley_skeyid_dae(iph1) < 0) | |
1220 | goto end; | |
1221 | if (oakley_compute_enckey(iph1) < 0) | |
1222 | goto end; | |
1223 | if (oakley_newiv(iph1) < 0) | |
1224 | goto end; | |
1225 | ||
1226 | /* set encryption flag */ | |
1227 | iph1->flags |= ISAKMP_FLAG_E; | |
1228 | ||
1229 | iph1->status = PHASE1ST_ESTABLISHED; | |
1230 | ||
1231 | error = 0; | |
1232 | ||
1233 | end: | |
1234 | if (vid) | |
1235 | vfree(vid); | |
1236 | return error; | |
1237 | } |