Return to backupsa.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 1: /* $NetBSD: backupsa.c,v 1.10 2010/04/02 15:15:00 christos 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: const 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: if ((p = ctime(&t)) == NULL) ! 464: p = "?"; ! 465: printf("[%s]\n", p); ! 466: ! 467: exit(0); ! 468: } ! 469: #endif