admin.c revision 1.10
1/*	$NetBSD: admin.c,v 1.10 2006/09/26 20:58:03 manu 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#ifndef HAVE_NETINET6_IPSEC
47#include <netinet/ipsec.h>
48#else
49#include <netinet6/ipsec.h>
50#endif
51
52
53#include <stdlib.h>
54#include <stdio.h>
55#include <string.h>
56#include <errno.h>
57#include <netdb.h>
58#ifdef HAVE_UNISTD_H
59#include <unistd.h>
60#endif
61#ifdef ENABLE_HYBRID
62#include <resolv.h>
63#endif
64
65#include "var.h"
66#include "misc.h"
67#include "vmbuf.h"
68#include "plog.h"
69#include "sockmisc.h"
70#include "debug.h"
71
72#include "schedule.h"
73#include "localconf.h"
74#include "remoteconf.h"
75#include "grabmyaddr.h"
76#include "isakmp_var.h"
77#include "isakmp.h"
78#include "oakley.h"
79#include "handler.h"
80#include "evt.h"
81#include "pfkey.h"
82#include "ipsec_doi.h"
83#include "admin.h"
84#include "admin_var.h"
85#include "isakmp_inf.h"
86#ifdef ENABLE_HYBRID
87#include "isakmp_cfg.h"
88#endif
89#include "session.h"
90#include "gcmalloc.h"
91
92#ifdef ENABLE_ADMINPORT
93char *adminsock_path = ADMINSOCK_PATH;
94uid_t adminsock_owner = 0;
95gid_t adminsock_group = 0;
96mode_t adminsock_mode = 0600;
97
98static struct sockaddr_un sunaddr;
99static int admin_process __P((int, char *));
100static int admin_reply __P((int, struct admin_com *, vchar_t *));
101
102int
103admin_handler()
104{
105	int so2;
106	struct sockaddr_storage from;
107	socklen_t fromlen = sizeof(from);
108	struct admin_com com;
109	char *combuf = NULL;
110	pid_t pid = -1;
111	int len, error = -1;
112
113	so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
114	if (so2 < 0) {
115		plog(LLV_ERROR, LOCATION, NULL,
116			"failed to accept admin command: %s\n",
117			strerror(errno));
118		return -1;
119	}
120
121	/* get buffer length */
122	while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
123		if (errno == EINTR)
124			continue;
125		plog(LLV_ERROR, LOCATION, NULL,
126			"failed to recv admin command: %s\n",
127			strerror(errno));
128		goto end;
129	}
130
131	/* sanity check */
132	if (len < sizeof(com)) {
133		plog(LLV_ERROR, LOCATION, NULL,
134			"invalid header length of admin command\n");
135		goto end;
136	}
137
138	/* get buffer to receive */
139	if ((combuf = racoon_malloc(com.ac_len)) == 0) {
140		plog(LLV_ERROR, LOCATION, NULL,
141			"failed to alloc buffer for admin command\n");
142		goto end;
143	}
144
145	/* get real data */
146	while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
147		if (errno == EINTR)
148			continue;
149		plog(LLV_ERROR, LOCATION, NULL,
150			"failed to recv admin command: %s\n",
151			strerror(errno));
152		goto end;
153	}
154
155	if (com.ac_cmd == ADMIN_RELOAD_CONF) {
156		/* reload does not work at all! */
157		signal_handler(SIGHUP);
158		goto end;
159	}
160
161	error = admin_process(so2, combuf);
162
163    end:
164	(void)close(so2);
165	if (combuf)
166		racoon_free(combuf);
167
168	/* exit if child's process. */
169	if (pid == 0 && !f_foreground)
170		exit(error);
171
172	return error;
173}
174
175/*
176 * main child's process.
177 */
178static int
179admin_process(so2, combuf)
180	int so2;
181	char *combuf;
182{
183	struct admin_com *com = (struct admin_com *)combuf;
184	vchar_t *buf = NULL;
185	vchar_t *id = NULL;
186	vchar_t *key = NULL;
187	int idtype = 0;
188	int error = 0;
189
190	com->ac_errno = 0;
191
192	switch (com->ac_cmd) {
193	case ADMIN_RELOAD_CONF:
194		/* don't entered because of proccessing it in other place. */
195		plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n");
196		goto bad;
197
198	case ADMIN_SHOW_SCHED:
199	{
200		caddr_t p;
201		int len;
202		if (sched_dump(&p, &len) == -1) {
203			com->ac_errno = -1;
204			break;
205		}
206
207		buf = vmalloc(len);
208		if (buf == NULL) {
209			com->ac_errno = -1;
210			break;
211		}
212
213		memcpy(buf->v, p, len);
214		racoon_free(p);
215	}
216		break;
217
218	case ADMIN_SHOW_EVT:
219		/* It's not really an error, don't force racoonctl to quit */
220		if ((buf = evt_dump()) == NULL)
221			com->ac_errno = 0;
222		break;
223
224	case ADMIN_SHOW_SA:
225	case ADMIN_FLUSH_SA:
226	    {
227		switch (com->ac_proto) {
228		case ADMIN_PROTO_ISAKMP:
229			switch (com->ac_cmd) {
230			case ADMIN_SHOW_SA:
231				buf = dumpph1();
232				if (buf == NULL)
233					com->ac_errno = -1;
234				break;
235			case ADMIN_FLUSH_SA:
236				flushph1();
237				break;
238			}
239			break;
240		case ADMIN_PROTO_IPSEC:
241		case ADMIN_PROTO_AH:
242		case ADMIN_PROTO_ESP:
243			switch (com->ac_cmd) {
244			case ADMIN_SHOW_SA:
245			    {
246				u_int p;
247				p = admin2pfkey_proto(com->ac_proto);
248				if (p == -1)
249					goto bad;
250				buf = pfkey_dump_sadb(p);
251				if (buf == NULL)
252					com->ac_errno = -1;
253			    }
254				break;
255			case ADMIN_FLUSH_SA:
256				pfkey_flush_sadb(com->ac_proto);
257				break;
258			}
259			break;
260
261		case ADMIN_PROTO_INTERNAL:
262			switch (com->ac_cmd) {
263			case ADMIN_SHOW_SA:
264				buf = NULL; /*XXX dumpph2(&error);*/
265				if (buf == NULL)
266					com->ac_errno = error;
267				break;
268			case ADMIN_FLUSH_SA:
269				/*XXX flushph2();*/
270				com->ac_errno = 0;
271				break;
272			}
273			break;
274
275		default:
276			/* ignore */
277			com->ac_errno = -1;
278		}
279	    }
280		break;
281
282	case ADMIN_DELETE_SA: {
283		struct ph1handle *iph1;
284		struct sockaddr *dst;
285		struct sockaddr *src;
286		char *loc, *rem;
287
288		src = (struct sockaddr *)
289			&((struct admin_com_indexes *)
290			    ((caddr_t)com + sizeof(*com)))->src;
291		dst = (struct sockaddr *)
292			&((struct admin_com_indexes *)
293			    ((caddr_t)com + sizeof(*com)))->dst;
294
295		loc = racoon_strdup(saddrwop2str(src));
296		rem = racoon_strdup(saddrwop2str(dst));
297		STRDUP_FATAL(loc);
298		STRDUP_FATAL(rem);
299
300		if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
301			plog(LLV_ERROR, LOCATION, NULL,
302			    "phase 1 for %s -> %s not found\n", loc, rem);
303		} else {
304			if (iph1->status == PHASE1ST_ESTABLISHED)
305				isakmp_info_send_d1(iph1);
306			purge_remote(iph1);
307		}
308
309		racoon_free(loc);
310		racoon_free(rem);
311
312		break;
313	}
314
315#ifdef ENABLE_HYBRID
316	case ADMIN_LOGOUT_USER: {
317		struct ph1handle *iph1;
318		char *user;
319		int found = 0;
320
321		if (com->ac_len > sizeof(com) + LOGINLEN + 1) {
322			plog(LLV_ERROR, LOCATION, NULL,
323			    "malformed message (login too long)\n");
324			break;
325		}
326
327		user = (char *)(com + 1);
328		found = purgeph1bylogin(user);
329		plog(LLV_INFO, LOCATION, NULL,
330		    "deleted %d SA for user \"%s\"\n", found, user);
331
332		break;
333	}
334#endif
335
336	case ADMIN_DELETE_ALL_SA_DST: {
337		struct ph1handle *iph1;
338		struct sockaddr *dst;
339		char *loc, *rem;
340
341		dst = (struct sockaddr *)
342			&((struct admin_com_indexes *)
343			    ((caddr_t)com + sizeof(*com)))->dst;
344
345		rem = racoon_strdup(saddrwop2str(dst));
346		STRDUP_FATAL(rem);
347
348		plog(LLV_INFO, LOCATION, NULL,
349		    "Flushing all SAs for peer %s\n", rem);
350
351		while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
352			loc = racoon_strdup(saddrwop2str(iph1->local));
353			STRDUP_FATAL(loc);
354
355			if (iph1->status == PHASE1ST_ESTABLISHED)
356				isakmp_info_send_d1(iph1);
357			purge_remote(iph1);
358
359			racoon_free(loc);
360		}
361
362		racoon_free(rem);
363
364		break;
365	}
366
367	case ADMIN_ESTABLISH_SA_PSK: {
368		struct admin_com_psk *acp;
369		char *data;
370
371		com->ac_cmd = ADMIN_ESTABLISH_SA;
372
373		acp = (struct admin_com_psk *)
374		    ((char *)com + sizeof(*com) +
375		    sizeof(struct admin_com_indexes));
376
377		idtype = acp->id_type;
378
379		if ((id = vmalloc(acp->id_len)) == NULL) {
380			plog(LLV_ERROR, LOCATION, NULL,
381			    "cannot allocate memory: %s\n",
382			    strerror(errno));
383			break;
384		}
385		data = (char *)(acp + 1);
386		memcpy(id->v, data, id->l);
387
388		if ((key = vmalloc(acp->key_len)) == NULL) {
389			plog(LLV_ERROR, LOCATION, NULL,
390			    "cannot allocate memory: %s\n",
391			    strerror(errno));
392			vfree(id);
393			break;
394		}
395		data = (char *)(data + acp->id_len);
396		memcpy(key->v, data, key->l);
397	}
398	/* FALLTHROUGH */
399	case ADMIN_ESTABLISH_SA:
400	    {
401		struct sockaddr *dst;
402		struct sockaddr *src;
403		src = (struct sockaddr *)
404			&((struct admin_com_indexes *)
405			    ((caddr_t)com + sizeof(*com)))->src;
406		dst = (struct sockaddr *)
407			&((struct admin_com_indexes *)
408			    ((caddr_t)com + sizeof(*com)))->dst;
409
410		switch (com->ac_proto) {
411		case ADMIN_PROTO_ISAKMP:
412		    {
413			struct remoteconf *rmconf;
414			struct sockaddr *remote;
415			struct sockaddr *local;
416
417			/* search appropreate configuration */
418			rmconf = getrmconf(dst);
419			if (rmconf == NULL) {
420				plog(LLV_ERROR, LOCATION, NULL,
421					"no configuration found "
422					"for %s\n", saddrwop2str(dst));
423				com->ac_errno = -1;
424				break;
425			}
426
427			/* get remote IP address and port number. */
428			remote = dupsaddr(dst);
429			if (remote == NULL) {
430				com->ac_errno = -1;
431				break;
432			}
433			switch (remote->sa_family) {
434			case AF_INET:
435				((struct sockaddr_in *)remote)->sin_port =
436					((struct sockaddr_in *)rmconf->remote)->sin_port;
437				break;
438#ifdef INET6
439			case AF_INET6:
440				((struct sockaddr_in6 *)remote)->sin6_port =
441					((struct sockaddr_in6 *)rmconf->remote)->sin6_port;
442				break;
443#endif
444			default:
445				plog(LLV_ERROR, LOCATION, NULL,
446					"invalid family: %d\n",
447					remote->sa_family);
448				com->ac_errno = -1;
449				break;
450			}
451
452			/* get local address */
453			local = dupsaddr(src);
454			if (local == NULL) {
455				com->ac_errno = -1;
456				break;
457			}
458			switch (local->sa_family) {
459			case AF_INET:
460				((struct sockaddr_in *)local)->sin_port =
461					getmyaddrsport(local);
462				break;
463#ifdef INET6
464			case AF_INET6:
465				((struct sockaddr_in6 *)local)->sin6_port =
466					getmyaddrsport(local);
467				break;
468#endif
469			default:
470				plog(LLV_ERROR, LOCATION, NULL,
471					"invalid family: %d\n",
472					local->sa_family);
473				com->ac_errno = -1;
474				break;
475			}
476
477#ifdef ENABLE_HYBRID
478			/* Set the id and key */
479			if (id && key) {
480				if (xauth_rmconf_used(&rmconf->xauth) == -1) {
481					com->ac_errno = -1;
482					break;
483				}
484
485				if (rmconf->xauth->login != NULL) {
486					vfree(rmconf->xauth->login);
487					rmconf->xauth->login = NULL;
488				}
489				if (rmconf->xauth->pass != NULL) {
490					vfree(rmconf->xauth->pass);
491					rmconf->xauth->pass = NULL;
492				}
493
494				rmconf->xauth->login = id;
495				rmconf->xauth->pass = key;
496			}
497#endif
498
499			plog(LLV_INFO, LOCATION, NULL,
500				"accept a request to establish IKE-SA: "
501				"%s\n", saddrwop2str(remote));
502
503			/* begin ident mode */
504			if (isakmp_ph1begin_i(rmconf, remote, local) < 0) {
505				com->ac_errno = -1;
506				break;
507			}
508		    }
509			break;
510		case ADMIN_PROTO_AH:
511		case ADMIN_PROTO_ESP:
512			break;
513		default:
514			/* ignore */
515			com->ac_errno = -1;
516		}
517	    }
518		break;
519
520	default:
521		plog(LLV_ERROR, LOCATION, NULL,
522			"invalid command: %d\n", com->ac_cmd);
523		com->ac_errno = -1;
524	}
525
526	if (admin_reply(so2, com, buf) < 0)
527		goto bad;
528
529	if (buf != NULL)
530		vfree(buf);
531
532	if (key != NULL)
533		vfree(key);
534
535	return 0;
536
537    bad:
538	if (buf != NULL)
539		vfree(buf);
540
541	if (key != NULL)
542		vfree(key);
543
544	return -1;
545}
546
547static int
548admin_reply(so, combuf, buf)
549	int so;
550	struct admin_com *combuf;
551	vchar_t *buf;
552{
553	int tlen;
554	char *retbuf = NULL;
555
556	if (buf != NULL)
557		tlen = sizeof(*combuf) + buf->l;
558	else
559		tlen = sizeof(*combuf);
560
561	retbuf = racoon_calloc(1, tlen);
562	if (retbuf == NULL) {
563		plog(LLV_ERROR, LOCATION, NULL,
564			"failed to allocate admin buffer\n");
565		return -1;
566	}
567
568	memcpy(retbuf, combuf, sizeof(*combuf));
569	((struct admin_com *)retbuf)->ac_len = tlen;
570
571	if (buf != NULL)
572		memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
573
574	tlen = send(so, retbuf, tlen, 0);
575	racoon_free(retbuf);
576	if (tlen < 0) {
577		plog(LLV_ERROR, LOCATION, NULL,
578			"failed to send admin command: %s\n",
579			strerror(errno));
580		return -1;
581	}
582
583	return 0;
584}
585
586/* ADMIN_PROTO -> SADB_SATYPE */
587int
588admin2pfkey_proto(proto)
589	u_int proto;
590{
591	switch (proto) {
592	case ADMIN_PROTO_IPSEC:
593		return SADB_SATYPE_UNSPEC;
594	case ADMIN_PROTO_AH:
595		return SADB_SATYPE_AH;
596	case ADMIN_PROTO_ESP:
597		return SADB_SATYPE_ESP;
598	default:
599		plog(LLV_ERROR, LOCATION, NULL,
600			"unsupported proto for admin: %d\n", proto);
601		return -1;
602	}
603	/*NOTREACHED*/
604}
605
606int
607admin_init()
608{
609	if (adminsock_path == NULL) {
610		lcconf->sock_admin = -1;
611		return 0;
612	}
613
614	memset(&sunaddr, 0, sizeof(sunaddr));
615	sunaddr.sun_family = AF_UNIX;
616	snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
617		"%s", adminsock_path);
618
619	lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
620	if (lcconf->sock_admin == -1) {
621		plog(LLV_ERROR, LOCATION, NULL,
622			"socket: %s\n", strerror(errno));
623		return -1;
624	}
625
626	unlink(sunaddr.sun_path);
627	if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
628			sizeof(sunaddr)) != 0) {
629		plog(LLV_ERROR, LOCATION, NULL,
630			"bind(sockname:%s): %s\n",
631			sunaddr.sun_path, strerror(errno));
632		(void)close(lcconf->sock_admin);
633		return -1;
634	}
635
636	if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
637		plog(LLV_ERROR, LOCATION, NULL,
638		    "chown(%s, %d, %d): %s\n",
639		    sunaddr.sun_path, adminsock_owner,
640		    adminsock_group, strerror(errno));
641		(void)close(lcconf->sock_admin);
642		return -1;
643	}
644
645	if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
646		plog(LLV_ERROR, LOCATION, NULL,
647		    "chmod(%s, 0%03o): %s\n",
648		    sunaddr.sun_path, adminsock_mode, strerror(errno));
649		(void)close(lcconf->sock_admin);
650		return -1;
651	}
652
653	if (listen(lcconf->sock_admin, 5) != 0) {
654		plog(LLV_ERROR, LOCATION, NULL,
655			"listen(sockname:%s): %s\n",
656			sunaddr.sun_path, strerror(errno));
657		(void)close(lcconf->sock_admin);
658		return -1;
659	}
660	plog(LLV_DEBUG, LOCATION, NULL,
661		"open %s as racoon management.\n", sunaddr.sun_path);
662
663	return 0;
664}
665
666int
667admin_close()
668{
669	close(lcconf->sock_admin);
670	return 0;
671}
672#endif
673
674