File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / admin.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    1: /*	$NetBSD: admin.c,v 1.38 2010/12/08 07:38:35 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 "policy.h"
   80: #include "admin.h"
   81: #include "admin_var.h"
   82: #include "isakmp_inf.h"
   83: #ifdef ENABLE_HYBRID
   84: #include "isakmp_cfg.h"
   85: #endif
   86: #include "session.h"
   87: #include "gcmalloc.h"
   88: 
   89: #ifdef ENABLE_ADMINPORT
   90: char *adminsock_path = ADMINSOCK_PATH;
   91: uid_t adminsock_owner = 0;
   92: gid_t adminsock_group = 0;
   93: mode_t adminsock_mode = 0600;
   94: 
   95: static struct sockaddr_un sunaddr;
   96: static int admin_process __P((int, char *));
   97: static int admin_reply __P((int, struct admin_com *, int, vchar_t *));
   98: 
   99: static int
  100: admin_handler(ctx, fd)
  101: 	void *ctx;
  102: 	int fd;
  103: {
  104: 	int so2;
  105: 	struct sockaddr_storage from;
  106: 	socklen_t fromlen = sizeof(from);
  107: 	struct admin_com com;
  108: 	char *combuf = NULL;
  109: 	int len, error = -1;
  110: 
  111: 	so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
  112: 	if (so2 < 0) {
  113: 		plog(LLV_ERROR, LOCATION, NULL,
  114: 			"failed to accept admin command: %s\n",
  115: 			strerror(errno));
  116: 		return -1;
  117: 	}
  118: 	close_on_exec(so2);
  119: 
  120: 	/* get buffer length */
  121: 	while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 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: 	/* sanity check */
  131: 	if (len < sizeof(com)) {
  132: 		plog(LLV_ERROR, LOCATION, NULL,
  133: 			"invalid header length of admin command\n");
  134: 		goto end;
  135: 	}
  136: 
  137: 	/* get buffer to receive */
  138: 	if ((combuf = racoon_malloc(com.ac_len)) == 0) {
  139: 		plog(LLV_ERROR, LOCATION, NULL,
  140: 			"failed to alloc buffer for admin command\n");
  141: 		goto end;
  142: 	}
  143: 
  144: 	/* get real data */
  145: 	while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
  146: 		if (errno == EINTR)
  147: 			continue;
  148: 		plog(LLV_ERROR, LOCATION, NULL,
  149: 			"failed to recv admin command: %s\n",
  150: 			strerror(errno));
  151: 		goto end;
  152: 	}
  153: 
  154: 	error = admin_process(so2, combuf);
  155: 
  156: end:
  157: 	if (error == -2) {
  158: 		plog(LLV_DEBUG, LOCATION, NULL,
  159: 			"[%d] admin connection established\n", so2);
  160: 	} else {
  161: 		(void)close(so2);
  162: 	}
  163: 
  164: 	if (combuf)
  165: 		racoon_free(combuf);
  166: 
  167: 	return error;
  168: }
  169: 
  170: static int admin_ph1_delete_sa(struct ph1handle *iph1, void *arg)
  171: {
  172: 	if (iph1->status >= PHASE1ST_ESTABLISHED)
  173: 		isakmp_info_send_d1(iph1);
  174: 	purge_remote(iph1);
  175: 	return 0;
  176: }
  177: 
  178: /*
  179:  * main child's process.
  180:  */
  181: static int
  182: admin_process(so2, combuf)
  183: 	int so2;
  184: 	char *combuf;
  185: {
  186: 	struct admin_com *com = (struct admin_com *)combuf;
  187: 	vchar_t *buf = NULL;
  188: 	vchar_t *id = NULL;
  189: 	vchar_t *key = NULL;
  190: 	int idtype = 0;
  191: 	int error = 0, l_ac_errno = 0;
  192: 	struct evt_listener_list *event_list = NULL;
  193: 
  194: 	if (com->ac_cmd & ADMIN_FLAG_VERSION)
  195: 		com->ac_cmd &= ~ADMIN_FLAG_VERSION;
  196: 	else
  197: 		com->ac_version = 0;
  198: 
  199: 	switch (com->ac_cmd) {
  200: 	case ADMIN_RELOAD_CONF:
  201: 		signal_handler(SIGHUP);
  202: 		break;
  203: 
  204: 	case ADMIN_SHOW_SCHED: {
  205: 		caddr_t p = NULL;
  206: 		int len;
  207: 
  208: 		if (sched_dump(&p, &len) != -1) {
  209: 			buf = vmalloc(len);
  210: 			if (buf != NULL)
  211: 				memcpy(buf->v, p, len);
  212: 			else
  213: 				l_ac_errno = ENOMEM;
  214: 			racoon_free(p);
  215: 		} else
  216: 			l_ac_errno = ENOMEM;
  217: 		break;
  218: 	}
  219: 
  220: 	case ADMIN_SHOW_EVT:
  221: 		if (com->ac_version == 0) {
  222: 			buf = evt_dump();
  223: 			l_ac_errno = 0;
  224: 		}
  225: 		break;
  226: 
  227: 	case ADMIN_SHOW_SA:
  228: 		switch (com->ac_proto) {
  229: 		case ADMIN_PROTO_ISAKMP:
  230: 			buf = dumpph1();
  231: 			if (buf == NULL)
  232: 				l_ac_errno = ENOMEM;
  233: 			break;
  234: 		case ADMIN_PROTO_IPSEC:
  235: 		case ADMIN_PROTO_AH:
  236: 		case ADMIN_PROTO_ESP: {
  237: 			u_int p;
  238: 			p = admin2pfkey_proto(com->ac_proto);
  239: 			if (p != -1) {
  240: 				buf = pfkey_dump_sadb(p);
  241: 				if (buf == NULL)
  242: 					l_ac_errno = ENOMEM;
  243: 			} else
  244: 				l_ac_errno = EINVAL;
  245: 			break;
  246: 		}
  247: 		case ADMIN_PROTO_INTERNAL:
  248: 		default:
  249: 			l_ac_errno = ENOTSUP;
  250: 			break;
  251: 		}
  252: 		break;
  253: 
  254: 	case ADMIN_GET_SA_CERT: {
  255: 		struct admin_com_indexes *ndx;
  256: 		struct sockaddr *src, *dst;
  257: 		struct ph1handle *iph1;
  258: 
  259: 		ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
  260: 		src = (struct sockaddr *) &ndx->src;
  261: 		dst = (struct sockaddr *) &ndx->dst;
  262: 
  263: 		if (com->ac_proto != ADMIN_PROTO_ISAKMP) {
  264: 			l_ac_errno = ENOTSUP;
  265: 			break;
  266: 		}
  267: 
  268: 		iph1 = getph1byaddr(src, dst, 0);
  269: 		if (iph1 == NULL) {
  270: 			l_ac_errno = ENOENT;
  271: 			break;
  272: 		}
  273: 
  274: 		if (iph1->cert_p != NULL) {
  275: 			vchar_t tmp;
  276: 			tmp.v = iph1->cert_p->v + 1;
  277: 			tmp.l = iph1->cert_p->l - 1;
  278: 			buf = vdup(&tmp);
  279: 		}
  280: 		break;
  281: 	}
  282: 
  283: 	case ADMIN_FLUSH_SA:
  284: 		switch (com->ac_proto) {
  285: 		case ADMIN_PROTO_ISAKMP:
  286: 			flushph1();
  287: 			break;
  288: 		case ADMIN_PROTO_IPSEC:
  289: 		case ADMIN_PROTO_AH:
  290: 		case ADMIN_PROTO_ESP:
  291: 			pfkey_flush_sadb(com->ac_proto);
  292: 			break;
  293: 		case ADMIN_PROTO_INTERNAL:
  294: 			/*XXX flushph2();*/
  295: 		default:
  296: 			l_ac_errno = ENOTSUP;
  297: 			break;
  298: 		}
  299: 		break;
  300: 
  301: 	case ADMIN_DELETE_SA: {
  302: 		char *loc, *rem;
  303: 		struct ph1selector sel;
  304: 
  305: 		memset(&sel, 0, sizeof(sel));
  306: 		sel.local = (struct sockaddr *)
  307: 			&((struct admin_com_indexes *)
  308: 			    ((caddr_t)com + sizeof(*com)))->src;
  309: 		sel.remote = (struct sockaddr *)
  310: 			&((struct admin_com_indexes *)
  311: 			    ((caddr_t)com + sizeof(*com)))->dst;
  312: 
  313: 		loc = racoon_strdup(saddr2str(sel.local));
  314: 		rem = racoon_strdup(saddr2str(sel.remote));
  315: 		STRDUP_FATAL(loc);
  316: 		STRDUP_FATAL(rem);
  317: 
  318: 		plog(LLV_INFO, LOCATION, NULL,
  319: 		     "admin delete-sa %s %s\n", loc, rem);
  320: 		enumph1(&sel, admin_ph1_delete_sa, NULL);
  321: 		remcontacted(sel.remote);
  322: 
  323: 		racoon_free(loc);
  324: 		racoon_free(rem);
  325: 		break;
  326: 	}
  327: 
  328: #ifdef ENABLE_HYBRID
  329: 	case ADMIN_LOGOUT_USER: {
  330: 		struct ph1handle *iph1;
  331: 		char user[LOGINLEN+1];
  332: 		int found = 0, len = com->ac_len - sizeof(*com);
  333: 
  334: 		if (len > LOGINLEN) {
  335: 			plog(LLV_ERROR, LOCATION, NULL,
  336: 			    "malformed message (login too long)\n");
  337: 			break;
  338: 		}
  339: 
  340: 		memcpy(user, (char *)(com + 1), len);
  341: 		user[len] = 0;
  342: 
  343: 		found = purgeph1bylogin(user);
  344: 		plog(LLV_INFO, LOCATION, NULL,
  345: 		    "deleted %d SA for user \"%s\"\n", found, user);
  346: 
  347: 		break;
  348: 	}
  349: #endif
  350: 
  351: 	case ADMIN_DELETE_ALL_SA_DST: {
  352: 		struct ph1handle *iph1;
  353: 		struct sockaddr *dst;
  354: 		char *loc, *rem;
  355: 
  356: 		dst = (struct sockaddr *)
  357: 			&((struct admin_com_indexes *)
  358: 			    ((caddr_t)com + sizeof(*com)))->dst;
  359: 
  360: 		rem = racoon_strdup(saddrwop2str(dst));
  361: 		STRDUP_FATAL(rem);
  362: 
  363: 		plog(LLV_INFO, LOCATION, NULL,
  364: 		    "Flushing all SAs for peer %s\n", rem);
  365: 
  366: 		while ((iph1 = getph1bydstaddr(dst)) != NULL) {
  367: 			loc = racoon_strdup(saddrwop2str(iph1->local));
  368: 			STRDUP_FATAL(loc);
  369: 
  370: 			if (iph1->status >= PHASE1ST_ESTABLISHED)
  371: 				isakmp_info_send_d1(iph1);
  372: 			purge_remote(iph1);
  373: 
  374: 			racoon_free(loc);
  375: 		}
  376: 
  377: 		racoon_free(rem);
  378: 		break;
  379: 	}
  380: 
  381: 	case ADMIN_ESTABLISH_SA_PSK: {
  382: 		struct admin_com_psk *acp;
  383: 		char *data;
  384: 
  385: 		acp = (struct admin_com_psk *)
  386: 		    ((char *)com + sizeof(*com) +
  387: 		    sizeof(struct admin_com_indexes));
  388: 
  389: 		idtype = acp->id_type;
  390: 
  391: 		if ((id = vmalloc(acp->id_len)) == NULL) {
  392: 			plog(LLV_ERROR, LOCATION, NULL,
  393: 			    "cannot allocate memory: %s\n",
  394: 			    strerror(errno));
  395: 			break;
  396: 		}
  397: 		data = (char *)(acp + 1);
  398: 		memcpy(id->v, data, id->l);
  399: 
  400: 		if ((key = vmalloc(acp->key_len)) == NULL) {
  401: 			plog(LLV_ERROR, LOCATION, NULL,
  402: 			    "cannot allocate memory: %s\n",
  403: 			    strerror(errno));
  404: 			vfree(id);
  405: 			id = NULL;
  406: 			break;
  407: 		}
  408: 		data = (char *)(data + acp->id_len);
  409: 		memcpy(key->v, data, key->l);
  410: 	}
  411: 	/* FALLTHROUGH */
  412: 	case ADMIN_ESTABLISH_SA: {
  413: 		struct admin_com_indexes *ndx;
  414: 		struct sockaddr *dst;
  415: 		struct sockaddr *src;
  416: 		char *name = NULL;
  417: 
  418: 		ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
  419: 		src = (struct sockaddr *) &ndx->src;
  420: 		dst = (struct sockaddr *) &ndx->dst;
  421: 
  422: 		if (com->ac_cmd == ADMIN_ESTABLISH_SA &&
  423: 		    com->ac_len > sizeof(*com) + sizeof(*ndx))
  424: 			name = (char *) ((caddr_t) ndx + sizeof(*ndx));
  425: 
  426: 		switch (com->ac_proto) {
  427: 		case ADMIN_PROTO_ISAKMP: {
  428: 			struct ph1handle *ph1;
  429: 			struct remoteconf *rmconf;
  430: 			u_int16_t port;
  431: 
  432: 			l_ac_errno = -1;
  433: 
  434: 			/* connected already? */
  435: 			ph1 = getph1byaddr(src, dst, 0);
  436: 			if (ph1 != NULL) {
  437: 				event_list = &ph1->evt_listeners;
  438: 				if (ph1->status == PHASE1ST_ESTABLISHED)
  439: 					l_ac_errno = EEXIST;
  440: 				else
  441: 					l_ac_errno = 0;
  442: 				break;
  443: 			}
  444: 
  445: 			/* search appropreate configuration */
  446: 			if (name == NULL)
  447: 				rmconf = getrmconf(dst, 0);
  448: 			else
  449: 				rmconf = getrmconf_by_name(name);
  450: 			if (rmconf == NULL) {
  451: 				plog(LLV_ERROR, LOCATION, NULL,
  452: 					"no configuration found "
  453: 					"for %s\n", saddrwop2str(dst));
  454: 				break;
  455: 			}
  456: 
  457: #ifdef ENABLE_HYBRID
  458: 			/* XXX This overwrites rmconf information globally. */
  459: 			/* Set the id and key */
  460: 			if (id && key) {
  461: 				if (xauth_rmconf_used(&rmconf->xauth) == -1)
  462: 					break;
  463: 
  464: 				if (rmconf->xauth->login != NULL) {
  465: 					vfree(rmconf->xauth->login);
  466: 					rmconf->xauth->login = NULL;
  467: 				}
  468: 				if (rmconf->xauth->pass != NULL) {
  469: 					vfree(rmconf->xauth->pass);
  470: 					rmconf->xauth->pass = NULL;
  471: 				}
  472: 
  473: 				rmconf->xauth->login = id;
  474: 				rmconf->xauth->pass = key;
  475: 			}
  476: #endif
  477: 
  478: 			plog(LLV_INFO, LOCATION, NULL,
  479: 				"accept a request to establish IKE-SA: "
  480: 				"%s\n", saddrwop2str(dst));
  481: 
  482: 			/* begin ident mode */
  483: 			ph1 = isakmp_ph1begin_i(rmconf, dst, src);
  484: 			if (ph1 == NULL)
  485: 				break;
  486: 
  487: 			event_list = &ph1->evt_listeners;
  488: 			l_ac_errno = 0;
  489: 			break;
  490: 		}
  491: 		case ADMIN_PROTO_AH:
  492: 		case ADMIN_PROTO_ESP: {
  493: 			struct ph2handle *iph2;
  494: 			struct secpolicy *sp_out = NULL, *sp_in = NULL;
  495: 			struct policyindex spidx;
  496: 
  497: 			l_ac_errno = -1;
  498: 
  499: 			/* got outbound policy */
  500: 			memset(&spidx, 0, sizeof(spidx));
  501: 			spidx.dir = IPSEC_DIR_OUTBOUND;
  502: 			memcpy(&spidx.src, src, sizeof(spidx.src));
  503: 			memcpy(&spidx.dst, dst, sizeof(spidx.dst));
  504: 			spidx.prefs = ndx->prefs;
  505: 			spidx.prefd = ndx->prefd;
  506: 			spidx.ul_proto = ndx->ul_proto;
  507: 
  508: 			sp_out = getsp_r(&spidx);
  509: 			if (sp_out) {
  510: 				plog(LLV_DEBUG, LOCATION, NULL,
  511: 					"suitable outbound SP found: %s.\n",
  512: 					spidx2str(&sp_out->spidx));
  513: 			} else {
  514: 				l_ac_errno = ENOENT;
  515: 				plog(LLV_NOTIFY, LOCATION, NULL,
  516: 					"no outbound policy found: %s\n",
  517: 					spidx2str(&spidx));
  518: 				break;
  519: 			}
  520: 
  521: 			iph2 = getph2byid(src, dst, sp_out->id);
  522: 			if (iph2 != NULL) {
  523: 				event_list = &iph2->evt_listeners;
  524: 				if (iph2->status == PHASE2ST_ESTABLISHED)
  525: 					l_ac_errno = EEXIST;
  526: 				else
  527: 					l_ac_errno = 0;
  528: 				break;
  529: 			}
  530: 
  531: 			/* get inbound policy */
  532: 			memset(&spidx, 0, sizeof(spidx));
  533: 			spidx.dir = IPSEC_DIR_INBOUND;
  534: 			memcpy(&spidx.src, dst, sizeof(spidx.src));
  535: 			memcpy(&spidx.dst, src, sizeof(spidx.dst));
  536: 			spidx.prefs = ndx->prefd;
  537: 			spidx.prefd = ndx->prefs;
  538: 			spidx.ul_proto = ndx->ul_proto;
  539: 
  540: 			sp_in = getsp_r(&spidx);
  541: 			if (sp_in) {
  542: 				plog(LLV_DEBUG, LOCATION, NULL,
  543: 					"suitable inbound SP found: %s.\n",
  544: 					spidx2str(&sp_in->spidx));
  545: 			} else {
  546: 				l_ac_errno = ENOENT;
  547: 				plog(LLV_NOTIFY, LOCATION, NULL,
  548: 					"no inbound policy found: %s\n",
  549: 				spidx2str(&spidx));
  550: 				break;
  551: 			}
  552: 
  553: 			/* allocate a phase 2 */
  554: 			iph2 = newph2();
  555: 			if (iph2 == NULL) {
  556: 				plog(LLV_ERROR, LOCATION, NULL,
  557: 					"failed to allocate phase2 entry.\n");
  558: 				break;
  559: 			}
  560: 			iph2->side = INITIATOR;
  561: 			iph2->satype = admin2pfkey_proto(com->ac_proto);
  562: 			iph2->spid = sp_out->id;
  563: 			iph2->seq = pk_getseq();
  564: 			iph2->status = PHASE2ST_STATUS2;
  565: 
  566: 			/* set end addresses of SA */
  567: 			iph2->sa_dst = dupsaddr(dst);
  568: 			iph2->sa_src = dupsaddr(src);
  569: 			iph2->dst = dupsaddr(dst);
  570: 			iph2->src = dupsaddr(src);
  571: 			if (iph2->sa_src == NULL || iph2->sa_dst == NULL ||
  572: 			    iph2->dst == NULL || iph2->src == NULL) {
  573: 				delph2(iph2);
  574: 				break;
  575: 			}
  576: 			set_port(iph2->dst, 0);
  577: 			set_port(iph2->src, 0);
  578: 
  579: 			if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
  580: 				delph2(iph2);
  581: 				break;
  582: 			}
  583: 
  584: 			insph2(iph2);
  585: 			if (isakmp_post_acquire(iph2, NULL, FALSE) < 0) {
  586: 				remph2(iph2);
  587: 				delph2(iph2);
  588: 				break;
  589: 			}
  590: 
  591: 			event_list = &iph2->evt_listeners;
  592: 			l_ac_errno = 0;
  593: 			break;
  594: 		}
  595: 		default:
  596: 			/* ignore */
  597: 			l_ac_errno = ENOTSUP;
  598: 		}
  599: 		break;
  600: 	}
  601: 
  602: 	default:
  603: 		plog(LLV_ERROR, LOCATION, NULL,
  604: 			"invalid command: %d\n", com->ac_cmd);
  605: 		l_ac_errno = ENOTSUP;
  606: 	}
  607: 
  608: 	if ((error = admin_reply(so2, com, l_ac_errno, buf)) != 0)
  609: 		goto out;
  610: 
  611: 	/* start pushing events if so requested */
  612: 	if ((l_ac_errno == 0) &&
  613: 	    (com->ac_version >= 1) &&
  614: 	    (com->ac_cmd == ADMIN_SHOW_EVT || event_list != NULL))
  615: 		error = evt_subscribe(event_list, so2);
  616: out:
  617: 	if (buf != NULL)
  618: 		vfree(buf);
  619: 
  620: 	return error;
  621: }
  622: 
  623: static int
  624: admin_reply(so, req, l_ac_errno, buf)
  625: 	int so, l_ac_errno;
  626: 	struct admin_com *req;
  627: 	vchar_t *buf;
  628: {
  629: 	int tlen;
  630: 	struct admin_com *combuf;
  631: 	char *retbuf = NULL;
  632: 
  633: 	if (buf != NULL)
  634: 		tlen = sizeof(*combuf) + buf->l;
  635: 	else
  636: 		tlen = sizeof(*combuf);
  637: 
  638: 	retbuf = racoon_calloc(1, tlen);
  639: 	if (retbuf == NULL) {
  640: 		plog(LLV_ERROR, LOCATION, NULL,
  641: 			"failed to allocate admin buffer\n");
  642: 		return -1;
  643: 	}
  644: 
  645: 	combuf = (struct admin_com *) retbuf;
  646: 	combuf->ac_len = (u_int16_t) tlen;
  647: 	combuf->ac_cmd = req->ac_cmd & ~ADMIN_FLAG_VERSION;
  648: 	if (tlen != (u_int32_t) combuf->ac_len &&
  649: 	    l_ac_errno == 0) {
  650: 		combuf->ac_len_high = tlen >> 16;
  651: 		combuf->ac_cmd |= ADMIN_FLAG_LONG_REPLY;
  652: 	} else {
  653: 		combuf->ac_errno = l_ac_errno;
  654: 	}
  655: 	combuf->ac_proto = req->ac_proto;
  656: 
  657: 	if (buf != NULL)
  658: 		memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
  659: 
  660: 	tlen = send(so, retbuf, tlen, 0);
  661: 	racoon_free(retbuf);
  662: 	if (tlen < 0) {
  663: 		plog(LLV_ERROR, LOCATION, NULL,
  664: 			"failed to send admin command: %s\n",
  665: 			strerror(errno));
  666: 		return -1;
  667: 	}
  668: 
  669: 	return 0;
  670: }
  671: 
  672: /* ADMIN_PROTO -> SADB_SATYPE */
  673: int
  674: admin2pfkey_proto(proto)
  675: 	u_int proto;
  676: {
  677: 	switch (proto) {
  678: 	case ADMIN_PROTO_IPSEC:
  679: 		return SADB_SATYPE_UNSPEC;
  680: 	case ADMIN_PROTO_AH:
  681: 		return SADB_SATYPE_AH;
  682: 	case ADMIN_PROTO_ESP:
  683: 		return SADB_SATYPE_ESP;
  684: 	default:
  685: 		plog(LLV_ERROR, LOCATION, NULL,
  686: 			"unsupported proto for admin: %d\n", proto);
  687: 		return -1;
  688: 	}
  689: 	/*NOTREACHED*/
  690: }
  691: 
  692: int
  693: admin_init()
  694: {
  695: 	if (adminsock_path == NULL) {
  696: 		lcconf->sock_admin = -1;
  697: 		return 0;
  698: 	}
  699: 
  700: 	memset(&sunaddr, 0, sizeof(sunaddr));
  701: 	sunaddr.sun_family = AF_UNIX;
  702: 	snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
  703: 		"%s", adminsock_path);
  704: 
  705: 	lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
  706: 	if (lcconf->sock_admin == -1) {
  707: 		plog(LLV_ERROR, LOCATION, NULL,
  708: 			"socket: %s\n", strerror(errno));
  709: 		return -1;
  710: 	}
  711: 	close_on_exec(lcconf->sock_admin);
  712: 
  713: 	unlink(sunaddr.sun_path);
  714: 	if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
  715: 			sizeof(sunaddr)) != 0) {
  716: 		plog(LLV_ERROR, LOCATION, NULL,
  717: 			"bind(sockname:%s): %s\n",
  718: 			sunaddr.sun_path, strerror(errno));
  719: 		(void)close(lcconf->sock_admin);
  720: 		return -1;
  721: 	}
  722: 
  723: 	if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
  724: 		plog(LLV_ERROR, LOCATION, NULL,
  725: 		    "chown(%s, %d, %d): %s\n",
  726: 		    sunaddr.sun_path, adminsock_owner,
  727: 		    adminsock_group, strerror(errno));
  728: 		(void)close(lcconf->sock_admin);
  729: 		return -1;
  730: 	}
  731: 
  732: 	if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
  733: 		plog(LLV_ERROR, LOCATION, NULL,
  734: 		    "chmod(%s, 0%03o): %s\n",
  735: 		    sunaddr.sun_path, adminsock_mode, strerror(errno));
  736: 		(void)close(lcconf->sock_admin);
  737: 		return -1;
  738: 	}
  739: 
  740: 	if (listen(lcconf->sock_admin, 5) != 0) {
  741: 		plog(LLV_ERROR, LOCATION, NULL,
  742: 			"listen(sockname:%s): %s\n",
  743: 			sunaddr.sun_path, strerror(errno));
  744: 		(void)close(lcconf->sock_admin);
  745: 		return -1;
  746: 	}
  747: 
  748: 	monitor_fd(lcconf->sock_admin, admin_handler, NULL, 0);
  749: 	plog(LLV_DEBUG, LOCATION, NULL,
  750: 	     "open %s as racoon management.\n", sunaddr.sun_path);
  751: 
  752: 	return 0;
  753: }
  754: 
  755: int
  756: admin_close()
  757: {
  758: 	unmonitor_fd(lcconf->sock_admin);
  759: 	close(lcconf->sock_admin);
  760: 	return 0;
  761: }
  762: 
  763: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>