]> git.saurik.com Git - apple/network_cmds.git/blob - racoon.tproj/admin.c
network_cmds-176.4.1.tar.gz
[apple/network_cmds.git] / racoon.tproj / admin.c
1 /* $KAME: admin.c,v 1.23 2001/06/01 10:12:55 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 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/socket.h>
35 #include <sys/signal.h>
36 #include <sys/un.h>
37
38 #include <net/pfkeyv2.h>
39 #include <netkey/key_var.h>
40
41 #include <netinet/in.h>
42
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <netdb.h>
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51
52 #include "var.h"
53 #include "misc.h"
54 #include "vmbuf.h"
55 #include "plog.h"
56 #include "sockmisc.h"
57 #include "debug.h"
58
59 #include "schedule.h"
60 #include "localconf.h"
61 #include "remoteconf.h"
62 #include "grabmyaddr.h"
63 #include "isakmp_var.h"
64 #include "isakmp.h"
65 #include "oakley.h"
66 #include "handler.h"
67 #include "pfkey.h"
68 #include "admin.h"
69 #include "admin_var.h"
70 #include "session.h"
71 #include "gcmalloc.h"
72
73 static struct sockaddr_un sunaddr;
74 static int admin_process __P((int, char *));
75 static int admin_reply __P((int, struct admin_com *, vchar_t *));
76
77 int
78 admin_handler()
79 {
80 int so2;
81 struct sockaddr_storage from;
82 int fromlen = sizeof(from);
83 struct admin_com com;
84 char *combuf = NULL;
85 pid_t pid = -1;
86 int len, error = -1;
87
88 so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
89 if (so2 < 0) {
90 plog(LLV_ERROR, LOCATION, NULL,
91 "failed to accept admin command: %s\n",
92 strerror(errno));
93 return -1;
94 }
95
96 /* get buffer length */
97 while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
98 if (errno == EINTR)
99 continue;
100 plog(LLV_ERROR, LOCATION, NULL,
101 "failed to recv admin command: %s\n",
102 strerror(errno));
103 goto end;
104 }
105
106 /* sanity check */
107 if (len < sizeof(com)) {
108 plog(LLV_ERROR, LOCATION, NULL,
109 "invalid header length of admin command\n");
110 goto end;
111 }
112
113 /* get buffer to receive */
114 if ((combuf = racoon_malloc(com.ac_len)) == 0) {
115 plog(LLV_ERROR, LOCATION, NULL,
116 "failed to alloc buffer for admin command\n");
117 goto end;
118 }
119
120 /* get real data */
121 while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
122 if (errno == EINTR)
123 continue;
124 plog(LLV_ERROR, LOCATION, NULL,
125 "failed to recv admin command: %s\n",
126 strerror(errno));
127 goto end;
128 }
129
130 /* don't fork() because of reloading config. */
131 if (com.ac_cmd == ADMIN_RELOAD_CONF) {
132 /* reload does not work at all! */
133 signal_handler(SIGHUP);
134 goto end;
135 }
136
137 /* fork for processing */
138 if (!f_foreground) {
139 if ((pid = fork()) < 0) {
140 plog(LLV_ERROR, LOCATION, NULL,
141 "failed to fork for admin processing: %s\n",
142 strerror(errno));
143 goto end;
144 }
145
146 /* parant's process. */
147 if (pid != 0) {
148 error = 0;
149 goto end;
150 }
151
152 /* child's process */
153 admin_close();
154 }
155
156 /* exit in this function. */
157 error = admin_process(so2, combuf);
158
159 end:
160 (void)close(so2);
161 if (combuf)
162 racoon_free(combuf);
163
164 /* exit if child's process. */
165 if (pid == 0 && !f_foreground)
166 exit(error);
167
168 return error;
169 }
170
171 /*
172 * main child's process.
173 */
174 static int
175 admin_process(so2, combuf)
176 int so2;
177 char *combuf;
178 {
179 struct admin_com *com = (struct admin_com *)combuf;
180 vchar_t *buf = NULL;
181 int error = 0;
182
183 com->ac_errno = 0;
184
185 switch (com->ac_cmd) {
186 case ADMIN_RELOAD_CONF:
187 /* don't entered because of proccessing it in other place. */
188 plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n");
189 goto bad;
190
191 case ADMIN_SHOW_SCHED:
192 {
193 caddr_t p;
194 int len;
195 if (sched_dump(&p, &len) == -1)
196 com->ac_errno = -1;
197 buf = vmalloc(len);
198 if (buf == NULL)
199 com->ac_errno = -1;
200 memcpy(buf->v, p, len);
201 }
202 break;
203 case ADMIN_SHOW_SA:
204 case ADMIN_FLUSH_SA:
205 {
206 switch (com->ac_proto) {
207 case ADMIN_PROTO_ISAKMP:
208 switch (com->ac_cmd) {
209 case ADMIN_SHOW_SA:
210 buf = dumpph1();
211 if (buf == NULL)
212 com->ac_errno = -1;
213 break;
214 case ADMIN_FLUSH_SA:
215 flushph1();
216 break;
217 }
218 break;
219 case ADMIN_PROTO_IPSEC:
220 case ADMIN_PROTO_AH:
221 case ADMIN_PROTO_ESP:
222 switch (com->ac_cmd) {
223 case ADMIN_SHOW_SA:
224 {
225 u_int p;
226 p = admin2pfkey_proto(com->ac_proto);
227 if (p == -1)
228 goto bad;
229 buf = pfkey_dump_sadb(p);
230 if (buf == NULL)
231 com->ac_errno = -1;
232 }
233 break;
234 case ADMIN_FLUSH_SA:
235 pfkey_flush_sadb(com->ac_proto);
236 break;
237 }
238 break;
239
240 case ADMIN_PROTO_INTERNAL:
241 switch (com->ac_cmd) {
242 case ADMIN_SHOW_SA:
243 buf = NULL; /*XXX dumpph2(&error);*/
244 if (buf == NULL)
245 com->ac_errno = error;
246 break;
247 case ADMIN_FLUSH_SA:
248 /*XXX flushph2();*/
249 com->ac_errno = 0;
250 break;
251 }
252 break;
253
254 default:
255 /* ignore */
256 com->ac_errno = -1;
257 }
258 }
259 break;
260
261 case ADMIN_DELETE_SA:
262 break;
263
264 case ADMIN_ESTABLISH_SA:
265 {
266 struct sockaddr *dst;
267 struct sockaddr *src;
268 src = (struct sockaddr *)
269 &((struct admin_com_indexes *)
270 ((caddr_t)com + sizeof(*com)))->src;
271 dst = (struct sockaddr *)
272 &((struct admin_com_indexes *)
273 ((caddr_t)com + sizeof(*com)))->dst;
274
275 switch (com->ac_proto) {
276 case ADMIN_PROTO_ISAKMP:
277 {
278 struct remoteconf *rmconf;
279 struct sockaddr *remote;
280 struct sockaddr *local;
281
282 /* search appropreate configuration */
283 rmconf = getrmconf(dst);
284 if (rmconf == NULL) {
285 plog(LLV_ERROR, LOCATION, NULL,
286 "no configuration found "
287 "for %s\n", saddrwop2str(dst));
288 com->ac_errno = -1;
289 break;
290 }
291
292 /* get remote IP address and port number. */
293 remote = dupsaddr(dst);
294 if (remote == NULL) {
295 com->ac_errno = -1;
296 break;
297 }
298 switch (remote->sa_family) {
299 case AF_INET:
300 ((struct sockaddr_in *)remote)->sin_port =
301 ((struct sockaddr_in *)rmconf->remote)->sin_port;
302 break;
303 #ifdef INET6
304 case AF_INET6:
305 ((struct sockaddr_in6 *)remote)->sin6_port =
306 ((struct sockaddr_in6 *)rmconf->remote)->sin6_port;
307 break;
308 #endif
309 default:
310 plog(LLV_ERROR, LOCATION, NULL,
311 "invalid family: %d\n",
312 remote->sa_family);
313 com->ac_errno = -1;
314 break;
315 }
316
317 /* get local address */
318 local = dupsaddr(src);
319 if (local == NULL) {
320 com->ac_errno = -1;
321 break;
322 }
323 switch (local->sa_family) {
324 case AF_INET:
325 ((struct sockaddr_in *)local)->sin_port =
326 getmyaddrsport(local);
327 break;
328 #ifdef INET6
329 case AF_INET6:
330 ((struct sockaddr_in6 *)local)->sin6_port =
331 getmyaddrsport(local);
332 break;
333 #endif
334 default:
335 plog(LLV_ERROR, LOCATION, NULL,
336 "invalid family: %d\n",
337 local->sa_family);
338 com->ac_errno = -1;
339 break;
340 }
341
342
343 plog(LLV_INFO, LOCATION, NULL,
344 "accept a request to establish IKE-SA: "
345 "%s\n", saddrwop2str(remote));
346
347 /* begin ident mode */
348 if (isakmp_ph1begin_i(rmconf, remote) < 0) {
349 com->ac_errno = -1;
350 break;
351 }
352 }
353 break;
354 case ADMIN_PROTO_AH:
355 case ADMIN_PROTO_ESP:
356 break;
357 default:
358 /* ignore */
359 com->ac_errno = -1;
360 }
361 }
362 break;
363
364 default:
365 plog(LLV_ERROR, LOCATION, NULL,
366 "invalid command: %d\n", com->ac_cmd);
367 com->ac_errno = -1;
368 }
369
370 if (admin_reply(so2, com, buf) < 0)
371 goto bad;
372
373 if (buf != NULL)
374 vfree(buf);
375
376 return 0;
377
378 bad:
379 if (buf != NULL)
380 vfree(buf);
381 return -1;
382 }
383
384 static int
385 admin_reply(so, combuf, buf)
386 int so;
387 struct admin_com *combuf;
388 vchar_t *buf;
389 {
390 int tlen;
391 char *retbuf = NULL;
392
393 if (buf != NULL)
394 tlen = sizeof(*combuf) + buf->l;
395 else
396 tlen = sizeof(*combuf);
397
398 retbuf = racoon_calloc(1, tlen);
399 if (retbuf == NULL) {
400 plog(LLV_ERROR, LOCATION, NULL,
401 "failed to allocate admin buffer\n");
402 return -1;
403 }
404
405 memcpy(retbuf, combuf, sizeof(*combuf));
406 ((struct admin_com *)retbuf)->ac_len = tlen;
407
408 if (buf != NULL)
409 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
410
411 tlen = send(so, retbuf, tlen, 0);
412 racoon_free(retbuf);
413 if (tlen < 0) {
414 plog(LLV_ERROR, LOCATION, NULL,
415 "failed to send admin command: %s\n",
416 strerror(errno));
417 return -1;
418 }
419
420 return 0;
421 }
422
423 /* ADMIN_PROTO -> SADB_SATYPE */
424 int
425 admin2pfkey_proto(proto)
426 u_int proto;
427 {
428 switch (proto) {
429 case ADMIN_PROTO_IPSEC:
430 return SADB_SATYPE_UNSPEC;
431 case ADMIN_PROTO_AH:
432 return SADB_SATYPE_AH;
433 case ADMIN_PROTO_ESP:
434 return SADB_SATYPE_ESP;
435 default:
436 plog(LLV_ERROR, LOCATION, NULL,
437 "unsupported proto for admin: %d\n", proto);
438 return -1;
439 }
440 /*NOTREACHED*/
441 }
442
443 int
444 admin_init()
445 {
446 memset(&sunaddr, 0, sizeof(sunaddr));
447 sunaddr.sun_family = AF_UNIX;
448 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
449 "%s", PORT_ADMIN);
450
451 lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
452 if (lcconf->sock_admin < 0) {
453 plog(LLV_ERROR, LOCATION, NULL,
454 "socket: %s\n", strerror(errno));
455 return -1;
456 }
457
458 if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
459 sizeof(sunaddr)) < 0) {
460 plog(LLV_ERROR, LOCATION, NULL,
461 "bind(sockname:%s): %s\n",
462 sunaddr.sun_path, strerror(errno));
463 (void)close(lcconf->sock_admin);
464 return -1;
465 }
466
467 if (listen(lcconf->sock_admin, 5) < 0) {
468 plog(LLV_ERROR, LOCATION, NULL,
469 "listen(sockname:%s): %s\n",
470 sunaddr.sun_path, strerror(errno));
471 (void)close(lcconf->sock_admin);
472 return -1;
473 }
474 plog(LLV_DEBUG, LOCATION, NULL,
475 "open %s as racoon management.\n", sunaddr.sun_path);
476
477 return 0;
478 }
479
480 int
481 admin_close()
482 {
483 close(lcconf->sock_admin);
484 unlink(sunaddr.sun_path);
485 return 0;
486 }