1 /* $NetBSD: admin.c,v 1.17.6.3 2009/04/20 13:32:57 tteras Exp $ */
2
3 /* Id: admin.c,v 1.25 2006/04/06 14:31:04 manubsd Exp */
4
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include "config.h"
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/signal.h>
40 #include <sys/stat.h>
41 #include <sys/un.h>
42
43 #include <net/pfkeyv2.h>
44
45 #include <netinet/in.h>
46 #include PATH_IPSEC_H
47
48
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <errno.h>
53 #include <netdb.h>
54 #ifdef HAVE_UNISTD_H
55 #include <unistd.h>
56 #endif
57 #ifdef ENABLE_HYBRID
58 #include <resolv.h>
59 #endif
60
61 #include "var.h"
62 #include "misc.h"
63 #include "vmbuf.h"
64 #include "plog.h"
65 #include "sockmisc.h"
66 #include "debug.h"
67
68 #include "schedule.h"
69 #include "localconf.h"
70 #include "remoteconf.h"
71 #include "grabmyaddr.h"
72 #include "isakmp_var.h"
73 #include "isakmp.h"
74 #include "oakley.h"
75 #include "handler.h"
76 #include "evt.h"
77 #include "pfkey.h"
78 #include "ipsec_doi.h"
79 #include "admin.h"
80 #include "admin_var.h"
81 #include "isakmp_inf.h"
82 #ifdef ENABLE_HYBRID
83 #include "isakmp_cfg.h"
84 #endif
85 #include "session.h"
86 #include "gcmalloc.h"
87
88 #ifdef ENABLE_ADMINPORT
89 char *adminsock_path = ADMINSOCK_PATH;
90 uid_t adminsock_owner = 0;
91 gid_t adminsock_group = 0;
92 mode_t adminsock_mode = 0600;
93
94 static struct sockaddr_un sunaddr;
95 static int admin_process __P((int, char *));
96 static int admin_reply __P((int, struct admin_com *, vchar_t *));
97
98 int
admin_handler()99 admin_handler()
100 {
101 int so2;
102 struct sockaddr_storage from;
103 socklen_t fromlen = sizeof(from);
104 struct admin_com com;
105 char *combuf = NULL;
106 int len, error = -1;
107
108 so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
109 if (so2 < 0) {
110 plog(LLV_ERROR, LOCATION, NULL,
111 "failed to accept admin command: %s\n",
112 strerror(errno));
113 return -1;
114 }
115
116 /* get buffer length */
117 while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
118 if (errno == EINTR)
119 continue;
120 plog(LLV_ERROR, LOCATION, NULL,
121 "failed to recv admin command: %s\n",
122 strerror(errno));
123 goto end;
124 }
125
126 /* sanity check */
127 if (len < sizeof(com)) {
128 plog(LLV_ERROR, LOCATION, NULL,
129 "invalid header length of admin command\n");
130 goto end;
131 }
132
133 /* get buffer to receive */
134 if ((combuf = racoon_malloc(com.ac_len)) == 0) {
135 plog(LLV_ERROR, LOCATION, NULL,
136 "failed to alloc buffer for admin command\n");
137 goto end;
138 }
139
140 /* get real data */
141 while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
142 if (errno == EINTR)
143 continue;
144 plog(LLV_ERROR, LOCATION, NULL,
145 "failed to recv admin command: %s\n",
146 strerror(errno));
147 goto end;
148 }
149
150 if (com.ac_cmd == ADMIN_RELOAD_CONF) {
151 /* reload does not work at all! */
152 signal_handler(SIGHUP);
153 goto end;
154 }
155
156 error = admin_process(so2, combuf);
157
158 end:
159 (void)close(so2);
160 if (combuf)
161 racoon_free(combuf);
162
163 return error;
164 }
165
166 /*
167 * main child's process.
168 */
169 static int
admin_process(so2,combuf)170 admin_process(so2, combuf)
171 int so2;
172 char *combuf;
173 {
174 struct admin_com *com = (struct admin_com *)combuf;
175 vchar_t *buf = NULL;
176 vchar_t *id = NULL;
177 vchar_t *key = NULL;
178 int idtype = 0;
179 int error = -1;
180
181 com->ac_errno = 0;
182
183 switch (com->ac_cmd) {
184 case ADMIN_RELOAD_CONF:
185 /* don't entered because of proccessing it in other place. */
186 plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n");
187 goto out;
188
189 case ADMIN_SHOW_SCHED:
190 {
191 caddr_t p = NULL;
192 int len;
193
194 com->ac_errno = -1;
195
196 if (sched_dump(&p, &len) == -1)
197 goto out2;
198
199 if ((buf = vmalloc(len)) == NULL)
200 goto out2;
201
202 memcpy(buf->v, p, len);
203
204 com->ac_errno = 0;
205 out2:
206 racoon_free(p);
207 break;
208 }
209
210 case ADMIN_SHOW_EVT:
211 /* It's not really an error, don't force racoonctl to quit */
212 if ((buf = evt_dump()) == NULL)
213 com->ac_errno = 0;
214 break;
215
216 case ADMIN_SHOW_SA:
217 case ADMIN_FLUSH_SA:
218 {
219 switch (com->ac_proto) {
220 case ADMIN_PROTO_ISAKMP:
221 switch (com->ac_cmd) {
222 case ADMIN_SHOW_SA:
223 buf = dumpph1();
224 if (buf == NULL)
225 com->ac_errno = -1;
226 break;
227 case ADMIN_FLUSH_SA:
228 flushph1();
229 break;
230 }
231 break;
232 case ADMIN_PROTO_IPSEC:
233 case ADMIN_PROTO_AH:
234 case ADMIN_PROTO_ESP:
235 switch (com->ac_cmd) {
236 case ADMIN_SHOW_SA:
237 {
238 u_int p;
239 p = admin2pfkey_proto(com->ac_proto);
240 if (p == -1)
241 goto out;
242 buf = pfkey_dump_sadb(p);
243 if (buf == NULL)
244 com->ac_errno = -1;
245 }
246 break;
247 case ADMIN_FLUSH_SA:
248 pfkey_flush_sadb(com->ac_proto);
249 break;
250 }
251 break;
252
253 case ADMIN_PROTO_INTERNAL:
254 switch (com->ac_cmd) {
255 case ADMIN_SHOW_SA:
256 buf = NULL; /*XXX dumpph2(&error);*/
257 if (buf == NULL)
258 com->ac_errno = error;
259 break;
260 case ADMIN_FLUSH_SA:
261 /*XXX flushph2();*/
262 com->ac_errno = 0;
263 break;
264 }
265 break;
266
267 default:
268 /* ignore */
269 com->ac_errno = -1;
270 }
271 }
272 break;
273
274 case ADMIN_DELETE_SA: {
275 struct ph1handle *iph1;
276 struct sockaddr *dst;
277 struct sockaddr *src;
278 char *loc, *rem;
279
280 src = (struct sockaddr *)
281 &((struct admin_com_indexes *)
282 ((caddr_t)com + sizeof(*com)))->src;
283 dst = (struct sockaddr *)
284 &((struct admin_com_indexes *)
285 ((caddr_t)com + sizeof(*com)))->dst;
286
287 loc = racoon_strdup(saddrwop2str(src));
288 rem = racoon_strdup(saddrwop2str(dst));
289 STRDUP_FATAL(loc);
290 STRDUP_FATAL(rem);
291
292 if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
293 plog(LLV_ERROR, LOCATION, NULL,
294 "phase 1 for %s -> %s not found\n", loc, rem);
295 } else {
296 if (iph1->status == PHASE1ST_ESTABLISHED)
297 isakmp_info_send_d1(iph1);
298 purge_remote(iph1);
299 }
300
301 racoon_free(loc);
302 racoon_free(rem);
303
304 break;
305 }
306
307 #ifdef ENABLE_HYBRID
308 case ADMIN_LOGOUT_USER: {
309 struct ph1handle *iph1;
310 char user[LOGINLEN+1];
311 int found = 0, len = com->ac_len - sizeof(com);
312
313 if (len > LOGINLEN) {
314 plog(LLV_ERROR, LOCATION, NULL,
315 "malformed message (login too long)\n");
316 break;
317 }
318
319 memcpy(user, (char *)(com + 1), len);
320 user[len] = 0;
321
322 found = purgeph1bylogin(user);
323 plog(LLV_INFO, LOCATION, NULL,
324 "deleted %d SA for user \"%s\"\n", found, user);
325
326 break;
327 }
328 #endif
329
330 case ADMIN_DELETE_ALL_SA_DST: {
331 struct ph1handle *iph1;
332 struct sockaddr *dst;
333 char *loc, *rem;
334
335 dst = (struct sockaddr *)
336 &((struct admin_com_indexes *)
337 ((caddr_t)com + sizeof(*com)))->dst;
338
339 rem = racoon_strdup(saddrwop2str(dst));
340 STRDUP_FATAL(rem);
341
342 plog(LLV_INFO, LOCATION, NULL,
343 "Flushing all SAs for peer %s\n", rem);
344
345 while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
346 loc = racoon_strdup(saddrwop2str(iph1->local));
347 STRDUP_FATAL(loc);
348
349 if (iph1->status == PHASE1ST_ESTABLISHED)
350 isakmp_info_send_d1(iph1);
351 purge_remote(iph1);
352
353 racoon_free(loc);
354 }
355
356 racoon_free(rem);
357
358 break;
359 }
360
361 case ADMIN_ESTABLISH_SA_PSK: {
362 struct admin_com_psk *acp;
363 char *data;
364
365 com->ac_cmd = ADMIN_ESTABLISH_SA;
366
367 acp = (struct admin_com_psk *)
368 ((char *)com + sizeof(*com) +
369 sizeof(struct admin_com_indexes));
370
371 idtype = acp->id_type;
372
373 if ((id = vmalloc(acp->id_len)) == NULL) {
374 plog(LLV_ERROR, LOCATION, NULL,
375 "cannot allocate memory: %s\n",
376 strerror(errno));
377 break;
378 }
379 data = (char *)(acp + 1);
380 memcpy(id->v, data, id->l);
381
382 if ((key = vmalloc(acp->key_len)) == NULL) {
383 plog(LLV_ERROR, LOCATION, NULL,
384 "cannot allocate memory: %s\n",
385 strerror(errno));
386 vfree(id);
387 id = NULL;
388 break;
389 }
390 data = (char *)(data + acp->id_len);
391 memcpy(key->v, data, key->l);
392 }
393 /* FALLTHROUGH */
394 case ADMIN_ESTABLISH_SA:
395 {
396 struct sockaddr *dst;
397 struct sockaddr *src;
398 src = (struct sockaddr *)
399 &((struct admin_com_indexes *)
400 ((caddr_t)com + sizeof(*com)))->src;
401 dst = (struct sockaddr *)
402 &((struct admin_com_indexes *)
403 ((caddr_t)com + sizeof(*com)))->dst;
404
405 switch (com->ac_proto) {
406 case ADMIN_PROTO_ISAKMP: {
407 struct remoteconf *rmconf;
408 struct sockaddr *remote = NULL;
409 struct sockaddr *local = NULL;
410 u_int16_t port;
411
412 com->ac_errno = -1;
413
414 /* search appropreate configuration */
415 rmconf = getrmconf(dst);
416 if (rmconf == NULL) {
417 plog(LLV_ERROR, LOCATION, NULL,
418 "no configuration found "
419 "for %s\n", saddrwop2str(dst));
420 goto out1;
421 }
422
423 /* get remote IP address and port number. */
424 if ((remote = dupsaddr(dst)) == NULL)
425 goto out1;
426
427 port = extract_port(rmconf->remote);
428 if (set_port(remote, port) == NULL)
429 goto out1;
430
431 /* get local address */
432 if ((local = dupsaddr(src)) == NULL)
433 goto out1;
434
435 port = getmyaddrsport(local);
436 if (set_port(local, port) == NULL)
437 goto out1;
438
439 #ifdef ENABLE_HYBRID
440 /* Set the id and key */
441 if (id && key) {
442 if (xauth_rmconf_used(&rmconf->xauth) == -1)
443 goto out1;
444
445 if (rmconf->xauth->login != NULL) {
446 vfree(rmconf->xauth->login);
447 rmconf->xauth->login = NULL;
448 }
449 if (rmconf->xauth->pass != NULL) {
450 vfree(rmconf->xauth->pass);
451 rmconf->xauth->pass = NULL;
452 }
453
454 rmconf->xauth->login = id;
455 rmconf->xauth->pass = key;
456 }
457 #endif
458
459 plog(LLV_INFO, LOCATION, NULL,
460 "accept a request to establish IKE-SA: "
461 "%s\n", saddrwop2str(remote));
462
463 /* begin ident mode */
464 if (isakmp_ph1begin_i(rmconf, remote, local) < 0)
465 goto out1;
466
467 com->ac_errno = 0;
468 out1:
469 if (local != NULL)
470 racoon_free(local);
471 if (remote != NULL)
472 racoon_free(remote);
473 break;
474 }
475 case ADMIN_PROTO_AH:
476 case ADMIN_PROTO_ESP:
477 break;
478 default:
479 /* ignore */
480 com->ac_errno = -1;
481 }
482 }
483 break;
484
485 default:
486 plog(LLV_ERROR, LOCATION, NULL,
487 "invalid command: %d\n", com->ac_cmd);
488 com->ac_errno = -1;
489 }
490
491 if ((error = admin_reply(so2, com, buf)) != 0)
492 goto out;
493
494 error = 0;
495 out:
496 if (buf != NULL)
497 vfree(buf);
498
499 return error;
500 }
501
502 static int
admin_reply(so,combuf,buf)503 admin_reply(so, combuf, buf)
504 int so;
505 struct admin_com *combuf;
506 vchar_t *buf;
507 {
508 int tlen;
509 char *retbuf = NULL;
510
511 if (buf != NULL)
512 tlen = sizeof(*combuf) + buf->l;
513 else
514 tlen = sizeof(*combuf);
515
516 retbuf = racoon_calloc(1, tlen);
517 if (retbuf == NULL) {
518 plog(LLV_ERROR, LOCATION, NULL,
519 "failed to allocate admin buffer\n");
520 return -1;
521 }
522
523 memcpy(retbuf, combuf, sizeof(*combuf));
524 ((struct admin_com *)retbuf)->ac_len = tlen;
525
526 if (buf != NULL)
527 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
528
529 tlen = send(so, retbuf, tlen, 0);
530 racoon_free(retbuf);
531 if (tlen < 0) {
532 plog(LLV_ERROR, LOCATION, NULL,
533 "failed to send admin command: %s\n",
534 strerror(errno));
535 return -1;
536 }
537
538 return 0;
539 }
540
541 /* ADMIN_PROTO -> SADB_SATYPE */
542 int
admin2pfkey_proto(proto)543 admin2pfkey_proto(proto)
544 u_int proto;
545 {
546 switch (proto) {
547 case ADMIN_PROTO_IPSEC:
548 return SADB_SATYPE_UNSPEC;
549 case ADMIN_PROTO_AH:
550 return SADB_SATYPE_AH;
551 case ADMIN_PROTO_ESP:
552 return SADB_SATYPE_ESP;
553 default:
554 plog(LLV_ERROR, LOCATION, NULL,
555 "unsupported proto for admin: %d\n", proto);
556 return -1;
557 }
558 /*NOTREACHED*/
559 }
560
561 int
admin_init()562 admin_init()
563 {
564 if (adminsock_path == NULL) {
565 lcconf->sock_admin = -1;
566 return 0;
567 }
568
569 memset(&sunaddr, 0, sizeof(sunaddr));
570 sunaddr.sun_family = AF_UNIX;
571 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
572 "%s", adminsock_path);
573
574 lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
575 if (lcconf->sock_admin == -1) {
576 plog(LLV_ERROR, LOCATION, NULL,
577 "socket: %s\n", strerror(errno));
578 return -1;
579 }
580
581 unlink(sunaddr.sun_path);
582 if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
583 sizeof(sunaddr)) != 0) {
584 plog(LLV_ERROR, LOCATION, NULL,
585 "bind(sockname:%s): %s\n",
586 sunaddr.sun_path, strerror(errno));
587 (void)close(lcconf->sock_admin);
588 return -1;
589 }
590
591 if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
592 plog(LLV_ERROR, LOCATION, NULL,
593 "chown(%s, %d, %d): %s\n",
594 sunaddr.sun_path, adminsock_owner,
595 adminsock_group, strerror(errno));
596 (void)close(lcconf->sock_admin);
597 return -1;
598 }
599
600 if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
601 plog(LLV_ERROR, LOCATION, NULL,
602 "chmod(%s, 0%03o): %s\n",
603 sunaddr.sun_path, adminsock_mode, strerror(errno));
604 (void)close(lcconf->sock_admin);
605 return -1;
606 }
607
608 if (listen(lcconf->sock_admin, 5) != 0) {
609 plog(LLV_ERROR, LOCATION, NULL,
610 "listen(sockname:%s): %s\n",
611 sunaddr.sun_path, strerror(errno));
612 (void)close(lcconf->sock_admin);
613 return -1;
614 }
615 plog(LLV_DEBUG, LOCATION, NULL,
616 "open %s as racoon management.\n", sunaddr.sun_path);
617
618 return 0;
619 }
620
621 int
admin_close()622 admin_close()
623 {
624 close(lcconf->sock_admin);
625 return 0;
626 }
627 #endif
628
629