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