]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/backupsa.c
ipsec-146.2.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 if (pfkey_send_add(
323 lcconf->sock_pfkey,
324 satype,
325 mode,
326 src,
327 dst,
328 spi,
329 reqid,
330 wsize,
331 keymat,
332 e_type, e_keylen, a_type, a_keylen, flags,
333 0, l_bytes, l_addtime, 0, seq, 0) < 0) {
334 plog(LLV_ERROR, LOCATION, NULL,
335 "restore SA filed line#%d in %s: %s\n",
336 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], ipsec_strerror());
337 }
338 racoon_free(src);
339 racoon_free(dst);
340 racoon_free(keymat);
341 }
342
343 fclose(fp);
344
345 /*
346 * There is a possibility that an abnormal system down will happen
347 * again before new negotiation will be started. so racoon clears
348 * the backup file here. it's ok that old SAs are remained in the
349 * file. any old SA will not be installed because racoon checks the
350 * lifetime and compare with current time.
351 */
352
353 return 0;
354 }
355
356 int
357 backupsa_clean()
358 {
359 FILE *fp;
360
361 /* simply return if the file is not defined. */
362 if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
363 return 0;
364
365 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+");
366 if (fp == NULL) {
367 plog(LLV_ERROR, LOCATION, NULL,
368 "failed to clean the backup file %s.\n",
369 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
370 return -1;
371 }
372 fclose(fp);
373 return 0;
374 }
375
376 /*
377 * convert fixed string into the tm structure.
378 * The fixed string is like 'Nov 24 18:22:48 1986'.
379 * static char *format = "%b %d %T %Y";
380 */
381 static char *
382 str2tmx(char *p, struct tm *tm)
383 {
384 int i, len;
385
386 /* Month */
387 for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) {
388 if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) {
389 tm->tm_mon = i;
390 break;
391 }
392 }
393 if (i == sizeof(strmon)/sizeof(strmon[0]))
394 return 0;
395 p += strlen(strmon[i]);
396 if (*p++ != ' ')
397 return 0;
398
399 /* Day */
400 len = 2;
401 tm->tm_mday = str2num(p, len);
402 if (tm->tm_mday == -1 || tm->tm_mday > 31)
403 return 0;
404 p += len;
405 if (*p++ != ' ')
406 return 0;
407
408 /* Hour */
409 len = 2;
410 tm->tm_hour = str2num(p, len);
411 if (tm->tm_hour == -1 || tm->tm_hour > 24)
412 return 0;
413 p += len;
414 if (*p++ != ':')
415 return 0;
416
417 /* Min */
418 len = 2;
419 tm->tm_min = str2num(p, len);
420 if (tm->tm_min == -1 || tm->tm_min > 60)
421 return 0;
422 p += len;
423 if (*p++ != ':')
424 return 0;
425
426 /* Sec */
427 len = 2;
428 tm->tm_sec = str2num(p, len);
429 if (tm->tm_sec == -1 || tm->tm_sec > 60)
430 return 0;
431 p += len;
432 if (*p++ != ' ')
433 return 0;
434
435 /* Year */
436 len = 4;
437 tm->tm_year = str2num(p, len);
438 if (tm->tm_year == -1 || tm->tm_year < 1900)
439 return 0;
440 tm->tm_year -= 1900;
441 p += len;
442
443 return p;
444 }
445
446 static int
447 str2num(p, len)
448 char *p;
449 int len;
450 {
451 int res, i;
452
453 res = 0;
454 for (i = len; i > 0; i--) {
455 if (!isdigit((int)*p))
456 return -1;
457 res *= 10;
458 res += *p - '0';
459 p++;
460 }
461
462 return res;
463 }
464
465 #ifdef TEST
466 #include <stdio.h>
467 int
468 main()
469 {
470 struct tm tm;
471 time_t t;
472 char *buf = "Nov 24 18:22:48 1986 ";
473 char *p;
474
475 memset(&tm, 0, sizeof(tm));
476 p = str2tmx(buf, &tm);
477 printf("[%x]\n", *p);
478 t = mktime(&tm);
479 if (t == -1)
480 printf("mktime failed.");
481 p = ctime(&t);
482 printf("[%s]\n", p);
483
484 exit(0);
485 }
486 #endif