]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/backupsa.c
ipsec-34.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / backupsa.c
1 /* $KAME: backupsa.c,v 1.16 2001/12/31 20:13:40 thorpej Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include "config.h"
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <ctype.h>
42
43 #include <netinet/in.h>
44 #ifndef HAVE_NETINET6_IPSEC
45 #include <netinet/ipsec.h>
46 #else
47 #include <netinet6/ipsec.h>
48 #endif
49
50 #if TIME_WITH_SYS_TIME
51 # include <sys/time.h>
52 # include <time.h>
53 #else
54 # if HAVE_SYS_TIME_H
55 # include <sys/time.h>
56 # else
57 # include <time.h>
58 # endif
59 #endif
60
61 #include "var.h"
62 #include "misc.h"
63 #include "vmbuf.h"
64 #include "str2val.h"
65 #include "plog.h"
66 #include "debug.h"
67
68 #include "localconf.h"
69 #include "sockmisc.h"
70 #include "safefile.h"
71 #include "backupsa.h"
72 #include "libpfkey.h"
73
74 /*
75 * (time string)%(sa parameter)
76 * (time string) := ex. Nov 24 18:22:48 1986
77 * (sa parameter) :=
78 * src dst satype spi mode reqid wsize \
79 * e_type e_keylen a_type a_keylen flags \
80 * l_alloc l_bytes l_addtime l_usetime seq keymat
81 */
82 static char *format = "%b %d %T %Y"; /* time format */
83 static char *strmon[12] = {
84 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
85 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
86 };
87
88 static char *str2tmx __P((char *, struct tm *));
89 static int str2num __P((char *, int));
90
91 /*
92 * output the sa parameter.
93 */
94 int
95 backupsa_to_file(satype, mode, src, dst, spi, reqid, wsize,
96 keymat, e_type, e_keylen, a_type, a_keylen, flags,
97 l_alloc, l_bytes, l_addtime, l_usetime, seq)
98 u_int satype, mode, wsize;
99 struct sockaddr *src, *dst;
100 u_int32_t spi, reqid;
101 caddr_t keymat;
102 u_int e_type, e_keylen, a_type, a_keylen, flags;
103 u_int32_t l_alloc;
104 u_int64_t l_bytes, l_addtime, l_usetime;
105 u_int32_t seq;
106 {
107 char buf[1024];
108 struct tm *tm;
109 time_t t;
110 char *p, *k;
111 int len, l, i;
112 FILE *fp;
113
114 p = buf;
115 len = sizeof(buf);
116
117 t = time(NULL);
118 tm = localtime(&t);
119 l = strftime(p, len, format, tm);
120 p += l;
121 len -= l;
122 if (len < 0)
123 goto err;
124
125 l = snprintf(p, len, "%%");
126 if (l < 0 || l >= len)
127 goto err;
128 p += l;
129 len -= l;
130 if (len < 0)
131 goto err;
132
133 i = getnameinfo(src, sysdep_sa_len(src), p, len, NULL, 0, NIFLAGS);
134 if (i != 0)
135 goto err;
136 l = strlen(p);
137 p += l;
138 len -= l;
139 if (len < 0)
140 goto err;
141
142 l = snprintf(p, len, " ");
143 if (l < 0 || l >= len)
144 goto err;
145 p += l;
146 len -= l;
147 if (len < 0)
148 goto err;
149
150 i = getnameinfo(dst, sysdep_sa_len(dst), p, len, NULL, 0, NIFLAGS);
151 if (i != 0)
152 goto err;
153 l = strlen(p);
154 p += l;
155 len -= l;
156 if (len < 0)
157 goto err;
158
159 l = snprintf(p, len,
160 " %u %lu %u %u %u "
161 "%u %u %u %u %u "
162 "%u %llu %llu %llu %u",
163 satype, (unsigned long)ntohl(spi), mode, reqid, wsize,
164 e_type, e_keylen, a_type, a_keylen, flags,
165 l_alloc, (unsigned long long)l_bytes,
166 (unsigned long long)l_addtime, (unsigned long long)l_usetime,
167 seq);
168 if (l < 0 || l >= len)
169 goto err;
170 p += l;
171 len -= l;
172 if (len < 0)
173 goto err;
174
175 k = val2str(keymat, e_keylen + a_keylen);
176 l = snprintf(p, len, " %s", k);
177 if (l < 0 || l >= len)
178 goto err;
179 racoon_free(k);
180 p += l;
181 len -= l;
182 if (len < 0)
183 goto err;
184
185 /* open the file and write the SA parameter */
186 if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) != 0 ||
187 (fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "a")) == NULL) {
188 plog(LLV_ERROR, LOCATION, NULL,
189 "failed to open the backup file %s.\n",
190 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
191 return -1;
192 }
193 fprintf(fp, "%s\n", buf);
194 fclose(fp);
195
196 return 0;
197
198 err:
199 plog(LLV_ERROR, LOCATION, NULL,
200 "SA cannot be saved to a file.\n");
201 return -1;
202 }
203
204 int
205 backupsa_from_file()
206 {
207 FILE *fp;
208 char buf[512];
209 struct tm tm;
210 time_t created, current;
211 char *p, *q;
212 u_int satype, mode;
213 struct sockaddr *src, *dst;
214 u_int32_t spi, reqid;
215 caddr_t keymat;
216 size_t keymatlen;
217 u_int wsize, e_type, e_keylen, a_type, a_keylen, flags;
218 u_int32_t l_alloc;
219 u_int64_t l_bytes, l_addtime, l_usetime;
220 u_int32_t seq;
221 int line;
222
223 if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) == 0)
224 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "r");
225 else
226 fp = NULL;
227 if (fp == NULL) {
228 plog(LLV_ERROR, LOCATION, NULL,
229 "failed to open the backup file %s.\n",
230 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
231 return -1;
232 }
233
234 current = time(NULL);
235
236 for(line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) {
237 /* comment line */
238 if (buf[0] == '#')
239 continue;
240
241 memset(&tm, 0, sizeof(tm));
242 p = str2tmx(buf, &tm);
243 if (*p != '%') {
244 err:
245 plog(LLV_ERROR, LOCATION, NULL,
246 "illegal format line#%d in %s: %s\n",
247 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf);
248 continue;
249 }
250 created = mktime(&tm);
251 p++;
252
253 for (q = p; *q != '\0' && !isspace((int)*q); q++)
254 ;
255 *q = '\0';
256 src = str2saddr(p, NULL);
257 if (src == NULL)
258 goto err;
259 p = q + 1;
260
261 for (q = p; *q != '\0' && !isspace((int)*q); q++)
262 ;
263 *q = '\0';
264 dst = str2saddr(p, NULL);
265 if (dst == NULL) {
266 racoon_free(src);
267 goto err;
268 }
269 p = q + 1;
270
271 #define GETNEXTNUM(value, function) \
272 do { \
273 char *y; \
274 for (q = p; *q != '\0' && !isspace((int)*q); q++) \
275 ; \
276 *q = '\0'; \
277 (value) = function(p, &y, 10); \
278 if ((value) == 0 && *y != '\0') \
279 goto err; \
280 p = q + 1; \
281 } while (0);
282
283 GETNEXTNUM(satype, strtoul);
284 GETNEXTNUM(spi, strtoul);
285 spi = ntohl(spi);
286 GETNEXTNUM(mode, strtoul);
287 GETNEXTNUM(reqid, strtoul);
288 GETNEXTNUM(wsize, strtoul);
289 GETNEXTNUM(e_type, strtoul);
290 GETNEXTNUM(e_keylen, strtoul);
291 GETNEXTNUM(a_type, strtoul);
292 GETNEXTNUM(a_keylen, strtoul);
293 GETNEXTNUM(flags, strtoul);
294 GETNEXTNUM(l_alloc, strtoul);
295 GETNEXTNUM(l_bytes, strtouq);
296 GETNEXTNUM(l_addtime, strtouq);
297 GETNEXTNUM(l_usetime, strtouq);
298 GETNEXTNUM(seq, strtoul);
299
300 #undef GETNEXTNUM
301
302 keymat = str2val(p, 16, &keymatlen);
303 if (keymat == NULL) {
304 plog(LLV_ERROR, LOCATION, NULL,
305 "illegal format(keymat) line#%d in %s: %s\n",
306 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf);
307 racoon_free(src);
308 racoon_free(dst);
309 continue;
310 }
311
312 if (created + l_addtime < current) {
313 plog(LLV_DEBUG, LOCATION, NULL,
314 "ignore this line#%d in %s due to expiration\n",
315 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
316 racoon_free(src);
317 racoon_free(dst);
318 racoon_free(keymat);
319 continue;
320 }
321 l_addtime -= current - created;
322 #ifdef __APPLE__
323 if (pfkey_send_add(
324 lcconf->sock_pfkey,
325 satype,
326 mode,
327 src,
328 dst,
329 spi,
330 reqid,
331 wsize,
332 keymat,
333 e_type, e_keylen, a_type, a_keylen, flags,
334 0, l_bytes, l_addtime, 0, seq, 0) < 0) {
335 plog(LLV_ERROR, LOCATION, NULL,
336 "restore SA filed line#%d in %s: %s\n",
337 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], ipsec_strerror());
338 }
339 #else
340 if (pfkey_send_add(
341 lcconf->sock_pfkey,
342 satype,
343 mode,
344 src,
345 dst,
346 spi,
347 reqid,
348 wsize,
349 keymat,
350 e_type, e_keylen, a_type, a_keylen, flags,
351 0, l_bytes, l_addtime, 0, seq) < 0) {
352 plog(LLV_ERROR, LOCATION, NULL,
353 "restore SA filed line#%d in %s: %s\n",
354 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], ipsec_strerror());
355 }
356 #endif
357 racoon_free(src);
358 racoon_free(dst);
359 racoon_free(keymat);
360 }
361
362 fclose(fp);
363
364 /*
365 * There is a possibility that an abnormal system down will happen
366 * again before new negotiation will be started. so racoon clears
367 * the backup file here. it's ok that old SAs are remained in the
368 * file. any old SA will not be installed because racoon checks the
369 * lifetime and compare with current time.
370 */
371
372 return 0;
373 }
374
375 int
376 backupsa_clean()
377 {
378 FILE *fp;
379
380 /* simply return if the file is not defined. */
381 if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
382 return 0;
383
384 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+");
385 if (fp == NULL) {
386 plog(LLV_ERROR, LOCATION, NULL,
387 "failed to clean the backup file %s.\n",
388 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
389 return -1;
390 }
391 fclose(fp);
392 return 0;
393 }
394
395 /*
396 * convert fixed string into the tm structure.
397 * The fixed string is like 'Nov 24 18:22:48 1986'.
398 * static char *format = "%b %d %T %Y";
399 */
400 static char *
401 str2tmx(char *p, struct tm *tm)
402 {
403 int i, len;
404
405 /* Month */
406 for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) {
407 if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) {
408 tm->tm_mon = i;
409 break;
410 }
411 }
412 if (i == sizeof(strmon)/sizeof(strmon[0]))
413 return 0;
414 p += strlen(strmon[i]);
415 if (*p++ != ' ')
416 return 0;
417
418 /* Day */
419 len = 2;
420 tm->tm_mday = str2num(p, len);
421 if (tm->tm_mday == -1 || tm->tm_mday > 31)
422 return 0;
423 p += len;
424 if (*p++ != ' ')
425 return 0;
426
427 /* Hour */
428 len = 2;
429 tm->tm_hour = str2num(p, len);
430 if (tm->tm_hour == -1 || tm->tm_hour > 24)
431 return 0;
432 p += len;
433 if (*p++ != ':')
434 return 0;
435
436 /* Min */
437 len = 2;
438 tm->tm_min = str2num(p, len);
439 if (tm->tm_min == -1 || tm->tm_min > 60)
440 return 0;
441 p += len;
442 if (*p++ != ':')
443 return 0;
444
445 /* Sec */
446 len = 2;
447 tm->tm_sec = str2num(p, len);
448 if (tm->tm_sec == -1 || tm->tm_sec > 60)
449 return 0;
450 p += len;
451 if (*p++ != ' ')
452 return 0;
453
454 /* Year */
455 len = 4;
456 tm->tm_year = str2num(p, len);
457 if (tm->tm_year == -1 || tm->tm_year < 1900)
458 return 0;
459 tm->tm_year -= 1900;
460 p += len;
461
462 return p;
463 }
464
465 static int
466 str2num(p, len)
467 char *p;
468 int len;
469 {
470 int res, i;
471
472 res = 0;
473 for (i = len; i > 0; i--) {
474 if (!isdigit((int)*p))
475 return -1;
476 res *= 10;
477 res += *p - '0';
478 p++;
479 }
480
481 return res;
482 }
483
484 #ifdef TEST
485 #include <stdio.h>
486 int
487 main()
488 {
489 struct tm tm;
490 time_t t;
491 char *buf = "Nov 24 18:22:48 1986 ";
492 char *p;
493
494 memset(&tm, 0, sizeof(tm));
495 p = str2tmx(buf, &tm);
496 printf("[%x]\n", *p);
497 t = mktime(&tm);
498 if (t == -1)
499 printf("mktime failed.");
500 p = ctime(&t);
501 printf("[%s]\n", p);
502
503 exit(0);
504 }
505 #endif