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