]> git.saurik.com Git - apple/network_cmds.git/blobdiff - racoon.tproj/backupsa.c
network_cmds-115.tar.gz
[apple/network_cmds.git] / racoon.tproj / backupsa.c
diff --git a/racoon.tproj/backupsa.c b/racoon.tproj/backupsa.c
new file mode 100644 (file)
index 0000000..96a4ff6
--- /dev/null
@@ -0,0 +1,485 @@
+/*     $KAME: backupsa.c,v 1.15 2001/11/16 04:08:10 sakane 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 <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>
+#ifdef IPV6_INRIA_VERSION
+#include <netinet/ipsec.h>
+#else
+#include <netinet6/ipsec.h>
+#endif
+
+#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(satype, mode, src, dst, spi, reqid, wsize,
+                keymat, e_type, e_keylen, a_type, a_keylen, flags,
+                l_alloc, l_bytes, l_addtime, l_usetime, seq)
+        u_int satype, mode, wsize;
+        struct sockaddr *src, *dst;
+        u_int32_t spi, reqid;
+        caddr_t keymat;
+        u_int e_type, e_keylen, a_type, a_keylen, flags;
+        u_int32_t l_alloc;
+        u_int64_t l_bytes, l_addtime, l_usetime;
+        u_int32_t seq;
+{
+       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(src, src->sa_len, 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(dst, dst->sa_len, 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",
+               satype, (unsigned long)ntohl(spi), mode, reqid, wsize,
+               e_type, e_keylen, a_type, a_keylen, flags,
+               l_alloc, (unsigned long long)l_bytes,
+               (unsigned long long)l_addtime, (unsigned long long)l_usetime,
+               seq);
+       if (l < 0 || l >= len)
+               goto err;
+       p += l;
+       len -= l;
+       if (len < 0)
+               goto err;
+
+       k = val2str(keymat, e_keylen + a_keylen);
+       l = snprintf(p, len, " %s", k);
+       if (l < 0 || l >= len)
+               goto err;
+       racoon_free(k);
+       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;
+        u_int satype, mode;
+        struct sockaddr *src, *dst;
+        u_int32_t spi, reqid;
+        caddr_t keymat;
+       size_t keymatlen;
+        u_int wsize, e_type, e_keylen, a_type, a_keylen, flags;
+        u_int32_t l_alloc;
+        u_int64_t l_bytes, l_addtime, l_usetime;
+        u_int32_t seq;
+       int line;
+
+       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);
+                       continue;
+               }
+               created = mktime(&tm);
+               p++;
+
+               for (q = p; *q != '\0' && !isspace(*q); q++)
+                       ;
+               *q = '\0';
+               src = str2saddr(p, NULL);
+               if (src == NULL)
+                       goto err;
+               p = q + 1;
+
+               for (q = p; *q != '\0' && !isspace(*q); q++)
+                       ;
+               *q = '\0';
+               dst = str2saddr(p, NULL);
+               if (dst == NULL) {
+                       racoon_free(src);
+                       goto err;
+               }
+               p = q + 1;
+
+#define GETNEXTNUM(value, function) \
+do { \
+       char *y; \
+       for (q = p; *q != '\0' && !isspace(*q); q++) \
+               ; \
+       *q = '\0'; \
+       (value) = function(p, &y, 10); \
+       if ((value) == 0 && *y != '\0') \
+               goto err; \
+       p = q + 1; \
+} while (0);
+
+               GETNEXTNUM(satype, strtoul);
+               GETNEXTNUM(spi, strtoul);
+               spi = ntohl(spi);
+               GETNEXTNUM(mode, strtoul);
+               GETNEXTNUM(reqid, strtoul);
+               GETNEXTNUM(wsize, strtoul);
+               GETNEXTNUM(e_type, strtoul);
+               GETNEXTNUM(e_keylen, strtoul);
+               GETNEXTNUM(a_type, strtoul);
+               GETNEXTNUM(a_keylen, strtoul);
+               GETNEXTNUM(flags, strtoul);
+               GETNEXTNUM(l_alloc, strtoul);
+               GETNEXTNUM(l_bytes, strtouq);
+               GETNEXTNUM(l_addtime, strtouq);
+               GETNEXTNUM(l_usetime, strtouq);
+               GETNEXTNUM(seq, strtoul);
+
+#undef GETNEXTNUM
+
+               keymat = str2val(p, 16, &keymatlen);
+               if (keymat == NULL) {
+                       plog(LLV_ERROR, LOCATION, NULL,
+                               "illegal format(keymat) line#%d in %s: %s\n",
+                               line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], buf);
+                       racoon_free(src);
+                       racoon_free(dst);
+                       continue;
+               }
+
+               if (created + l_addtime < current) {
+                       plog(LLV_DEBUG, LOCATION, NULL,
+                               "ignore this line#%d in %s due to expiration\n",
+                               line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA]);
+                       racoon_free(src);
+                       racoon_free(dst);
+                       racoon_free(keymat);
+                       continue;
+               }
+               l_addtime -= current - created;
+
+               if (pfkey_send_add(
+                               lcconf->sock_pfkey,
+                               satype,
+                               mode,
+                               src,
+                               dst,
+                               spi,
+                               reqid,
+                               wsize,
+                               keymat,
+                               e_type, e_keylen, a_type, a_keylen, flags,
+                               0, l_bytes, l_addtime, 0, seq) < 0) {
+                       plog(LLV_ERROR, LOCATION, NULL,
+                               "restore SA filed line#%d in %s: %s\n",
+                               line, lcconf->pathinfo[LC_PATHTYPE_BACKUPSA], ipsec_strerror());
+               }
+               racoon_free(src);
+               racoon_free(dst);
+               racoon_free(keymat);
+       }
+
+       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(*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 ";
+       char *p;
+
+       memset(&tm, 0, sizeof(tm));
+       p = str2tmx(buf, &tm);
+       printf("[%x]\n", *p);
+       t = mktime(&tm);
+       if (t == -1)
+               printf("mktime failed.");
+       p = ctime(&t);
+       printf("[%s]\n", p);
+
+       exit(0);
+}
+#endif