diff options
Diffstat (limited to 'ipsec-tools/src/racoon/backupsa.c')
-rw-r--r-- | ipsec-tools/src/racoon/backupsa.c | 469 |
1 files changed, 469 insertions, 0 deletions
diff --git a/ipsec-tools/src/racoon/backupsa.c b/ipsec-tools/src/racoon/backupsa.c new file mode 100644 index 00000000..82d74ca8 --- /dev/null +++ b/ipsec-tools/src/racoon/backupsa.c @@ -0,0 +1,469 @@ +/* $NetBSD: backupsa.c,v 1.10 2010/04/02 15:15:00 christos Exp $ */ + +/* $KAME: backupsa.c,v 1.16 2001/12/31 20:13:40 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include <netinet/in.h> +#include PATH_IPSEC_H + +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +#include "var.h" +#include "misc.h" +#include "vmbuf.h" +#include "str2val.h" +#include "plog.h" +#include "debug.h" + +#include "localconf.h" +#include "sockmisc.h" +#include "safefile.h" +#include "backupsa.h" +#include "libpfkey.h" + +/* + * (time string)%(sa parameter) + * (time string) := ex. Nov 24 18:22:48 1986 + * (sa parameter) := + * src dst satype spi mode reqid wsize \ + * e_type e_keylen a_type a_keylen flags \ + * l_alloc l_bytes l_addtime l_usetime seq keymat + */ +static char *format = "%b %d %T %Y"; /* time format */ +static char *strmon[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static char *str2tmx __P((char *, struct tm *)); +static int str2num __P((char *, int)); + +/* + * output the sa parameter. + */ +int +backupsa_to_file(sa_args) + struct pfkey_send_sa_args *sa_args; +{ + char buf[1024]; + struct tm *tm; + time_t t; + char *p, *k; + int len, l, i; + FILE *fp; + + p = buf; + len = sizeof(buf); + + t = time(NULL); + tm = localtime(&t); + l = strftime(p, len, format, tm); + p += l; + len -= l; + if (len < 0) + goto err; + + l = snprintf(p, len, "%%"); + if (l < 0 || l >= len) + goto err; + p += l; + len -= l; + if (len < 0) + goto err; + + i = getnameinfo(sa_args->src, sysdep_sa_len(sa_args->src), p, len, NULL, 0, NIFLAGS); + if (i != 0) + goto err; + l = strlen(p); + p += l; + len -= l; + if (len < 0) + goto err; + + l = snprintf(p, len, " "); + if (l < 0 || l >= len) + goto err; + p += l; + len -= l; + if (len < 0) + goto err; + + i = getnameinfo(sa_args->dst, sysdep_sa_len(sa_args->dst), p, len, NULL, 0, NIFLAGS); + if (i != 0) + goto err; + l = strlen(p); + p += l; + len -= l; + if (len < 0) + goto err; + + l = snprintf(p, len, + " %u %lu %u %u %u " + "%u %u %u %u %u " + "%u %llu %llu %llu %u", + sa_args->satype, (unsigned long)ntohl(sa_args->spi), + sa_args->mode, sa_args->reqid, sa_args->wsize, sa_args->e_type, + sa_args->e_keylen, sa_args->a_type, sa_args->a_keylen, + sa_args->flags, sa_args->l_alloc, + (unsigned long long)sa_args->l_bytes, + (unsigned long long)sa_args->l_addtime, + (unsigned long long)sa_args->l_usetime, sa_args->seq); + + if (l < 0 || l >= len) + goto err; + p += l; + len -= l; + if (len < 0) + goto err; + + k = val2str(sa_args->keymat, sa_args->e_keylen + sa_args->a_keylen); + l = snprintf(p, len, " %s", k); + racoon_free(k); + if (l < 0 || l >= len) + goto err; + p += l; + len -= l; + if (len < 0) + goto err; + + /* open the file and write the SA parameter */ + if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) != 0 || + (fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "a")) == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to open the backup file %s.\n", + lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); + return -1; + } + fprintf(fp, "%s\n", buf); + fclose(fp); + + return 0; + +err: + plog(LLV_ERROR, LOCATION, NULL, + "SA cannot be saved to a file.\n"); + return -1; +} + +int +backupsa_from_file() +{ + FILE *fp; + char buf[512]; + struct tm tm; + time_t created, current; + char *p, *q; + size_t keymatlen; + int line; + struct pfkey_send_sa_args sa_args; + + memset(&sa_args, 0, sizeof(sa_args)); + + if (safefile(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], 1) == 0) + fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "r"); + else + fp = NULL; + if (fp == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to open the backup file %s.\n", + lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); + return -1; + } + + current = time(NULL); + + for(line = 1; fgets(buf, sizeof(buf), fp) != NULL; line++) { + /* comment line */ + if (buf[0] == '#') + continue; + + memset(&tm, 0, sizeof(tm)); + p = str2tmx(buf, &tm); + if (*p != '%') { + err: + plog(LLV_ERROR, LOCATION, NULL, + "illegal format line#%d in %s: %s\n", + line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], + buf); + goto next; + } + created = mktime(&tm); + p++; + + for (q = p; *q != '\0' && !isspace((int)*q); q++) + ; + *q = '\0'; + if ((sa_args.src = str2saddr(p, NULL)) == NULL) + goto next; + p = q + 1; + + for (q = p; *q != '\0' && !isspace((int)*q); q++) + ; + *q = '\0'; + if ((sa_args.dst = str2saddr(p, NULL)) == NULL) + goto next; + p = q + 1; + +#define GETNEXTNUM(value, function) \ +do { \ + char *y; \ + for (q = p; *q != '\0' && !isspace((int)*q); q++) \ + ; \ + *q = '\0'; \ + (value) = function(p, &y, 10); \ + if ((value) == 0 && *y != '\0') \ + goto next; \ + p = q + 1; \ +} while (/*CONSTCOND*/0); + + GETNEXTNUM(sa_args.satype, strtoul); + GETNEXTNUM(sa_args.spi, strtoul); + sa_args.spi = ntohl(sa_args.spi); + GETNEXTNUM(sa_args.mode, strtoul); + GETNEXTNUM(sa_args.reqid, strtoul); + GETNEXTNUM(sa_args.wsize, strtoul); + GETNEXTNUM(sa_args.e_type, strtoul); + GETNEXTNUM(sa_args.e_keylen, strtoul); + GETNEXTNUM(sa_args.a_type, strtoul); + GETNEXTNUM(sa_args.a_keylen, strtoul); + GETNEXTNUM(sa_args.flags, strtoul); + GETNEXTNUM(sa_args.l_alloc, strtoul); + GETNEXTNUM(sa_args.l_bytes, strtouq); + GETNEXTNUM(sa_args.l_addtime, strtouq); + GETNEXTNUM(sa_args.l_usetime, strtouq); + GETNEXTNUM(sa_args.seq, strtoul); + +#undef GETNEXTNUM + + sa_args.keymat = str2val(p, 16, &keymatlen); + if (sa_args.keymat == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "illegal format(keymat) line#%d in %s: %s\n", + line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], + buf); + goto next; + } + + if (created + sa_args.l_addtime < current) { + plog(LLV_DEBUG, LOCATION, NULL, + "ignore this line#%d in %s due to expiration\n", + line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); + goto next; + } + sa_args.l_addtime -= current - created; + + if (pfkey_send_add2(&sa_args) < 0) { + plog(LLV_ERROR, LOCATION, NULL, + "restore SA failed line#%d in %s: %s\n", + line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], + ipsec_strerror()); + } + +next: + if (sa_args.src != NULL) { + racoon_free(sa_args.src); + sa_args.src = NULL; + } + if (sa_args.dst != NULL) { + racoon_free(sa_args.dst); + sa_args.dst = NULL; + } + if (sa_args.keymat != NULL) { + racoon_free(sa_args.keymat); + sa_args.keymat = NULL; + } + } + + fclose(fp); + + /* + * There is a possibility that an abnormal system down will happen + * again before new negotiation will be started. so racoon clears + * the backup file here. it's ok that old SAs are remained in the + * file. any old SA will not be installed because racoon checks the + * lifetime and compare with current time. + */ + + return 0; +} + +int +backupsa_clean() +{ + FILE *fp; + + /* simply return if the file is not defined. */ + if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]) + return 0; + + fp = fopen(lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], "w+"); + if (fp == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to clean the backup file %s.\n", + lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]); + return -1; + } + fclose(fp); + return 0; +} + +/* + * convert fixed string into the tm structure. + * The fixed string is like 'Nov 24 18:22:48 1986'. + * static char *format = "%b %d %T %Y"; + */ +static char * +str2tmx(char *p, struct tm *tm) +{ + int i, len; + + /* Month */ + for (i = 0; i < sizeof(strmon)/sizeof(strmon[0]); i++) { + if (strncasecmp(p, strmon[i], strlen(strmon[i])) == 0) { + tm->tm_mon = i; + break; + } + } + if (i == sizeof(strmon)/sizeof(strmon[0])) + return 0; + p += strlen(strmon[i]); + if (*p++ != ' ') + return 0; + + /* Day */ + len = 2; + tm->tm_mday = str2num(p, len); + if (tm->tm_mday == -1 || tm->tm_mday > 31) + return 0; + p += len; + if (*p++ != ' ') + return 0; + + /* Hour */ + len = 2; + tm->tm_hour = str2num(p, len); + if (tm->tm_hour == -1 || tm->tm_hour > 24) + return 0; + p += len; + if (*p++ != ':') + return 0; + + /* Min */ + len = 2; + tm->tm_min = str2num(p, len); + if (tm->tm_min == -1 || tm->tm_min > 60) + return 0; + p += len; + if (*p++ != ':') + return 0; + + /* Sec */ + len = 2; + tm->tm_sec = str2num(p, len); + if (tm->tm_sec == -1 || tm->tm_sec > 60) + return 0; + p += len; + if (*p++ != ' ') + return 0; + + /* Year */ + len = 4; + tm->tm_year = str2num(p, len); + if (tm->tm_year == -1 || tm->tm_year < 1900) + return 0; + tm->tm_year -= 1900; + p += len; + + return p; +} + +static int +str2num(p, len) + char *p; + int len; +{ + int res, i; + + res = 0; + for (i = len; i > 0; i--) { + if (!isdigit((int)*p)) + return -1; + res *= 10; + res += *p - '0'; + p++; + } + + return res; +} + +#ifdef TEST +#include <stdio.h> +int +main() +{ + struct tm tm; + time_t t; + char *buf = "Nov 24 18:22:48 1986 "; + const char *p; + + memset(&tm, 0, sizeof(tm)); + p = str2tmx(buf, &tm); + printf("[%x]\n", *p); + t = mktime(&tm); + if (t == -1) + printf("mktime failed."); + if ((p = ctime(&t)) == NULL) + p = "?"; + printf("[%s]\n", p); + + exit(0); +} +#endif |