]>
Commit | Line | Data |
---|---|---|
d1e348cf A |
1 | /* |
2 | * Copyright (c) 2007 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | ||
23 | /* | |
24 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
25 | * All rights reserved. | |
26 | * | |
27 | * Redistribution and use in source and binary forms, with or without | |
28 | * modification, are permitted provided that the following conditions | |
29 | * are met: | |
30 | * 1. Redistributions of source code must retain the above copyright | |
31 | * notice, this list of conditions and the following disclaimer. | |
32 | * 2. Redistributions in binary form must reproduce the above copyright | |
33 | * notice, this list of conditions and the following disclaimer in the | |
34 | * documentation and/or other materials provided with the distribution. | |
35 | * 3. Neither the name of the project nor the names of its contributors | |
36 | * may be used to endorse or promote products derived from this software | |
37 | * without specific prior written permission. | |
38 | * | |
39 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
40 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
42 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
43 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
44 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
45 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
46 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
47 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
48 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
49 | * SUCH DAMAGE. | |
50 | */ | |
51 | ||
52 | #include "config.h" | |
53 | ||
54 | #include <sys/types.h> | |
55 | #include <sys/param.h> | |
56 | #include <sys/socket.h> | |
57 | #include <sys/signal.h> | |
58 | #include <sys/stat.h> | |
59 | #include <sys/un.h> | |
60 | ||
d1e348cf | 61 | #include <System/net/pfkeyv2.h> |
d1e348cf A |
62 | |
63 | #include <netinet/in.h> | |
64 | #ifndef HAVE_NETINET6_IPSEC | |
65 | #include <netinet/ipsec.h> | |
66 | #else | |
67 | #include <netinet6/ipsec.h> | |
68 | #endif | |
69 | ||
70 | ||
71 | #include <stdlib.h> | |
72 | #include <stdio.h> | |
73 | #include <string.h> | |
74 | #include <errno.h> | |
75 | #include <netdb.h> | |
76 | #ifdef HAVE_UNISTD_H | |
77 | #include <unistd.h> | |
78 | #endif | |
79 | #ifdef ENABLE_HYBRID | |
80 | #include <resolv.h> | |
81 | #endif | |
82 | ||
83 | #include "var.h" | |
84 | #include "misc.h" | |
85 | #include "vmbuf.h" | |
86 | #include "plog.h" | |
87 | #include "sockmisc.h" | |
88 | #include "debug.h" | |
89 | #include "handler.h" | |
90 | #include "schedule.h" | |
91 | #include "localconf.h" | |
92 | #include "remoteconf.h" | |
93 | #include "grabmyaddr.h" | |
94 | #include "isakmp_var.h" | |
95 | #include "isakmp.h" | |
96 | #include "oakley.h" | |
97 | #include "evt.h" | |
98 | #include "pfkey.h" | |
99 | #include "ipsec_doi.h" | |
100 | #include "admin.h" | |
101 | #include "admin_var.h" | |
102 | #include "isakmp_inf.h" | |
103 | #ifdef ENABLE_HYBRID | |
104 | #include "isakmp_cfg.h" | |
105 | #include "isakmp_unity.h" | |
106 | #endif | |
107 | #include "session.h" | |
108 | #include "gcmalloc.h" | |
109 | #include "sainfo.h" | |
110 | #include "ipsec_doi.h" | |
111 | #include "nattraversal.h" | |
112 | ||
113 | #include "vpn_control.h" | |
114 | #include "vpn_control_var.h" | |
115 | #include "strnames.h" | |
116 | #include "ike_session.h" | |
e8d9021d | 117 | #include "ipsecMessageTracer.h" |
d1e348cf A |
118 | |
119 | ||
120 | static int vpn_get_ph2pfs(struct ph1handle *); | |
121 | ||
122 | int | |
e8d9021d | 123 | vpn_connect(struct bound_addr *srv, int oper) |
d1e348cf A |
124 | { |
125 | int error = -1; | |
126 | struct sockaddr *dst; | |
127 | struct remoteconf *rmconf; | |
128 | struct sockaddr *remote = NULL; | |
129 | struct sockaddr *local = NULL; | |
130 | u_int16_t port; | |
131 | ||
132 | dst = racoon_calloc(1, sizeof(struct sockaddr)); // this should come from the bound_addr parameter | |
133 | if (dst == NULL) | |
134 | goto out; | |
135 | ((struct sockaddr_in *)(dst))->sin_len = sizeof(struct sockaddr_in); | |
136 | ((struct sockaddr_in *)(dst))->sin_family = AF_INET; | |
137 | ((struct sockaddr_in *)(dst))->sin_port = 500; | |
138 | ((struct sockaddr_in *)(dst))->sin_addr.s_addr = srv->address; | |
139 | ||
140 | /* | |
141 | * Find the source address | |
142 | */ | |
143 | if ((local = getlocaladdr(dst)) == NULL) { | |
144 | plog(LLV_ERROR, LOCATION, NULL, | |
145 | "cannot get local address\n"); | |
146 | goto out1; | |
147 | } | |
148 | ||
149 | /* find appropreate configuration */ | |
150 | rmconf = getrmconf(dst); | |
151 | if (rmconf == NULL) { | |
152 | plog(LLV_ERROR, LOCATION, NULL, | |
153 | "no configuration found " | |
154 | "for %s\n", saddrwop2str(dst)); | |
155 | goto out1; | |
156 | } | |
157 | ||
158 | /* get remote IP address and port number. */ | |
159 | if ((remote = dupsaddr(dst)) == NULL) { | |
160 | plog(LLV_ERROR, LOCATION, NULL, | |
161 | "failed to duplicate address\n"); | |
162 | goto out1; | |
163 | } | |
164 | ||
165 | switch (remote->sa_family) { | |
166 | case AF_INET: | |
167 | ((struct sockaddr_in *)remote)->sin_port = | |
168 | ((struct sockaddr_in *)rmconf->remote)->sin_port; | |
169 | break; | |
170 | #ifdef INET6 | |
171 | case AF_INET6: | |
172 | ((struct sockaddr_in6 *)remote)->sin6_port = | |
173 | ((struct sockaddr_in6 *)rmconf->remote)->sin6_port; | |
174 | break; | |
175 | #endif | |
176 | default: | |
177 | plog(LLV_ERROR, LOCATION, NULL, | |
178 | "invalid family: %d\n", | |
179 | remote->sa_family); | |
180 | goto out1; | |
181 | break; | |
182 | } | |
183 | ||
184 | port = ntohs(getmyaddrsport(local)); | |
185 | if (set_port(local, port) == NULL) | |
186 | goto out1; | |
187 | ||
188 | plog(LLV_INFO, LOCATION, NULL, | |
189 | "accept a request to establish IKE-SA: " | |
190 | "%s\n", saddrwop2str(remote)); | |
191 | ||
e8d9021d A |
192 | IPSECLOGASLMSG("IPSec connecting to server %s\n", |
193 | saddrwop2str(remote)); | |
194 | ||
d1e348cf | 195 | /* begin ident mode */ |
e8d9021d | 196 | if (isakmp_ph1begin_i(rmconf, remote, local, oper) < 0) |
d1e348cf A |
197 | goto out1; |
198 | ||
199 | error = 0; | |
200 | ||
201 | out1: | |
202 | if (dst != NULL) | |
203 | racoon_free(dst); | |
204 | if (local != NULL) | |
205 | racoon_free(local); | |
206 | if (remote != NULL) | |
207 | racoon_free(remote); | |
208 | out: | |
209 | ||
210 | return error; | |
211 | } | |
212 | ||
213 | int | |
214 | vpn_disconnect(struct bound_addr *srv) | |
215 | { | |
216 | struct sockaddr_in saddr; | |
217 | ||
218 | bzero(&saddr, sizeof(saddr)); | |
219 | saddr.sin_len = sizeof(saddr); | |
220 | saddr.sin_addr.s_addr = srv->address; | |
221 | saddr.sin_port = 0; | |
222 | saddr.sin_family = AF_INET; | |
e8d9021d A |
223 | |
224 | IPSECLOGASLMSG("IPSec disconnecting from server %s\n", | |
225 | saddrwop2str(&saddr)); | |
226 | ||
227 | ike_sessions_stopped_by_controller(&saddr, | |
d1e348cf A |
228 | 0, |
229 | ike_session_stopped_by_vpn_disconnect); | |
230 | if (purgephXbydstaddrwop((struct sockaddr *)(&saddr)) > 0) { | |
231 | return 0; | |
232 | } else { | |
233 | return -1; | |
234 | } | |
235 | } | |
236 | ||
237 | int | |
238 | vpn_start_ph2(struct bound_addr *addr, struct vpnctl_cmd_start_ph2 *pkt) | |
239 | { | |
240 | struct vpnctl_sa_selector *selector_ptr; | |
241 | struct vpnctl_algo *algo_ptr, *next_algo; | |
242 | int i, j, defklen; | |
243 | struct sainfoalg *new_algo; | |
244 | struct sainfo *new_sainfo = NULL, *check; | |
245 | u_int16_t class, algorithm, keylen; | |
246 | struct ph1handle *ph1; | |
247 | struct sockaddr_in saddr; | |
248 | ||
249 | struct id { | |
250 | u_int8_t type; /* ID Type */ | |
251 | u_int8_t proto_id; /* Protocol ID */ | |
252 | u_int16_t port; /* Port */ | |
253 | u_int32_t addr; /* IPv4 address */ | |
254 | u_int32_t mask; | |
255 | } *id_ptr; | |
256 | ||
257 | /* verify ph1 exists */ | |
258 | bzero(&saddr, sizeof(saddr)); | |
259 | saddr.sin_len = sizeof(saddr); | |
260 | saddr.sin_addr.s_addr = addr->address; | |
261 | saddr.sin_port = 0; | |
262 | saddr.sin_family = AF_INET; | |
263 | ph1 = getph1bydstaddrwop((struct sockaddr *)(&saddr)); | |
264 | if (ph1 == NULL) { | |
265 | plog(LLV_ERROR, LOCATION, NULL, | |
266 | "cannot start phase2 - no phase1 found.\n"); | |
267 | return -1; | |
268 | } | |
269 | if (ph1->status != PHASE1ST_ESTABLISHED) { | |
270 | plog(LLV_ERROR, LOCATION, NULL, | |
271 | "cannot start phase2 - phase1 not established.\n"); | |
272 | return -1; | |
273 | } | |
274 | ||
275 | selector_ptr = (struct vpnctl_sa_selector *)(pkt + 1); | |
276 | algo_ptr = (struct vpnctl_algo *)(selector_ptr + ntohs(pkt->selector_count)); | |
277 | ||
278 | for (i = 0; i < ntohs(pkt->selector_count); i++, selector_ptr++) { | |
279 | new_sainfo = newsainfo(); | |
280 | if (new_sainfo == NULL) { | |
281 | plog(LLV_ERROR, LOCATION, NULL, | |
282 | "unable to allocate sainfo struct.\n"); | |
283 | goto fail; | |
284 | } | |
285 | ||
286 | if (ntohl(selector_ptr->src_tunnel_mask) == 0xFFFFFFFF) | |
287 | new_sainfo->idsrc = vmalloc(sizeof(struct id) - sizeof(u_int32_t)); | |
288 | else | |
289 | new_sainfo->idsrc = vmalloc(sizeof(struct id)); | |
290 | if (new_sainfo->idsrc == NULL) { | |
291 | plog(LLV_ERROR, LOCATION, NULL, | |
292 | "unable to allocate id struct.\n"); | |
293 | goto fail; | |
294 | } | |
295 | if (selector_ptr->dst_tunnel_mask == 0xFFFFFFFF) | |
296 | new_sainfo->iddst = vmalloc(sizeof(struct id) - sizeof(u_int32_t)); | |
297 | else | |
298 | new_sainfo->iddst = vmalloc(sizeof(struct id)); | |
299 | if (new_sainfo->iddst == NULL) { | |
300 | plog(LLV_ERROR, LOCATION, NULL, | |
301 | "unable to allocate id struct.\n"); | |
302 | goto fail; | |
303 | } | |
304 | ||
305 | id_ptr = (struct id *)new_sainfo->idsrc->v; | |
306 | if (ntohl(selector_ptr->src_tunnel_mask) == 0xFFFFFFFF) | |
307 | id_ptr->type = IPSECDOI_ID_IPV4_ADDR; | |
308 | else { | |
309 | id_ptr->type = IPSECDOI_ID_IPV4_ADDR_SUBNET; | |
310 | id_ptr->mask = selector_ptr->src_tunnel_mask; | |
311 | } | |
312 | id_ptr->addr = selector_ptr->src_tunnel_address; | |
313 | id_ptr->port = selector_ptr->src_tunnel_port; | |
314 | id_ptr->proto_id = selector_ptr->ul_protocol; | |
315 | ||
316 | id_ptr = (struct id *)new_sainfo->iddst->v; | |
317 | if (selector_ptr->dst_tunnel_mask == 0xFFFFFFFF) | |
318 | id_ptr->type = IPSECDOI_ID_IPV4_ADDR; | |
319 | else { | |
320 | id_ptr->type = IPSECDOI_ID_IPV4_ADDR_SUBNET; | |
321 | id_ptr->mask = selector_ptr->dst_tunnel_mask; | |
322 | } | |
323 | id_ptr->addr = selector_ptr->dst_tunnel_address; | |
324 | id_ptr->port = selector_ptr->dst_tunnel_port; | |
325 | id_ptr->proto_id = selector_ptr->ul_protocol; | |
326 | ||
327 | new_sainfo->dynamic = addr->address; | |
328 | new_sainfo->lifetime = ntohl(pkt->lifetime); | |
329 | ||
330 | if (ntohs(pkt->pfs_group) != 0) { | |
331 | new_sainfo->pfs_group = algtype2doi(algclass_isakmp_dh, ntohs(pkt->pfs_group)); | |
332 | if (new_sainfo->pfs_group == -1) { | |
333 | plog(LLV_ERROR, LOCATION, NULL, "invalid dh group specified\n"); | |
334 | goto fail; | |
335 | } | |
336 | } | |
337 | for (j = 0, next_algo = algo_ptr; j < ntohs(pkt->algo_count); j++, next_algo++) { | |
338 | ||
339 | new_algo = newsainfoalg(); | |
340 | if (new_algo == NULL) { | |
341 | plog(LLV_ERROR, LOCATION, NULL, | |
342 | "failed to allocate algorithm structure\n"); | |
343 | goto fail; | |
344 | } | |
345 | ||
346 | class = ntohs(next_algo->algo_class); | |
347 | algorithm = ntohs(next_algo->algo); | |
348 | keylen = ntohs(next_algo->key_len); | |
349 | ||
350 | new_algo->alg = algtype2doi(class, algorithm); | |
351 | if (new_algo->alg == -1) { | |
352 | plog(LLV_ERROR, LOCATION, NULL, "algorithm mismatched\n"); | |
353 | racoon_free(new_algo); | |
354 | goto fail; | |
355 | } | |
356 | ||
357 | defklen = default_keylen(class, algorithm); | |
358 | if (defklen == 0) { | |
359 | if (keylen) { | |
360 | plog(LLV_ERROR, LOCATION, NULL, "keylen not allowed\n"); | |
361 | racoon_free(new_algo); | |
362 | goto fail; | |
363 | } | |
364 | } else { | |
365 | if (keylen && check_keylen(class, algorithm, keylen) < 0) { | |
366 | plog(LLV_ERROR, LOCATION, NULL, "invalid keylen %d\n", keylen); | |
367 | racoon_free(new_algo); | |
368 | goto fail; | |
369 | } | |
370 | } | |
371 | ||
372 | if (keylen) | |
373 | new_algo->encklen = keylen; | |
374 | else | |
375 | new_algo->encklen = defklen; | |
376 | ||
377 | /* check if it's supported algorithm by kernel */ | |
378 | if (!(class == algclass_ipsec_auth && algorithm == algtype_non_auth) | |
379 | && pk_checkalg(class, algorithm, new_algo->encklen)) { | |
380 | int a = algclass2doi(class); | |
381 | int b = new_algo->alg; | |
382 | if (a == IPSECDOI_ATTR_AUTH) | |
383 | a = IPSECDOI_PROTO_IPSEC_AH; | |
384 | plog(LLV_ERROR, LOCATION, NULL, | |
385 | "algorithm %s not supported by the kernel (missing module?)\n", s_ipsecdoi_trns(a, b)); | |
386 | racoon_free(new_algo); | |
387 | goto fail; | |
388 | } | |
389 | inssainfoalg(&new_sainfo->algs[class], new_algo); | |
390 | } | |
391 | ||
392 | if (new_sainfo->algs[algclass_ipsec_enc] == 0) { | |
393 | plog(LLV_ERROR, LOCATION, NULL, | |
394 | "no encryption algorithm at %s\n", sainfo2str(new_sainfo)); | |
395 | goto fail; | |
396 | } | |
397 | if (new_sainfo->algs[algclass_ipsec_auth] == 0) { | |
398 | plog(LLV_ERROR, LOCATION, NULL, | |
399 | "no authentication algorithm at %s\n", sainfo2str(new_sainfo)); | |
400 | goto fail; | |
401 | } | |
402 | if (new_sainfo->algs[algclass_ipsec_comp] == 0) { | |
403 | plog(LLV_ERROR, LOCATION, NULL, | |
404 | "no compression algorithm at %s\n", sainfo2str(new_sainfo)); | |
405 | goto fail; | |
406 | } | |
407 | ||
408 | /* duplicate check */ | |
409 | check = getsainfo(new_sainfo->idsrc, new_sainfo->iddst, new_sainfo->id_i, 0); | |
410 | if (check && (!check->idsrc && !new_sainfo->idsrc)) { | |
411 | plog(LLV_ERROR, LOCATION, NULL,"duplicated sainfo: %s\n", sainfo2str(new_sainfo)); | |
412 | goto fail; | |
413 | } | |
414 | plog(LLV_DEBUG2, LOCATION, NULL, "create sainfo: %s\n", sainfo2str(new_sainfo)); | |
415 | inssainfo(new_sainfo); | |
416 | new_sainfo = NULL; | |
417 | } | |
418 | ||
419 | return 0; | |
420 | ||
421 | fail: | |
422 | if (new_sainfo) | |
423 | delsainfo(new_sainfo); | |
424 | flushsainfo_dynamic(addr); | |
425 | return -1; | |
426 | } | |
427 | ||
428 | static int | |
429 | vpn_get_ph2pfs(struct ph1handle *ph1) | |
430 | { | |
431 | } | |
432 | ||
433 | ||
434 | int | |
435 | vpn_get_config(struct ph1handle *iph1, struct vpnctl_status_phase_change **msg, size_t *msg_size) | |
436 | { | |
437 | ||
438 | struct vpnctl_modecfg_params *params; | |
439 | struct myaddrs *myaddr; | |
440 | u_int16_t ifname_len, msize; | |
441 | u_int8_t *cptr; | |
442 | ||
443 | *msg = NULL; | |
444 | msize = 0; | |
445 | ||
446 | if (((struct sockaddr_in *)iph1->local)->sin_family != AF_INET) { | |
447 | plog(LLV_ERROR, LOCATION, NULL, | |
448 | "IPv6 not supported for mode config.\n"); | |
449 | return -1; | |
450 | } | |
451 | ||
452 | if (iph1->mode_cfg->attr_list == NULL) | |
453 | return 1; /* haven't received configuration yet */ | |
454 | ||
455 | myaddr = find_myaddr(iph1->local, 0); | |
456 | if (myaddr == NULL) { | |
457 | plog(LLV_ERROR, LOCATION, NULL, | |
458 | "unable to find address structure.\n"); | |
459 | return -1; | |
460 | } | |
461 | ||
462 | msize = sizeof(struct vpnctl_status_phase_change) | |
463 | + sizeof(struct vpnctl_modecfg_params); | |
464 | msize += iph1->mode_cfg->attr_list->l; | |
465 | ||
466 | *msg = racoon_calloc(1, msize); | |
467 | if (*msg == NULL) { | |
468 | plog(LLV_ERROR, LOCATION, NULL, | |
469 | "faled to allocate space for message.\n"); | |
470 | return -1; | |
471 | } | |
472 | ||
473 | (*msg)->hdr.flags = htons(VPNCTL_FLAG_MODECFG_USED); | |
474 | params = (struct vpnctl_modecfg_params *)(*msg + 1); | |
475 | params->outer_local_addr = ((struct sockaddr_in *)iph1->local)->sin_addr.s_addr; | |
476 | params->outer_remote_port = htons(0); | |
477 | params->outer_local_port = htons(0); | |
478 | ifname_len = strlen(myaddr->ifname); | |
479 | memset(¶ms->ifname, 0, IFNAMSIZ); | |
480 | memcpy(¶ms->ifname, myaddr->ifname, ifname_len < IFNAMSIZ ? ifname_len : IFNAMSIZ-1); | |
481 | cptr = (u_int8_t *)(params + 1); | |
482 | memcpy(cptr, iph1->mode_cfg->attr_list->v, iph1->mode_cfg->attr_list->l); | |
483 | *msg_size = msize; | |
484 | ||
e8d9021d A |
485 | IPSECLOGASLMSG("IPSec Network Configuration established.\n"); |
486 | ||
d1e348cf A |
487 | return 0; |
488 | } | |
489 | ||
490 | ||
491 | int | |
492 | vpn_xauth_reply(u_int32_t address, void *attr_list, size_t attr_len) | |
493 | { | |
494 | ||
495 | struct isakmp_pl_attr *reply; | |
496 | void* attr_ptr; | |
497 | vchar_t *payload = NULL; | |
498 | struct ph1handle *iph1; | |
499 | struct sockaddr_in saddr; | |
500 | int error = -1; | |
501 | int tlen = attr_len; | |
502 | struct isakmp_data *attr; | |
503 | char *dataptr = (char *)attr_list; | |
504 | ||
505 | /* find ph1 */ | |
506 | bzero(&saddr, sizeof(saddr)); | |
507 | saddr.sin_len = sizeof(saddr); | |
508 | saddr.sin_addr.s_addr = address; | |
509 | saddr.sin_port = 0; | |
510 | saddr.sin_family = AF_INET; | |
511 | iph1 = getph1bydstaddrwop((struct sockaddr *)(&saddr)); | |
512 | if (iph1 == NULL) { | |
513 | plog(LLV_ERROR, LOCATION, NULL, | |
514 | "cannot reply to xauth request - no ph1 found.\n"); | |
515 | goto end; | |
516 | } | |
517 | ||
518 | if (iph1->xauth_awaiting_userinput == 0) { | |
519 | plog(LLV_ERROR, LOCATION, NULL, "Huh? recvd xauth reply data with no xauth reply pending \n"); | |
520 | goto end; | |
521 | } | |
522 | ||
523 | /* validate attr lengths */ | |
524 | while (tlen > 0) | |
525 | { | |
526 | int tlv; | |
527 | ||
528 | attr = (struct isakmp_data *)dataptr; | |
529 | tlv = (attr->type & htons(0x8000)) == 0; | |
530 | ||
531 | if (tlv) { | |
532 | tlen -= ntohs(attr->lorv); | |
533 | dataptr += ntohs(attr->lorv); | |
534 | } | |
535 | tlen -= sizeof(u_int32_t); | |
536 | dataptr += sizeof(u_int32_t); | |
537 | } | |
538 | if (tlen != 0) { | |
539 | plog(LLV_ERROR, LOCATION, NULL, "invalid auth info received from VPN Control socket.\n"); | |
540 | goto end; | |
541 | } | |
542 | ||
543 | payload = vmalloc(sizeof(struct isakmp_pl_attr) + attr_len); | |
544 | if (payload == NULL) { | |
545 | plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory for xauth reply\n"); | |
546 | goto end; | |
547 | } | |
548 | memset(payload->v, 0, sizeof(reply)); | |
549 | ||
550 | reply = (struct isakmp_pl_attr *)payload->v; | |
551 | reply->h.len = htons(payload->l); | |
552 | reply->type = ISAKMP_CFG_REPLY; | |
553 | reply->id = iph1->pended_xauth_id; /* network byte order */ | |
554 | iph1->xauth_awaiting_userinput = 0; /* no longer waiting */ | |
555 | attr_ptr = reply + 1; | |
556 | memcpy(attr_ptr, attr_list, attr_len); | |
557 | ||
558 | plog(LLV_DEBUG, LOCATION, NULL, | |
559 | "Sending MODE_CFG REPLY\n"); | |
560 | error = isakmp_cfg_send(iph1, payload, | |
561 | ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0, 0, iph1->xauth_awaiting_userinput_msg); | |
562 | VPTRINIT(iph1->xauth_awaiting_userinput_msg); | |
563 | ike_session_stop_xauth_timer(iph1); | |
564 | ||
e8d9021d A |
565 | IPSECLOGASLMSG("IPSec Extended Authentication sent.\n"); |
566 | ||
d1e348cf A |
567 | end: |
568 | if (payload) | |
569 | vfree(payload); | |
570 | return error; | |
571 | } | |
572 | ||
e8d9021d A |
573 | int |
574 | vpn_assert(struct sockaddr *src_addr, struct sockaddr *dst_addr) | |
575 | { | |
576 | if (ike_session_assert(src_addr, dst_addr)) { | |
577 | plog(LLV_ERROR, LOCATION, NULL, | |
578 | "cannot assert - no matching session.\n"); | |
579 | return -1; | |
580 | } | |
581 | ||
582 | return 0; | |
583 | } |