1 /* $NetBSD: backupsa.c,v 1.3 2005/11/21 14:20:28 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 if (l < 0 || l >= len) 180 goto err; 181 racoon_free(k); 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, *dst; 216 u_int32_t spi, reqid; 217 caddr_t keymat; 218 size_t keymatlen; 219 u_int wsize, e_type, e_keylen, a_type, a_keylen, flags; 220 u_int32_t l_alloc; 221 u_int64_t l_bytes, l_addtime, l_usetime; 222 u_int32_t seq; 223 int line; 224 225 if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) == 0) 226 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "r"); 227 else 228 fp = NULL; 229 if (fp == NULL) { 230 plog(LLV_ERROR, LOCATION, NULL, 231 "failed to open the backup file %s.\n", 232 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); 233 return -1; 234 } 235 236 current = time(NULL); 237 238 for(line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) { 239 /* comment line */ 240 if (buf[0] == '#') 241 continue; 242 243 memset(&tm, 0, sizeof(tm)); 244 p = str2tmx(buf, &tm); 245 if (*p != '%') { 246 err: 247 plog(LLV_ERROR, LOCATION, NULL, 248 "illegal format line#%d in %s: %s\n", 249 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf); 250 continue; 251 } 252 created = mktime(&tm); 253 p++; 254 255 for (q = p; *q != '\0' && !isspace((int)*q); q++) 256 ; 257 *q = '\0'; 258 src = str2saddr(p, NULL); 259 if (src == NULL) 260 goto err; 261 p = q + 1; 262 263 for (q = p; *q != '\0' && !isspace((int)*q); q++) 264 ; 265 *q = '\0'; 266 dst = str2saddr(p, NULL); 267 if (dst == NULL) { 268 racoon_free(src); 269 goto err; 270 } 271 p = q + 1; 272 273 #define GETNEXTNUM(value, function) \ 274 do { \ 275 char *y; \ 276 for (q = p; *q != '\0' && !isspace((int)*q); q++) \ 277 ; \ 278 *q = '\0'; \ 279 (value) = function(p, &y, 10); \ 280 if ((value) == 0 && *y != '\0') \ 281 goto err; \ 282 p = q + 1; \ 283 } while (0); 284 285 GETNEXTNUM(satype, strtoul); 286 GETNEXTNUM(spi, strtoul); 287 spi = ntohl(spi); 288 GETNEXTNUM(mode, strtoul); 289 GETNEXTNUM(reqid, strtoul); 290 GETNEXTNUM(wsize, strtoul); 291 GETNEXTNUM(e_type, strtoul); 292 GETNEXTNUM(e_keylen, strtoul); 293 GETNEXTNUM(a_type, strtoul); 294 GETNEXTNUM(a_keylen, strtoul); 295 GETNEXTNUM(flags, strtoul); 296 GETNEXTNUM(l_alloc, strtoul); 297 GETNEXTNUM(l_bytes, strtouq); 298 GETNEXTNUM(l_addtime, strtouq); 299 GETNEXTNUM(l_usetime, strtouq); 300 GETNEXTNUM(seq, strtoul); 301 302 #undef GETNEXTNUM 303 304 keymat = str2val(p, 16, &keymatlen); 305 if (keymat == NULL) { 306 plog(LLV_ERROR, LOCATION, NULL, 307 "illegal format(keymat) line#%d in %s: %s\n", 308 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf); 309 racoon_free(src); 310 racoon_free(dst); 311 continue; 312 } 313 314 if (created + l_addtime < current) { 315 plog(LLV_DEBUG, LOCATION, NULL, 316 "ignore this line#%d in %s due to expiration\n", 317 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); 318 racoon_free(src); 319 racoon_free(dst); 320 racoon_free(keymat); 321 continue; 322 } 323 l_addtime -= current - created; 324 325 if (pfkey_send_add( 326 lcconf->sock_pfkey, 327 satype, 328 mode, 329 src, 330 dst, 331 spi, 332 reqid, 333 wsize, 334 keymat, 335 e_type, e_keylen, a_type, a_keylen, flags, 336 0, l_bytes, l_addtime, 0, seq) < 0) { 337 plog(LLV_ERROR, LOCATION, NULL, 338 "restore SA filed line#%d in %s: %s\n", 339 line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], ipsec_strerror()); 340 } 341 racoon_free(src); 342 racoon_free(dst); 343 racoon_free(keymat); 344 } 345 346 fclose(fp); 347 348 /* 349 * There is a possibility that an abnormal system down will happen 350 * again before new negotiation will be started. so racoon clears 351 * the backup file here. it's ok that old SAs are remained in the 352 * file. any old SA will not be installed because racoon checks the 353 * lifetime and compare with current time. 354 */ 355 356 return 0; 357 } 358 359 int 360 backupsa_clean() 361 { 362 FILE *fp; 363 364 /* simply return if the file is not defined. */ 365 if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]) 366 return 0; 367 368 fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+"); 369 if (fp == NULL) { 370 plog(LLV_ERROR, LOCATION, NULL, 371 "failed to clean the backup file %s.\n", 372 lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); 373 return -1; 374 } 375 fclose(fp); 376 return 0; 377 } 378 379 /* 380 * convert fixed string into the tm structure. 381 * The fixed string is like 'Nov 24 18:22:48 1986'. 382 * static char *format = "%b %d %T %Y"; 383 */ 384 static char * 385 str2tmx(char *p, struct tm *tm) 386 { 387 int i, len; 388 389 /* Month */ 390 for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) { 391 if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) { 392 tm->tm_mon = i; 393 break; 394 } 395 } 396 if (i == sizeof(strmon)/sizeof(strmon[0])) 397 return 0; 398 p += strlen(strmon[i]); 399 if (*p++ != ' ') 400 return 0; 401 402 /* Day */ 403 len = 2; 404 tm->tm_mday = str2num(p, len); 405 if (tm->tm_mday == -1 || tm->tm_mday > 31) 406 return 0; 407 p += len; 408 if (*p++ != ' ') 409 return 0; 410 411 /* Hour */ 412 len = 2; 413 tm->tm_hour = str2num(p, len); 414 if (tm->tm_hour == -1 || tm->tm_hour > 24) 415 return 0; 416 p += len; 417 if (*p++ != ':') 418 return 0; 419 420 /* Min */ 421 len = 2; 422 tm->tm_min = str2num(p, len); 423 if (tm->tm_min == -1 || tm->tm_min > 60) 424 return 0; 425 p += len; 426 if (*p++ != ':') 427 return 0; 428 429 /* Sec */ 430 len = 2; 431 tm->tm_sec = str2num(p, len); 432 if (tm->tm_sec == -1 || tm->tm_sec > 60) 433 return 0; 434 p += len; 435 if (*p++ != ' ') 436 return 0; 437 438 /* Year */ 439 len = 4; 440 tm->tm_year = str2num(p, len); 441 if (tm->tm_year == -1 || tm->tm_year < 1900) 442 return 0; 443 tm->tm_year -= 1900; 444 p += len; 445 446 return p; 447 } 448 449 static int 450 str2num(p, len) 451 char *p; 452 int len; 453 { 454 int res, i; 455 456 res = 0; 457 for (i = len; i > 0; i--) { 458 if (!isdigit((int)*p)) 459 return -1; 460 res *= 10; 461 res += *p - '0'; 462 p++; 463 } 464 465 return res; 466 } 467 468 #ifdef TEST 469 #include <stdio.h> 470 int 471 main() 472 { 473 struct tm tm; 474 time_t t; 475 char *buf = "Nov 24 18:22:48 1986 "; 476 char *p; 477 478 memset(&tm, 0, sizeof(tm)); 479 p = str2tmx(buf, &tm); 480 printf("[%x]\n", *p); 481 t = mktime(&tm); 482 if (t == -1) 483 printf("mktime failed."); 484 p = ctime(&t); 485 printf("[%s]\n", p); 486 487 exit(0); 488 } 489 #endif 490