]> git.saurik.com Git - apple/network_cmds.git/blob - racoon.tproj/backupsa.c
network_cmds-245.19.tar.gz
[apple/network_cmds.git] / racoon.tproj / 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 <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/socket.h>
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <ctype.h>
40
41 #include <netinet/in.h>
42 #ifdef IPV6_INRIA_VERSION
43 #include <netinet/ipsec.h>
44 #else
45 #include <netinet6/ipsec.h>
46 #endif
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(satype, mode, src, dst, spi, reqid, wsize,
94 keymat, e_type, e_keylen, a_type, a_keylen, flags,
95 l_alloc, l_bytes, l_addtime, l_usetime, seq)
96 u_int satype, mode, wsize;
97 struct sockaddr *src, *dst;
98 u_int32_t spi, reqid;
99 caddr_t keymat;
100 u_int e_type, e_keylen, a_type, a_keylen, flags;
101 u_int32_t l_alloc;
102 u_int64_t l_bytes, l_addtime, l_usetime;
103 u_int32_t seq;
104 {
105 char buf[1024];
106 struct tm *tm;
107 time_t t;
108 char *p, *k;
109 int len, l, i;
110 FILE *fp;
111
112 p = buf;
113 len = sizeof(buf);
114
115 t = time(NULL);
116 tm = localtime(&t);
117 l = strftime(p, len, format, tm);
118 p += l;
119 len -= l;
120 if (len < 0)
121 goto err;
122
123 l = snprintf(p, len, "%%");
124 if (l < 0 || l >= len)
125 goto err;
126 p += l;
127 len -= l;
128 if (len < 0)
129 goto err;
130
131 i = getnameinfo(src, src->sa_len, p, len, NULL, 0, NIFLAGS);
132 if (i != 0)
133 goto err;
134 l = strlen(p);
135 p += l;
136 len -= l;
137 if (len < 0)
138 goto err;
139
140 l = snprintf(p, len, " ");
141 if (l < 0 || l >= len)
142 goto err;
143 p += l;
144 len -= l;
145 if (len < 0)
146 goto err;
147
148 i = getnameinfo(dst, dst->sa_len, p, len, NULL, 0, NIFLAGS);
149 if (i != 0)
150 goto err;
151 l = strlen(p);
152 p += l;
153 len -= l;
154 if (len < 0)
155 goto err;
156
157 l = snprintf(p, len,
158 " %u %lu %u %u %u "
159 "%u %u %u %u %u "
160 "%u %llu %llu %llu %u",
161 satype, (unsigned long)ntohl(spi), mode, reqid, wsize,
162 e_type, e_keylen, a_type, a_keylen, flags,
163 l_alloc, (unsigned long long)l_bytes,
164 (unsigned long long)l_addtime, (unsigned long long)l_usetime,
165 seq);
166 if (l < 0 || l >= len)
167 goto err;
168 p += l;
169 len -= l;
170 if (len < 0)
171 goto err;
172
173 k = val2str(keymat, e_keylen + a_keylen);
174 l = snprintf(p, len, " %s", k);
175 if (l < 0 || l >= len)
176 goto err;
177 racoon_free(k);
178 p += l;
179 len -= l;
180 if (len < 0)
181 goto err;
182
183 /* open the file and write the SA parameter */
184 if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) != 0 ||
185 (fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "a")) == NULL) {
186 plog(LLV_ERROR, LOCATION, NULL,
187 "failed to open the backup file %s.\n",
188 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
189 return -1;
190 }
191 fprintf(fp, "%s\n", buf);
192 fclose(fp);
193
194 return 0;
195
196 err:
197 plog(LLV_ERROR, LOCATION, NULL,
198 "SA cannot be saved to a file.\n");
199 return -1;
200 }
201
202 int
203 backupsa_from_file()
204 {
205 FILE *fp;
206 char buf[512];
207 struct tm tm;
208 time_t created, current;
209 char *p, *q;
210 u_int satype, mode;
211 struct sockaddr *src, *dst;
212 u_int32_t spi, reqid;
213 caddr_t keymat;
214 size_t keymatlen;
215 u_int wsize, e_type, e_keylen, a_type, a_keylen, flags;
216 u_int32_t l_alloc;
217 u_int64_t l_bytes, l_addtime, l_usetime;
218 u_int32_t seq;
219 int line;
220
221 if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) == 0)
222 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "r");
223 else
224 fp = NULL;
225 if (fp == NULL) {
226 plog(LLV_ERROR, LOCATION, NULL,
227 "failed to open the backup file %s.\n",
228 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
229 return -1;
230 }
231
232 current = time(NULL);
233
234 for(line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) {
235 /* comment line */
236 if (buf[0] == '#')
237 continue;
238
239 memset(&tm, 0, sizeof(tm));
240 p = str2tmx(buf, &tm);
241 if (*p != '%') {
242 err:
243 plog(LLV_ERROR, LOCATION, NULL,
244 "illegal format line#%d in %s: %s\n",
245 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf);
246 continue;
247 }
248 created = mktime(&tm);
249 p++;
250
251 for (q = p; *q != '\0' && !isspace(*q); q++)
252 ;
253 *q = '\0';
254 src = str2saddr(p, NULL);
255 if (src == NULL)
256 goto err;
257 p = q + 1;
258
259 for (q = p; *q != '\0' && !isspace(*q); q++)
260 ;
261 *q = '\0';
262 dst = str2saddr(p, NULL);
263 if (dst == NULL) {
264 racoon_free(src);
265 goto err;
266 }
267 p = q + 1;
268
269 #define GETNEXTNUM(value, function) \
270 do { \
271 char *y; \
272 for (q = p; *q != '\0' && !isspace(*q); q++) \
273 ; \
274 *q = '\0'; \
275 (value) = function(p, &y, 10); \
276 if ((value) == 0 && *y != '\0') \
277 goto err; \
278 p = q + 1; \
279 } while (0);
280
281 GETNEXTNUM(satype, strtoul);
282 GETNEXTNUM(spi, strtoul);
283 spi = ntohl(spi);
284 GETNEXTNUM(mode, strtoul);
285 GETNEXTNUM(reqid, strtoul);
286 GETNEXTNUM(wsize, strtoul);
287 GETNEXTNUM(e_type, strtoul);
288 GETNEXTNUM(e_keylen, strtoul);
289 GETNEXTNUM(a_type, strtoul);
290 GETNEXTNUM(a_keylen, strtoul);
291 GETNEXTNUM(flags, strtoul);
292 GETNEXTNUM(l_alloc, strtoul);
293 GETNEXTNUM(l_bytes, strtouq);
294 GETNEXTNUM(l_addtime, strtouq);
295 GETNEXTNUM(l_usetime, strtouq);
296 GETNEXTNUM(seq, strtoul);
297
298 #undef GETNEXTNUM
299
300 keymat = str2val(p, 16, &keymatlen);
301 if (keymat == NULL) {
302 plog(LLV_ERROR, LOCATION, NULL,
303 "illegal format(keymat) line#%d in %s: %s\n",
304 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf);
305 racoon_free(src);
306 racoon_free(dst);
307 continue;
308 }
309
310 if (created + l_addtime < current) {
311 plog(LLV_DEBUG, LOCATION, NULL,
312 "ignore this line#%d in %s due to expiration\n",
313 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
314 racoon_free(src);
315 racoon_free(dst);
316 racoon_free(keymat);
317 continue;
318 }
319 l_addtime -= current - created;
320
321 if (pfkey_send_add(
322 lcconf->sock_pfkey,
323 satype,
324 mode,
325 src,
326 dst,
327 spi,
328 reqid,
329 wsize,
330 keymat,
331 e_type, e_keylen, a_type, a_keylen, flags,
332 0, l_bytes, l_addtime, 0, seq, 0) < 0) {
333 plog(LLV_ERROR, LOCATION, NULL,
334 "restore SA filed line#%d in %s: %s\n",
335 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], ipsec_strerror());
336 }
337 racoon_free(src);
338 racoon_free(dst);
339 racoon_free(keymat);
340 }
341
342 fclose(fp);
343
344 /*
345 * There is a possibility that an abnormal system down will happen
346 * again before new negotiation will be started. so racoon clears
347 * the backup file here. it's ok that old SAs are remained in the
348 * file. any old SA will not be installed because racoon checks the
349 * lifetime and compare with current time.
350 */
351
352 return 0;
353 }
354
355 int
356 backupsa_clean()
357 {
358 FILE *fp;
359
360 /* simply return if the file is not defined. */
361 if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
362 return 0;
363
364 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+");
365 if (fp == NULL) {
366 plog(LLV_ERROR, LOCATION, NULL,
367 "failed to clean the backup file %s.\n",
368 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
369 return -1;
370 }
371 fclose(fp);
372 return 0;
373 }
374
375 /*
376 * convert fixed string into the tm structure.
377 * The fixed string is like 'Nov 24 18:22:48 1986'.
378 * static char *format = "%b %d %T %Y";
379 */
380 static char *
381 str2tmx(char *p, struct tm *tm)
382 {
383 int i, len;
384
385 /* Month */
386 for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) {
387 if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) {
388 tm->tm_mon = i;
389 break;
390 }
391 }
392 if (i == sizeof(strmon)/sizeof(strmon[0]))
393 return 0;
394 p += strlen(strmon[i]);
395 if (*p++ != ' ')
396 return 0;
397
398 /* Day */
399 len = 2;
400 tm->tm_mday = str2num(p, len);
401 if (tm->tm_mday == -1 || tm->tm_mday > 31)
402 return 0;
403 p += len;
404 if (*p++ != ' ')
405 return 0;
406
407 /* Hour */
408 len = 2;
409 tm->tm_hour = str2num(p, len);
410 if (tm->tm_hour == -1 || tm->tm_hour > 24)
411 return 0;
412 p += len;
413 if (*p++ != ':')
414 return 0;
415
416 /* Min */
417 len = 2;
418 tm->tm_min = str2num(p, len);
419 if (tm->tm_min == -1 || tm->tm_min > 60)
420 return 0;
421 p += len;
422 if (*p++ != ':')
423 return 0;
424
425 /* Sec */
426 len = 2;
427 tm->tm_sec = str2num(p, len);
428 if (tm->tm_sec == -1 || tm->tm_sec > 60)
429 return 0;
430 p += len;
431 if (*p++ != ' ')
432 return 0;
433
434 /* Year */
435 len = 4;
436 tm->tm_year = str2num(p, len);
437 if (tm->tm_year == -1 || tm->tm_year < 1900)
438 return 0;
439 tm->tm_year -= 1900;
440 p += len;
441
442 return p;
443 }
444
445 static int
446 str2num(p, len)
447 char *p;
448 int len;
449 {
450 int res, i;
451
452 res = 0;
453 for (i = len; i > 0; i--) {
454 if (!isdigit(*p))
455 return -1;
456 res *= 10;
457 res += *p - '0';
458 p++;
459 }
460
461 return res;
462 }
463
464 #ifdef TEST
465 #include <stdio.h>
466 int
467 main()
468 {
469 struct tm tm;
470 time_t t;
471 char *buf = "Nov 24 18:22:48 1986 ";
472 char *p;
473
474 memset(&tm, 0, sizeof(tm));
475 p = str2tmx(buf, &tm);
476 printf("[%x]\n", *p);
477 t = mktime(&tm);
478 if (t == -1)
479 printf("mktime failed.");
480 p = ctime(&t);
481 printf("[%s]\n", p);
482
483 exit(0);
484 }
485 #endif