Home | History | Annotate | Download | only in racoon
      1 /*	$NetBSD: backupsa.c,v 1.8.4.1 2007/08/01 11:52:19 vanhu 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 	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 	p = ctime(&t);
    464 	printf("[%s]\n", p);
    465 
    466 	exit(0);
    467 }
    468 #endif
    469