• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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