1: /* $NetBSD: backupsa.c,v 1.10 2010/04/02 15:15:00 christos 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: const 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: if ((p = ctime(&t)) == NULL)
464: p = "?";
465: printf("[%s]\n", p);
466:
467: exit(0);
468: }
469: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>