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