• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
backupsa_to_file(sa_args)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
backupsa_from_file()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
backupsa_clean()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 *
str2tmx(char * p,struct tm * tm)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
str2num(p,len)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
main()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