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