1 /* $NetBSD: backupsa.c,v 1.5 2006/09/26 21:25:52 manu 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 #ifndef HAVE_NETINET6_IPSEC 47 #include <netinet/ipsec.h> 48 #else 49 #include <netinet6/ipsec.h> 50 #endif 51 52 #if TIME_WITH_SYS_TIME 53 # include <sys/time.h> 54 # include <time.h> 55 #else 56 # if HAVE_SYS_TIME_H 57 # include <sys/time.h> 58 # else 59 # include <time.h> 60 # endif 61 #endif 62 63 #include "var.h" 64 #include "misc.h" 65 #include "vmbuf.h" 66 #include "str2val.h" 67 #include "plog.h" 68 #include "debug.h" 69 70 #include "localconf.h" 71 #include "sockmisc.h" 72 #include "safefile.h" 73 #include "backupsa.h" 74 #include "libpfkey.h" 75 76 /* 77 * (time string)%(sa parameter) 78 * (time string) := ex. Nov 24 18:22:48 1986 79 * (sa parameter) := 80 * src dst satype spi mode reqid wsize \ 81 * e_type e_keylen a_type a_keylen flags \ 82 * l_alloc l_bytes l_addtime l_usetime seq keymat 83 */ 84 static char *format = "%b %d %T %Y"; /* time format */ 85 static char *strmon[12] = { 86 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 87 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 88 }; 89 90 static char *str2tmx __P((char *, struct tm *)); 91 static int str2num __P((char *, int)); 92 93 /* 94 * output the sa parameter. 95 */ 96 int 97 backupsa_to_file(satype, mode, src, dst, spi, reqid, wsize, 98 keymat, e_type, e_keylen, a_type, a_keylen, flags, 99 l_alloc, l_bytes, l_addtime, l_usetime, seq) 100 u_int satype, mode, wsize; 101 struct sockaddr *src, *dst; 102 u_int32_t spi, reqid; 103 caddr_t keymat; 104 u_int e_type, e_keylen, a_type, a_keylen, flags; 105 u_int32_t l_alloc; 106 u_int64_t l_bytes, l_addtime, l_usetime; 107 u_int32_t seq; 108 { 109 char buf[1024]; 110 struct tm *tm; 111 time_t t; 112 char *p, *k; 113 int len, l, i; 114 FILE *fp; 115 116 p = buf; 117 len = sizeof(buf); 118 119 t = time(NULL); 120 tm = localtime(&t); 121 l = strftime(p, len, format, tm); 122 p += l; 123 len -= l; 124 if (len < 0) 125 goto err; 126 127 l = snprintf(p, len, "%%"); 128 if (l < 0 || l >= len) 129 goto err; 130 p += l; 131 len -= l; 132 if (len < 0) 133 goto err; 134 135 i = getnameinfo(src, sysdep_sa_len(src), p, len, NULL, 0, NIFLAGS); 136 if (i != 0) 137 goto err; 138 l = strlen(p); 139 p += l; 140 len -= l; 141 if (len < 0) 142 goto err; 143 144 l = snprintf(p, len, " "); 145 if (l < 0 || l >= len) 146 goto err; 147 p += l; 148 len -= l; 149 if (len < 0) 150 goto err; 151 152 i = getnameinfo(dst, sysdep_sa_len(dst), p, len, NULL, 0, NIFLAGS); 153 if (i != 0) 154 goto err; 155 l = strlen(p); 156 p += l; 157 len -= l; 158 if (len < 0) 159 goto err; 160 161 l = snprintf(p, len, 162 " %u %lu %u %u %u " 163 "%u %u %u %u %u " 164 "%u %llu %llu %llu %u", 165 satype, (unsigned long)ntohl(spi), mode, reqid, wsize, 166 e_type, e_keylen, a_type, a_keylen, flags, 167 l_alloc, (unsigned long long)l_bytes, 168 (unsigned long long)l_addtime, (unsigned long long)l_usetime, 169 seq); 170 if (l < 0 || l >= len) 171 goto err; 172 p += l; 173 len -= l; 174 if (len < 0) 175 goto err; 176 177 k = val2str(keymat, e_keylen + a_keylen); 178 l = snprintf(p, len, " %s", k); 179 racoon_free(k); 180 if (l < 0 || l >= len) 181 goto err; 182 p += l; 183 len -= l; 184 if (len < 0) 185 goto err; 186 187 /* open the file and write the SA parameter */ 188 if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) != 0 || 189 (fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "a")) == NULL) { 190 plog(LLV_ERROR, LOCATION, NULL, 191 "failed to open the backup file %s.\n", 192 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); 193 return -1; 194 } 195 fprintf(fp, "%s\n", buf); 196 fclose(fp); 197 198 return 0; 199 200 err: 201 plog(LLV_ERROR, LOCATION, NULL, 202 "SA cannot be saved to a file.\n"); 203 return -1; 204 } 205 206 int 207 backupsa_from_file() 208 { 209 FILE *fp; 210 char buf[512]; 211 struct tm tm; 212 time_t created, current; 213 char *p, *q; 214 u_int satype, mode; 215 struct sockaddr *src = NULL; 216 struct sockaddr *dst = NULL; 217 caddr_t keymat = NULL; 218 u_int32_t spi, reqid; 219 size_t keymatlen; 220 u_int wsize, e_type, e_keylen, a_type, a_keylen, flags; 221 u_int32_t l_alloc; 222 u_int64_t l_bytes, l_addtime, l_usetime; 223 u_int32_t seq; 224 int line; 225 226 if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) == 0) 227 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "r"); 228 else 229 fp = NULL; 230 if (fp == NULL) { 231 plog(LLV_ERROR, LOCATION, NULL, 232 "failed to open the backup file %s.\n", 233 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); 234 return -1; 235 } 236 237 current = time(NULL); 238 239 for(line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) { 240 /* comment line */ 241 if (buf[0] == '#') 242 continue; 243 244 memset(&tm, 0, sizeof(tm)); 245 p = str2tmx(buf, &tm); 246 if (*p != '%') { 247 err: 248 plog(LLV_ERROR, LOCATION, NULL, 249 "illegal format line#%d in %s: %s\n", 250 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 251 buf); 252 goto next; 253 } 254 created = mktime(&tm); 255 p++; 256 257 for (q = p; *q != '\0' && !isspace((int)*q); q++) 258 ; 259 *q = '\0'; 260 if ((src = str2saddr(p, NULL)) == NULL) 261 goto next; 262 p = q + 1; 263 264 for (q = p; *q != '\0' && !isspace((int)*q); q++) 265 ; 266 *q = '\0'; 267 if ((dst = str2saddr(p, NULL)) == NULL) 268 goto next; 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 next; \ 280 p = q + 1; \ 281 } while (/*CONSTCOND*/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], 307 buf); 308 goto next; 309 } 310 311 if (created + l_addtime < current) { 312 plog(LLV_DEBUG, LOCATION, NULL, 313 "ignore this line#%d in %s due to expiration\n", 314 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); 315 goto next; 316 } 317 l_addtime -= current - created; 318 319 if (pfkey_send_add( 320 lcconf->sock_pfkey, 321 satype, 322 mode, 323 src, 324 dst, 325 spi, 326 reqid, 327 wsize, 328 keymat, 329 e_type, e_keylen, a_type, a_keylen, flags, 330 0, l_bytes, l_addtime, 0, seq) < 0) { 331 plog(LLV_ERROR, LOCATION, NULL, 332 "restore SA filed line#%d in %s: %s\n", 333 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 334 ipsec_strerror()); 335 } 336 337 next: 338 if (src != NULL) { 339 racoon_free(src); 340 src = NULL; 341 } 342 if (dst != NULL) { 343 racoon_free(dst); 344 dst = NULL; 345 } 346 if (keymat != NULL) { 347 racoon_free(keymat); 348 keymat = NULL; 349 } 350 } 351 352 fclose(fp); 353 354 /* 355 * There is a possibility that an abnormal system down will happen 356 * again before new negotiation will be started. so racoon clears 357 * the backup file here. it's ok that old SAs are remained in the 358 * file. any old SA will not be installed because racoon checks the 359 * lifetime and compare with current time. 360 */ 361 362 return 0; 363 } 364 365 int 366 backupsa_clean() 367 { 368 FILE *fp; 369 370 /* simply return if the file is not defined. */ 371 if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]) 372 return 0; 373 374 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+"); 375 if (fp == NULL) { 376 plog(LLV_ERROR, LOCATION, NULL, 377 "failed to clean the backup file %s.\n", 378 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); 379 return -1; 380 } 381 fclose(fp); 382 return 0; 383 } 384 385 /* 386 * convert fixed string into the tm structure. 387 * The fixed string is like 'Nov 24 18:22:48 1986'. 388 * static char *format = "%b %d %T %Y"; 389 */ 390 static char * 391 str2tmx(char *p, struct tm *tm) 392 { 393 int i, len; 394 395 /* Month */ 396 for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) { 397 if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) { 398 tm->tm_mon = i; 399 break; 400 } 401 } 402 if (i == sizeof(strmon)/sizeof(strmon[0])) 403 return 0; 404 p += strlen(strmon[i]); 405 if (*p++ != ' ') 406 return 0; 407 408 /* Day */ 409 len = 2; 410 tm->tm_mday = str2num(p, len); 411 if (tm->tm_mday == -1 || tm->tm_mday > 31) 412 return 0; 413 p += len; 414 if (*p++ != ' ') 415 return 0; 416 417 /* Hour */ 418 len = 2; 419 tm->tm_hour = str2num(p, len); 420 if (tm->tm_hour == -1 || tm->tm_hour > 24) 421 return 0; 422 p += len; 423 if (*p++ != ':') 424 return 0; 425 426 /* Min */ 427 len = 2; 428 tm->tm_min = str2num(p, len); 429 if (tm->tm_min == -1 || tm->tm_min > 60) 430 return 0; 431 p += len; 432 if (*p++ != ':') 433 return 0; 434 435 /* Sec */ 436 len = 2; 437 tm->tm_sec = str2num(p, len); 438 if (tm->tm_sec == -1 || tm->tm_sec > 60) 439 return 0; 440 p += len; 441 if (*p++ != ' ') 442 return 0; 443 444 /* Year */ 445 len = 4; 446 tm->tm_year = str2num(p, len); 447 if (tm->tm_year == -1 || tm->tm_year < 1900) 448 return 0; 449 tm->tm_year -= 1900; 450 p += len; 451 452 return p; 453 } 454 455 static int 456 str2num(p, len) 457 char *p; 458 int len; 459 { 460 int res, i; 461 462 res = 0; 463 for (i = len; i > 0; i--) { 464 if (!isdigit((int)*p)) 465 return -1; 466 res *= 10; 467 res += *p - '0'; 468 p++; 469 } 470 471 return res; 472 } 473 474 #ifdef TEST 475 #include <stdio.h> 476 int 477 main() 478 { 479 struct tm tm; 480 time_t t; 481 char *buf = "Nov 24 18:22:48 1986 "; 482 char *p; 483 484 memset(&tm, 0, sizeof(tm)); 485 p = str2tmx(buf, &tm); 486 printf("[%x]\n", *p); 487 t = mktime(&tm); 488 if (t == -1) 489 printf("mktime failed."); 490 p = ctime(&t); 491 printf("[%s]\n", p); 492 493 exit(0); 494 } 495 #endif 496