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 */ 80static char *format = "%b %d %T %Y"; /* time format */ 81static char *strmon[12] = { 82 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 83 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 84}; 85 86static char *str2tmx __P((char *, struct tm *)); 87static int str2num __P((char *, int)); 88 89/* 90 * output the sa parameter. 91 */ 92int 93backupsa_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, sysdep_sa_len(src), 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, sysdep_sa_len(dst), 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 196err: 197 plog(LLV_ERROR, LOCATION, NULL, 198 "SA cannot be saved to a file.\n"); 199 return -1; 200} 201 202int 203backupsa_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) \ 270do { \ 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) { 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 355int 356backupsa_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 */ 380static char * 381str2tmx(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 445static int 446str2num(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> 466int 467main() 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 486