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