File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / backupsa.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, 5 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    1: /*	$NetBSD: backupsa.c,v 1.10 2010/04/02 15:15:00 christos Exp $	*/
    2: 
    3: /*	$KAME: backupsa.c,v 1.16 2001/12/31 20:13:40 thorpej 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: 
   40: #include <stdlib.h>
   41: #include <stdio.h>
   42: #include <string.h>
   43: #include <ctype.h>
   44: 
   45: #include <netinet/in.h>
   46: #include PATH_IPSEC_H
   47: 
   48: #if TIME_WITH_SYS_TIME
   49: # include <sys/time.h>
   50: # include <time.h>
   51: #else
   52: # if HAVE_SYS_TIME_H
   53: #  include <sys/time.h>
   54: # else
   55: #  include <time.h>
   56: # endif
   57: #endif
   58: 
   59: #include "var.h"
   60: #include "misc.h"
   61: #include "vmbuf.h"
   62: #include "str2val.h"
   63: #include "plog.h"
   64: #include "debug.h"
   65: 
   66: #include "localconf.h"
   67: #include "sockmisc.h"
   68: #include "safefile.h"
   69: #include "backupsa.h"
   70: #include "libpfkey.h"
   71: 
   72: /*
   73:  * (time string)%(sa parameter)
   74:  * (time string) := ex. Nov 24 18:22:48 1986
   75:  * (sa parameter) :=
   76:  *    src dst satype spi mode reqid wsize \
   77:  *    e_type e_keylen a_type a_keylen flags \
   78:  *    l_alloc l_bytes l_addtime l_usetime seq keymat
   79:  */
   80: static char *format = "%b %d %T %Y";	/* time format */
   81: static char *strmon[12] = {
   82:         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
   83:         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
   84: };
   85: 
   86: static char *str2tmx __P((char *, struct tm *));
   87: static int str2num __P((char *, int));
   88: 
   89: /*
   90:  * output the sa parameter.
   91:  */
   92: int
   93: backupsa_to_file(sa_args)
   94: 	struct pfkey_send_sa_args *sa_args;
   95: {
   96: 	char buf[1024];
   97: 	struct tm *tm;
   98: 	time_t t;
   99: 	char *p, *k;
  100: 	int len, l, i;
  101: 	FILE *fp;
  102: 
  103: 	p = buf;
  104: 	len = sizeof(buf);
  105: 
  106: 	t = time(NULL);
  107: 	tm = localtime(&t);
  108: 	l = strftime(p, len, format, tm);
  109: 	p += l;
  110: 	len -= l;
  111: 	if (len < 0)
  112: 		goto err;
  113: 
  114: 	l = snprintf(p, len, "%%");
  115: 	if (l < 0 || l >= len)
  116: 		goto err;
  117: 	p += l;
  118: 	len -= l;
  119: 	if (len < 0)
  120: 		goto err;
  121: 
  122:         i = getnameinfo(sa_args->src, sysdep_sa_len(sa_args->src), p, len, NULL, 0, NIFLAGS);
  123: 	if (i != 0)
  124: 		goto err;
  125: 	l = strlen(p);
  126: 	p += l;
  127: 	len -= l;
  128: 	if (len < 0)
  129: 		goto err;
  130: 
  131: 	l = snprintf(p, len, " ");
  132: 	if (l < 0 || l >= len)
  133: 		goto err;
  134: 	p += l;
  135: 	len -= l;
  136: 	if (len < 0)
  137: 		goto err;
  138: 
  139:         i = getnameinfo(sa_args->dst, sysdep_sa_len(sa_args->dst), p, len, NULL, 0, NIFLAGS);
  140: 	if (i != 0)
  141: 		goto err;
  142: 	l = strlen(p);
  143: 	p += l;
  144: 	len -= l;
  145: 	if (len < 0)
  146: 		goto err;
  147: 
  148: 	l = snprintf(p, len,
  149: 		" %u %lu %u %u %u "
  150: 		"%u %u %u %u %u "
  151: 		"%u %llu %llu %llu %u",
  152: 		sa_args->satype, (unsigned long)ntohl(sa_args->spi), 
  153: 		sa_args->mode, sa_args->reqid, sa_args->wsize, sa_args->e_type, 
  154: 		sa_args->e_keylen, sa_args->a_type, sa_args->a_keylen, 
  155: 		sa_args->flags, sa_args->l_alloc, 
  156: 		(unsigned long long)sa_args->l_bytes, 
  157: 		(unsigned long long)sa_args->l_addtime, 
  158: 		(unsigned long long)sa_args->l_usetime, sa_args->seq);
  159: 
  160: 	if (l < 0 || l >= len)
  161: 		goto err;
  162: 	p += l;
  163: 	len -= l;
  164: 	if (len < 0)
  165: 		goto err;
  166: 
  167: 	k = val2str(sa_args->keymat, sa_args->e_keylen + sa_args->a_keylen);
  168: 	l = snprintf(p, len, " %s", k);
  169: 	racoon_free(k);
  170: 	if (l < 0 || l >= len)
  171: 		goto err;
  172: 	p += l;
  173: 	len -= l;
  174: 	if (len < 0)
  175: 		goto err;
  176: 
  177: 	/* open the file and write the SA parameter */
  178: 	if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) != 0 ||
  179: 	    (fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "a")) == NULL) {
  180: 		plog(LLV_ERROR, LOCATION, NULL,
  181: 			"failed to open the backup file %s.\n",
  182: 			lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
  183: 		return -1;
  184: 	}
  185: 	fprintf(fp, "%s\n", buf);
  186: 	fclose(fp);
  187: 
  188: 	return 0;
  189: 
  190: err:
  191: 	plog(LLV_ERROR, LOCATION, NULL,
  192: 		"SA cannot be saved to a file.\n");
  193: 	return -1;
  194: }
  195: 
  196: int
  197: backupsa_from_file()
  198: {
  199: 	FILE *fp;
  200: 	char buf[512];
  201: 	struct tm tm;
  202: 	time_t created, current;
  203: 	char *p, *q;
  204: 	size_t keymatlen;
  205: 	int line;
  206: 	struct pfkey_send_sa_args sa_args;
  207: 
  208: 	memset(&sa_args, 0, sizeof(sa_args));
  209: 
  210: 	if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) == 0)
  211: 		fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "r");
  212: 	else
  213: 		fp = NULL;
  214: 	if (fp == NULL) {
  215: 		plog(LLV_ERROR, LOCATION, NULL,
  216: 			"failed to open the backup file %s.\n",
  217: 			lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
  218: 		return -1;
  219: 	}
  220: 
  221: 	current = time(NULL);
  222: 
  223: 	for(line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) {
  224: 		/* comment line */
  225: 		if (buf[0] == '#')
  226: 			continue;
  227: 
  228: 		memset(&tm, 0, sizeof(tm));
  229: 		p = str2tmx(buf, &tm);
  230: 		if (*p != '%') {
  231: 	err:
  232: 			plog(LLV_ERROR, LOCATION, NULL,
  233: 				"illegal format line#%d in %s: %s\n",
  234: 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 
  235: 				buf);
  236: 			goto next;
  237: 		}
  238: 		created = mktime(&tm);
  239: 		p++;
  240: 
  241: 		for (q = p; *q != '\0' && !isspace((int)*q); q++)
  242: 			;
  243: 		*q = '\0';
  244: 		if ((sa_args.src = str2saddr(p, NULL)) == NULL)
  245: 			goto next;
  246: 		p = q + 1;
  247: 
  248: 		for (q = p; *q != '\0' && !isspace((int)*q); q++)
  249: 			;
  250: 		*q = '\0';
  251: 		if ((sa_args.dst = str2saddr(p, NULL)) == NULL)
  252: 			goto next;
  253: 		p = q + 1;
  254: 
  255: #define GETNEXTNUM(value, function) 				\
  256: do { 								\
  257: 	char *y; 						\
  258: 	for (q = p; *q != '\0' && !isspace((int)*q); q++) 	\
  259: 		; 						\
  260: 	*q = '\0'; 						\
  261: 	(value) = function(p, &y, 10); 				\
  262: 	if ((value) == 0 && *y != '\0') 			\
  263: 		goto next; 					\
  264: 	p = q + 1; 						\
  265: } while (/*CONSTCOND*/0);
  266: 
  267: 		GETNEXTNUM(sa_args.satype, strtoul);
  268: 		GETNEXTNUM(sa_args.spi, strtoul);
  269: 		sa_args.spi = ntohl(sa_args.spi);
  270: 		GETNEXTNUM(sa_args.mode, strtoul);
  271: 		GETNEXTNUM(sa_args.reqid, strtoul);
  272: 		GETNEXTNUM(sa_args.wsize, strtoul);
  273: 		GETNEXTNUM(sa_args.e_type, strtoul);
  274: 		GETNEXTNUM(sa_args.e_keylen, strtoul);
  275: 		GETNEXTNUM(sa_args.a_type, strtoul);
  276: 		GETNEXTNUM(sa_args.a_keylen, strtoul);
  277: 		GETNEXTNUM(sa_args.flags, strtoul);
  278: 		GETNEXTNUM(sa_args.l_alloc, strtoul);
  279: 		GETNEXTNUM(sa_args.l_bytes, strtouq);
  280: 		GETNEXTNUM(sa_args.l_addtime, strtouq);
  281: 		GETNEXTNUM(sa_args.l_usetime, strtouq);
  282: 		GETNEXTNUM(sa_args.seq, strtoul);
  283: 
  284: #undef GETNEXTNUM
  285: 
  286: 		sa_args.keymat = str2val(p, 16, &keymatlen);
  287: 		if (sa_args.keymat == NULL) {
  288: 			plog(LLV_ERROR, LOCATION, NULL,
  289: 				"illegal format(keymat) line#%d in %s: %s\n",
  290: 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 
  291: 				buf);
  292: 			goto next;
  293: 		}
  294: 
  295: 		if (created + sa_args.l_addtime < current) {
  296: 			plog(LLV_DEBUG, LOCATION, NULL,
  297: 				"ignore this line#%d in %s due to expiration\n",
  298: 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
  299: 			goto next;
  300: 		}
  301: 		sa_args.l_addtime -= current - created;
  302: 
  303: 		if (pfkey_send_add2(&sa_args) < 0) {
  304: 			plog(LLV_ERROR, LOCATION, NULL,
  305: 				"restore SA failed line#%d in %s: %s\n",
  306: 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 
  307: 				ipsec_strerror());
  308: 		}
  309: 
  310: next:
  311: 	 	if (sa_args.src != NULL) {
  312: 			racoon_free(sa_args.src);
  313: 			sa_args.src = NULL;
  314: 		}
  315: 		if (sa_args.dst != NULL) {
  316: 			racoon_free(sa_args.dst);
  317: 			sa_args.dst = NULL;
  318: 		}
  319: 		if (sa_args.keymat != NULL) {
  320: 			racoon_free(sa_args.keymat);
  321: 			sa_args.keymat = NULL;
  322: 		}
  323: 	}
  324: 
  325: 	fclose(fp);
  326: 
  327: 	/*
  328: 	 * There is a possibility that an abnormal system down will happen
  329: 	 * again before new negotiation will be started.  so racoon clears
  330: 	 * the backup file here.  it's ok that old SAs are remained in the
  331: 	 * file.  any old SA will not be installed because racoon checks the
  332: 	 * lifetime and compare with current time.
  333: 	 */
  334: 
  335: 	return 0;
  336: }
  337: 
  338: int
  339: backupsa_clean()
  340: {
  341: 	FILE *fp;
  342: 
  343: 	/* simply return if the file is not defined. */
  344: 	if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
  345: 		return 0;
  346: 
  347: 	fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+");
  348: 	if (fp == NULL) {
  349: 		plog(LLV_ERROR, LOCATION, NULL,
  350: 			"failed to clean the backup file %s.\n",
  351: 			lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
  352: 		return -1;
  353: 	}
  354: 	fclose(fp);
  355: 	return 0;
  356: }
  357: 
  358: /*
  359:  * convert fixed string into the tm structure.
  360:  * The fixed string is like 'Nov 24 18:22:48 1986'.
  361:  * static char *format = "%b %d %T %Y";
  362:  */
  363: static char *
  364: str2tmx(char *p, struct tm *tm)
  365: {
  366: 	int i, len;
  367: 
  368: 	/* Month */
  369:         for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) {
  370: 		if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) {
  371: 			tm->tm_mon = i;
  372: 			break;
  373: 		}
  374: 	}
  375: 	if (i == sizeof(strmon)/sizeof(strmon[0]))
  376: 		return 0;
  377: 	p += strlen(strmon[i]);
  378: 	if (*p++ != ' ')
  379: 		return 0;
  380: 
  381: 	/* Day */
  382: 	len = 2;
  383: 	tm->tm_mday = str2num(p, len);
  384: 	if (tm->tm_mday == -1 || tm->tm_mday > 31)
  385: 		return 0;
  386: 	p += len;
  387: 	if (*p++ != ' ')
  388: 		return 0;
  389: 
  390: 	/* Hour */
  391: 	len = 2;
  392: 	tm->tm_hour = str2num(p, len);
  393: 	if (tm->tm_hour == -1 || tm->tm_hour > 24)
  394: 		return 0;
  395: 	p += len;
  396: 	if (*p++ != ':')
  397: 		return 0;
  398: 
  399: 	/* Min */
  400: 	len = 2;
  401: 	tm->tm_min = str2num(p, len);
  402: 	if (tm->tm_min == -1 || tm->tm_min > 60)
  403: 		return 0;
  404: 	p += len;
  405: 	if (*p++ != ':')
  406: 		return 0;
  407: 
  408: 	/* Sec */
  409: 	len = 2;
  410: 	tm->tm_sec = str2num(p, len);
  411: 	if (tm->tm_sec == -1 || tm->tm_sec > 60)
  412: 		return 0;
  413: 	p += len;
  414: 	if (*p++ != ' ')
  415: 		return 0;
  416: 
  417: 	/* Year */
  418: 	len = 4;
  419: 	tm->tm_year = str2num(p, len);
  420: 	if (tm->tm_year == -1 || tm->tm_year < 1900)
  421: 		return 0;
  422: 	tm->tm_year -= 1900;
  423: 	p += len;
  424: 
  425: 	return p;
  426: }
  427: 
  428: static int
  429: str2num(p, len)
  430: 	char *p;
  431: 	int len;
  432: {
  433: 	int res, i;
  434: 
  435: 	res = 0;
  436:         for (i = len; i > 0; i--) {
  437: 		if (!isdigit((int)*p))
  438: 			return -1;
  439: 		res *= 10;
  440: 		res += *p - '0';
  441: 		p++;
  442: 	}
  443: 
  444: 	return res;
  445: }
  446: 
  447: #ifdef TEST
  448: #include <stdio.h>
  449: int
  450: main()
  451: {
  452: 	struct tm tm;
  453: 	time_t t;
  454: 	char *buf = "Nov 24 18:22:48 1986 ";
  455: 	const char *p;
  456: 
  457: 	memset(&tm, 0, sizeof(tm));
  458: 	p = str2tmx(buf, &tm);
  459: 	printf("[%x]\n", *p);
  460: 	t = mktime(&tm);
  461: 	if (t == -1)
  462: 		printf("mktime failed.");
  463: 	if ((p = ctime(&t)) == NULL)
  464: 		p = "?";
  465: 	printf("[%s]\n", p);
  466: 
  467: 	exit(0);
  468: }
  469: #endif

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