xref: /netbsd-src/crypto/dist/ipsec-tools/src/racoon/backupsa.c (revision 27527e67bbdf8d9ec84fd58803048ed6d181ece2)
1 /*	$NetBSD: backupsa.c,v 1.3 2005/11/21 14:20:28 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 	if (l < 0 || l >= len)
180 		goto err;
181 	racoon_free(k);
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, *dst;
216         u_int32_t spi, reqid;
217         caddr_t keymat;
218 	size_t keymatlen;
219         u_int wsize, e_type, e_keylen, a_type, a_keylen, flags;
220         u_int32_t l_alloc;
221         u_int64_t l_bytes, l_addtime, l_usetime;
222         u_int32_t seq;
223 	int line;
224 
225 	if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) == 0)
226 		fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "r");
227 	else
228 		fp = NULL;
229 	if (fp == NULL) {
230 		plog(LLV_ERROR, LOCATION, NULL,
231 			"failed to open the backup file %s.\n",
232 			lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
233 		return -1;
234 	}
235 
236 	current = time(NULL);
237 
238 	for(line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) {
239 		/* comment line */
240 		if (buf[0] == '#')
241 			continue;
242 
243 		memset(&tm, 0, sizeof(tm));
244 		p = str2tmx(buf, &tm);
245 		if (*p != '%') {
246 	err:
247 			plog(LLV_ERROR, LOCATION, NULL,
248 				"illegal format line#%d in %s: %s\n",
249 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf);
250 			continue;
251 		}
252 		created = mktime(&tm);
253 		p++;
254 
255 		for (q = p; *q != '\0' && !isspace((int)*q); q++)
256 			;
257 		*q = '\0';
258 		src = str2saddr(p, NULL);
259 		if (src == NULL)
260 			goto err;
261 		p = q + 1;
262 
263 		for (q = p; *q != '\0' && !isspace((int)*q); q++)
264 			;
265 		*q = '\0';
266 		dst = str2saddr(p, NULL);
267 		if (dst == NULL) {
268 			racoon_free(src);
269 			goto err;
270 		}
271 		p = q + 1;
272 
273 #define GETNEXTNUM(value, function) \
274 do { \
275 	char *y; \
276 	for (q = p; *q != '\0' && !isspace((int)*q); q++) \
277 		; \
278 	*q = '\0'; \
279 	(value) = function(p, &y, 10); \
280 	if ((value) == 0 && *y != '\0') \
281 		goto err; \
282 	p = q + 1; \
283 } while (0);
284 
285 		GETNEXTNUM(satype, strtoul);
286 		GETNEXTNUM(spi, strtoul);
287 		spi = ntohl(spi);
288 		GETNEXTNUM(mode, strtoul);
289 		GETNEXTNUM(reqid, strtoul);
290 		GETNEXTNUM(wsize, strtoul);
291 		GETNEXTNUM(e_type, strtoul);
292 		GETNEXTNUM(e_keylen, strtoul);
293 		GETNEXTNUM(a_type, strtoul);
294 		GETNEXTNUM(a_keylen, strtoul);
295 		GETNEXTNUM(flags, strtoul);
296 		GETNEXTNUM(l_alloc, strtoul);
297 		GETNEXTNUM(l_bytes, strtouq);
298 		GETNEXTNUM(l_addtime, strtouq);
299 		GETNEXTNUM(l_usetime, strtouq);
300 		GETNEXTNUM(seq, strtoul);
301 
302 #undef GETNEXTNUM
303 
304 		keymat = str2val(p, 16, &keymatlen);
305 		if (keymat == NULL) {
306 			plog(LLV_ERROR, LOCATION, NULL,
307 				"illegal format(keymat) line#%d in %s: %s\n",
308 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf);
309 			racoon_free(src);
310 			racoon_free(dst);
311 			continue;
312 		}
313 
314 		if (created + l_addtime < current) {
315 			plog(LLV_DEBUG, LOCATION, NULL,
316 				"ignore this line#%d in %s due to expiration\n",
317 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
318 			racoon_free(src);
319 			racoon_free(dst);
320 			racoon_free(keymat);
321 			continue;
322 		}
323 		l_addtime -= current - created;
324 
325 		if (pfkey_send_add(
326 				lcconf->sock_pfkey,
327 				satype,
328 				mode,
329 				src,
330 				dst,
331 				spi,
332 				reqid,
333 				wsize,
334 				keymat,
335 				e_type, e_keylen, a_type, a_keylen, flags,
336 				0, l_bytes, l_addtime, 0, seq) < 0) {
337 			plog(LLV_ERROR, LOCATION, NULL,
338 				"restore SA filed line#%d in %s: %s\n",
339 				line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], ipsec_strerror());
340 		}
341 		racoon_free(src);
342 		racoon_free(dst);
343 		racoon_free(keymat);
344 	}
345 
346 	fclose(fp);
347 
348 	/*
349 	 * There is a possibility that an abnormal system down will happen
350 	 * again before new negotiation will be started.  so racoon clears
351 	 * the backup file here.  it's ok that old SAs are remained in the
352 	 * file.  any old SA will not be installed because racoon checks the
353 	 * lifetime and compare with current time.
354 	 */
355 
356 	return 0;
357 }
358 
359 int
360 backupsa_clean()
361 {
362 	FILE *fp;
363 
364 	/* simply return if the file is not defined. */
365 	if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
366 		return 0;
367 
368 	fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+");
369 	if (fp == NULL) {
370 		plog(LLV_ERROR, LOCATION, NULL,
371 			"failed to clean the backup file %s.\n",
372 			lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
373 		return -1;
374 	}
375 	fclose(fp);
376 	return 0;
377 }
378 
379 /*
380  * convert fixed string into the tm structure.
381  * The fixed string is like 'Nov 24 18:22:48 1986'.
382  * static char *format = "%b %d %T %Y";
383  */
384 static char *
385 str2tmx(char *p, struct tm *tm)
386 {
387 	int i, len;
388 
389 	/* Month */
390         for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) {
391 		if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) {
392 			tm->tm_mon = i;
393 			break;
394 		}
395 	}
396 	if (i == sizeof(strmon)/sizeof(strmon[0]))
397 		return 0;
398 	p += strlen(strmon[i]);
399 	if (*p++ != ' ')
400 		return 0;
401 
402 	/* Day */
403 	len = 2;
404 	tm->tm_mday = str2num(p, len);
405 	if (tm->tm_mday == -1 || tm->tm_mday > 31)
406 		return 0;
407 	p += len;
408 	if (*p++ != ' ')
409 		return 0;
410 
411 	/* Hour */
412 	len = 2;
413 	tm->tm_hour = str2num(p, len);
414 	if (tm->tm_hour == -1 || tm->tm_hour > 24)
415 		return 0;
416 	p += len;
417 	if (*p++ != ':')
418 		return 0;
419 
420 	/* Min */
421 	len = 2;
422 	tm->tm_min = str2num(p, len);
423 	if (tm->tm_min == -1 || tm->tm_min > 60)
424 		return 0;
425 	p += len;
426 	if (*p++ != ':')
427 		return 0;
428 
429 	/* Sec */
430 	len = 2;
431 	tm->tm_sec = str2num(p, len);
432 	if (tm->tm_sec == -1 || tm->tm_sec > 60)
433 		return 0;
434 	p += len;
435 	if (*p++ != ' ')
436 		return 0;
437 
438 	/* Year */
439 	len = 4;
440 	tm->tm_year = str2num(p, len);
441 	if (tm->tm_year == -1 || tm->tm_year < 1900)
442 		return 0;
443 	tm->tm_year -= 1900;
444 	p += len;
445 
446 	return p;
447 }
448 
449 static int
450 str2num(p, len)
451 	char *p;
452 	int len;
453 {
454 	int res, i;
455 
456 	res = 0;
457         for (i = len; i > 0; i--) {
458 		if (!isdigit((int)*p))
459 			return -1;
460 		res *= 10;
461 		res += *p - '0';
462 		p++;
463 	}
464 
465 	return res;
466 }
467 
468 #ifdef TEST
469 #include <stdio.h>
470 int
471 main()
472 {
473 	struct tm tm;
474 	time_t t;
475 	char *buf = "Nov 24 18:22:48 1986 ";
476 	char *p;
477 
478 	memset(&tm, 0, sizeof(tm));
479 	p = str2tmx(buf, &tm);
480 	printf("[%x]\n", *p);
481 	t = mktime(&tm);
482 	if (t == -1)
483 		printf("mktime failed.");
484 	p = ctime(&t);
485 	printf("[%s]\n", p);
486 
487 	exit(0);
488 }
489 #endif
490