File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / admin.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:45:57 2016 UTC (7 years, 7 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, HEAD
ipsec-tools 0.8.2

    1: /*	$NetBSD: admin.c,v 1.38.4.1 2013/06/03 05:49:59 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:                         if (sp_out->local && sp_out->remote) {
  567:                             /* hints available, let's use them */
  568:                             iph2->sa_dst = dupsaddr(dst);
  569:                             iph2->sa_src = dupsaddr(src);
  570:                             iph2->src = dupsaddr((struct sockaddr *)sp_out->local);
  571:                             iph2->dst = dupsaddr((struct sockaddr *)sp_out->remote);
  572:                         } else if (sp_out->req && sp_out->req->saidx.mode == IPSEC_MODE_TUNNEL) {
  573:                             /* Tunnel mode and no hint, use endpoints */
  574:                             iph2->src = dupsaddr((struct sockaddr *)&sp_out->req->saidx.src);
  575:                             iph2->dst = dupsaddr((struct sockaddr *)&sp_out->req->saidx.dst);
  576:                         } else {
  577:                             /* default, use selectors as fallback */
  578:                             iph2->sa_dst = dupsaddr(dst);
  579:                             iph2->sa_src = dupsaddr(src);
  580:                             iph2->dst = dupsaddr(dst);
  581:                             iph2->src = dupsaddr(src);
  582:                         }
  583: 
  584:                         if (iph2->dst == NULL || iph2->src == NULL) {
  585:                             delph2(iph2);
  586:                             break;
  587:                         }
  588:                         set_port(iph2->dst, 0);
  589:                         set_port(iph2->src, 0);
  590: 
  591: 			if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
  592: 				delph2(iph2);
  593: 				break;
  594: 			}
  595: 
  596: 			insph2(iph2);
  597: 			if (isakmp_post_acquire(iph2, NULL, FALSE) < 0) {
  598: 				remph2(iph2);
  599: 				delph2(iph2);
  600: 				break;
  601: 			}
  602: 
  603: 			event_list = &iph2->evt_listeners;
  604: 			l_ac_errno = 0;
  605: 			break;
  606: 		}
  607: 		default:
  608: 			/* ignore */
  609: 			l_ac_errno = ENOTSUP;
  610: 		}
  611: 		break;
  612: 	}
  613: 
  614: 	default:
  615: 		plog(LLV_ERROR, LOCATION, NULL,
  616: 			"invalid command: %d\n", com->ac_cmd);
  617: 		l_ac_errno = ENOTSUP;
  618: 	}
  619: 
  620: 	if ((error = admin_reply(so2, com, l_ac_errno, buf)) != 0)
  621: 		goto out;
  622: 
  623: 	/* start pushing events if so requested */
  624: 	if ((l_ac_errno == 0) &&
  625: 	    (com->ac_version >= 1) &&
  626: 	    (com->ac_cmd == ADMIN_SHOW_EVT || event_list != NULL))
  627: 		error = evt_subscribe(event_list, so2);
  628: out:
  629: 	if (buf != NULL)
  630: 		vfree(buf);
  631: 
  632: 	return error;
  633: }
  634: 
  635: static int
  636: admin_reply(so, req, l_ac_errno, buf)
  637: 	int so, l_ac_errno;
  638: 	struct admin_com *req;
  639: 	vchar_t *buf;
  640: {
  641: 	int tlen;
  642: 	struct admin_com *combuf;
  643: 	char *retbuf = NULL;
  644: 
  645: 	if (buf != NULL)
  646: 		tlen = sizeof(*combuf) + buf->l;
  647: 	else
  648: 		tlen = sizeof(*combuf);
  649: 
  650: 	retbuf = racoon_calloc(1, tlen);
  651: 	if (retbuf == NULL) {
  652: 		plog(LLV_ERROR, LOCATION, NULL,
  653: 			"failed to allocate admin buffer\n");
  654: 		return -1;
  655: 	}
  656: 
  657: 	combuf = (struct admin_com *) retbuf;
  658: 	combuf->ac_len = (u_int16_t) tlen;
  659: 	combuf->ac_cmd = req->ac_cmd & ~ADMIN_FLAG_VERSION;
  660: 	if (tlen != (u_int32_t) combuf->ac_len &&
  661: 	    l_ac_errno == 0) {
  662: 		combuf->ac_len_high = tlen >> 16;
  663: 		combuf->ac_cmd |= ADMIN_FLAG_LONG_REPLY;
  664: 	} else {
  665: 		combuf->ac_errno = l_ac_errno;
  666: 	}
  667: 	combuf->ac_proto = req->ac_proto;
  668: 
  669: 	if (buf != NULL)
  670: 		memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
  671: 
  672: 	tlen = send(so, retbuf, tlen, 0);
  673: 	racoon_free(retbuf);
  674: 	if (tlen < 0) {
  675: 		plog(LLV_ERROR, LOCATION, NULL,
  676: 			"failed to send admin command: %s\n",
  677: 			strerror(errno));
  678: 		return -1;
  679: 	}
  680: 
  681: 	return 0;
  682: }
  683: 
  684: /* ADMIN_PROTO -> SADB_SATYPE */
  685: int
  686: admin2pfkey_proto(proto)
  687: 	u_int proto;
  688: {
  689: 	switch (proto) {
  690: 	case ADMIN_PROTO_IPSEC:
  691: 		return SADB_SATYPE_UNSPEC;
  692: 	case ADMIN_PROTO_AH:
  693: 		return SADB_SATYPE_AH;
  694: 	case ADMIN_PROTO_ESP:
  695: 		return SADB_SATYPE_ESP;
  696: 	default:
  697: 		plog(LLV_ERROR, LOCATION, NULL,
  698: 			"unsupported proto for admin: %d\n", proto);
  699: 		return -1;
  700: 	}
  701: 	/*NOTREACHED*/
  702: }
  703: 
  704: int
  705: admin_init()
  706: {
  707: 	if (adminsock_path == NULL) {
  708: 		lcconf->sock_admin = -1;
  709: 		return 0;
  710: 	}
  711: 
  712: 	memset(&sunaddr, 0, sizeof(sunaddr));
  713: 	sunaddr.sun_family = AF_UNIX;
  714: 	snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
  715: 		"%s", adminsock_path);
  716: 
  717: 	lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
  718: 	if (lcconf->sock_admin == -1) {
  719: 		plog(LLV_ERROR, LOCATION, NULL,
  720: 			"socket: %s\n", strerror(errno));
  721: 		return -1;
  722: 	}
  723: 	close_on_exec(lcconf->sock_admin);
  724: 
  725: 	unlink(sunaddr.sun_path);
  726: 	if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
  727: 			sizeof(sunaddr)) != 0) {
  728: 		plog(LLV_ERROR, LOCATION, NULL,
  729: 			"bind(sockname:%s): %s\n",
  730: 			sunaddr.sun_path, strerror(errno));
  731: 		(void)close(lcconf->sock_admin);
  732: 		return -1;
  733: 	}
  734: 
  735: 	if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
  736: 		plog(LLV_ERROR, LOCATION, NULL,
  737: 		    "chown(%s, %d, %d): %s\n",
  738: 		    sunaddr.sun_path, adminsock_owner,
  739: 		    adminsock_group, strerror(errno));
  740: 		(void)close(lcconf->sock_admin);
  741: 		return -1;
  742: 	}
  743: 
  744: 	if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
  745: 		plog(LLV_ERROR, LOCATION, NULL,
  746: 		    "chmod(%s, 0%03o): %s\n",
  747: 		    sunaddr.sun_path, adminsock_mode, strerror(errno));
  748: 		(void)close(lcconf->sock_admin);
  749: 		return -1;
  750: 	}
  751: 
  752: 	if (listen(lcconf->sock_admin, 5) != 0) {
  753: 		plog(LLV_ERROR, LOCATION, NULL,
  754: 			"listen(sockname:%s): %s\n",
  755: 			sunaddr.sun_path, strerror(errno));
  756: 		(void)close(lcconf->sock_admin);
  757: 		return -1;
  758: 	}
  759: 
  760: 	monitor_fd(lcconf->sock_admin, admin_handler, NULL, 0);
  761: 	plog(LLV_DEBUG, LOCATION, NULL,
  762: 	     "open %s as racoon management.\n", sunaddr.sun_path);
  763: 
  764: 	return 0;
  765: }
  766: 
  767: int
  768: admin_close()
  769: {
  770: 	unmonitor_fd(lcconf->sock_admin);
  771: 	close(lcconf->sock_admin);
  772: 	return 0;
  773: }
  774: 
  775: #endif

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