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