chiark / gitweb /
Import release 0.1.8 v0.1.8
authorStephen Early <steve@greenend.org.uk>
Tue, 16 Oct 2001 13:05:00 +0000 (14:05 +0100)
committerStephen Early <steve@greenend.org.uk>
Wed, 18 May 2011 12:40:08 +0000 (13:40 +0100)
Makefile.in
NEWS [new file with mode: 0644]
README
TODO
example-sites-file [deleted file]
example.conf
netlink.c
netlink.h
site.c
transform.c
tun.c

index abc8528..5faf2f6 100644 (file)
@@ -18,7 +18,7 @@
 .PHONY:        all clean realclean dist install
 
 PACKAGE:=secnet
-VERSION:=0.1.7
+VERSION:=0.1.8
 
 @SET_MAKE@
 
@@ -48,12 +48,12 @@ OBJECTS:=secnet.o util.o conffile.yy.o conffile.tab.o conffile.o modules.o \
        serpent.o md5.o version.o tun.o slip.o sha1.o ipaddr.o log.o \
        process.o
 
-DISTFILES:=COPYING CREDITS INSTALL Makefile.in NOTES README TODO \
+DISTFILES:=COPYING CREDITS INSTALL Makefile.in NEWS NOTES README TODO \
        conffile.c conffile.fl conffile.h conffile.y \
        conffile_internal.h config.h.bot \
        config.h.in config.h.top configure \
        configure.in debian dh.c \
-       example-sites-file example.conf make-secnet-sites.py \
+       example.conf make-secnet-sites.py \
        install.sh ipaddr.c ipaddr.h ipaddr.py linux log.c md5.c md5.h \
        modules.c netlink.c netlink.h process.c process.h \
        random.c resolver.c rsa.c \
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..d605fe5
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,20 @@
+* New in version 0.1.8
+
+Netlink devices now support a 'point-to-point' mode.  In this mode the
+netlink device does not require an IP address; instead, the IP address
+of the other end of the tunnel is specified using the 'ptp-address'
+option.  Precisely one site must be configured to use the netlink
+device.
+
+The tunnel code in site.c now initiates a key setup if the
+reverse-transform function fails (wrong key, bad MAC, too much skew,
+etc.) - this should make secnet more reliable on dodgy links, which
+are much more common than links with active attackers...  (an attacker
+can now force a new key setup by replaying an old packet, but apart
+from minor denial of service on slow links or machines this won't
+achieve them much).
+
+The sequence number skew detection code in transform.c now only
+complains about 'reverse skew' - replays of packets that are too
+old. 'Forward skew' (gaps in the sequence numbers of received packets)
+is now tolerated silently, to cope with large amounts of packet loss.
diff --git a/README b/README
index a21a2e7..79b5447 100644 (file)
--- a/README
+++ b/README
@@ -291,8 +291,13 @@ null-netlink: dict argument
     by any remote site using this netlink device
   local-address (string): IP address of host's tunnel interface
   secnet-address (string): IP address of this netlink device
+  ptp-address (string): IP address of the other end of a point-to-point link
   mtu (integer): MTU of host's tunnel interface
 
+Only one of secnet-address or ptp-address may be specified. If
+point-to-point mode is in use then precisely one tunnel must register
+with the netlink device.
+
 Netlink will dump its current routing table to the system/log on
 receipt of SIGUSR1.
 
@@ -331,6 +336,9 @@ tun-old: dict argument
   route-path (string): optional, path to route command
  plus generic netlink options, as for 'null-netlink'
 
+ I recommend you don't specify the 'interface' option unless you're
+ doing something that requires the interface name to be constant.
+
 ** rsa
 
 Defines:
@@ -364,3 +372,21 @@ Defines:
 
 Defines:
   sha1 (hash closure)
+
+** conffile
+
+Defines:
+  makelist (dictionary => list of definitions)
+  readfile (string => string)
+  map (closure,list => list)
+
+makelist: dictionary
+  returns a list consisting of the definitions in the dictionary. The keys
+  are discarded.
+
+readfile: string
+  reads the named file and returns its contents as a string
+
+map:
+  applies the closure specified as arg1 to each of the elements in the list.
+  Returns a list made up of the outputs of the closure.
diff --git a/TODO b/TODO
index d0e8db7..f32d109 100644 (file)
--- a/TODO
+++ b/TODO
@@ -3,16 +3,11 @@ Makefile.in: autodep stuff
 dh.c: change format to binary from decimal string (without introducing
 endianness problems)
 
+ipaddr.c: implement the useful functionality from ipaddr.py
+
 netlink.c: investigate why 'default' routes don't appear to work
 (reported by JDA).
-
-slip.c: restart userv-ipif to cope with soft routes? Restart it if it
-fails in use?
-
-tun.c: jdamery reports tun-old code works on Linux-2.2.
-Unresolved problem with ioctl(TUNSETIFF) sometimes returning EINVAL, seems
-to be related to early 2.4.x (x<=5) series kernels. 2.4.9 and above seem ok;
-2.4.[678] untested.
+Implement the 'allow_route' option properly.
 
 random.c: test
 
@@ -22,12 +17,23 @@ rsa.c: check padding type, change format to binary from decimal string
 site.c: the site_incoming() routing could be implemented much more
 cleanly using a table. There's still quite a lot of redundancy in this
 file. Abandon key exchanges when a bad packet is received. Modify
-protocol to include version fields, as described in the NOTES file.
+protocol to include version fields, as described in the NOTES
+file. Implement keepalive mode. Make policy about when to initiate key
+exchanges more configurable (how many NAKs / bad reverse-transforms
+does it take to prompt a key exchange?)
+
+slip.c: restart userv-ipif to cope with soft routes? Restart it if it
+fails in use?
+userv-ipif doesn't like the same bit of network to be specified
+twice. Use the new functionality in ipaddr.c once it's done to prevent
+this.
+
+tun.c: jdamery reports tun-old code works on Linux-2.2.
+Unresolved problem with ioctl(TUNSETIFF) sometimes returning EINVAL, seems
+to be related to early 2.4.x (x<=5) series kernels. 2.4.9 and above seem ok;
+2.4.[678] untested.
 
 transform.c: separate the transforms into multiple parts, which can
 then be combined in the configuration file.  Will allow the user to
 plug in different block ciphers, invent an authenticity-only mode,
 etc.
-
-sha1.c: test
-
diff --git a/example-sites-file b/example-sites-file
deleted file mode 100644 (file)
index 1249dd1..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# This is an example /etc/secnet/sites file. It doesn't define any real
-# sites. The diffie-hellman modulus and generator are real and will work,
-# but if you're setting up your own VPN I suggest you choose your own.
-
-example-vpn {
-
-dh diffie-hellman("8db5f2c15ac96d9f3382d1ef4688fba14dc7908ae7dfd71a9cfe7f479a75d506dc53f159aeaf488bde073fe544bc91c099f101fcf60074f30c06e36263c03ca9e07931ce3fc235fe1171dc6d9316fb097bd4362891e2c36e234e7c16b038fd97b1f165c710e90537de66ee4f54001f5712b050d4e07de3fba07607b19b64f6c3","2");
-hash md5;
-
-key-lifetime 3600000; # One hour = 3600000 milliseconds
-
-some-site {
-       # The 'name' here must match the 'local-name' defined in the 
-       # site's /etc/secnet/secnet.conf, because it's used in the
-       # key-setup protocol.
-       # The name of this dictionary doesn't have to - it's local
-       # to the configuration system.
-       name "some-site";
-       address "foo.greenend.org.uk";
-       port 5678;
-       networks "192.168.x.x/24", "192.168.x.x/24";
-       key rsa-public("35","131453873229748492184986747327990913828179255774895541667982108408897406369168730551214152673574619385573519088922707364993860644376262000057302119569116289693520981276177337391324943049983046703853106890057346878967444626093102422836819979338760420960495059950787838142162794317002315919126174831103379472833");
-       };
-
-some-other-site {
-       name "some-other-site";
-       address "bar.greenend.org.uk";
-       port 18436;
-       networks "192.168.x.x/24", "192.168.x.x/24";
-       key rsa-public("35","154107175724781677184264293617887954015562225725852111745852699493257053099810379926047345975839848434403852210573185384327420788855664167034282567346429150999373740871227795773749618022407366186555483566435251279808390618987056868368084933125373643004284007109877210578088697520329039753099981203724057693543");
-       };
-
-a-third-site {
-       name "different-for-a-change";
-       address "baz.greenend.org.uk";
-       port 3234;
-       networks "foo";
-       key-lifetime 1800000; # Can be set per-site as well, you see...
-       setup-retries 10; # So can this
-       setup-timeout 2000; # And this. (And 'wait-time' too.)
-       key rsa-public("e","n");
-       };
-
-};
index 03e5f43..189b442 100644 (file)
@@ -60,6 +60,9 @@ system {
 # wait-time             wait between unsuccessful key setup attempts, in ms
 # renegotiate-time      set up a new key if we see any traffic after this time
 
+setup-retries 10;
+setup-timeout 2000;
+
 # Use the universal TUN/TAP driver to get packets to and from the kernel
 #  (use tun-old if you are not on Linux-2.4)
 netlink tun {
@@ -125,6 +128,8 @@ log-events "setup-init","setup-timeout","activate-key","timeout-key","errors",
 # that it's non-blocking. XXX 'yes' isn't implemented yet.
 random randomfile("/dev/urandom",no);
 
+# If you're using the make-secnet-sites.py script then your local-name
+# will be of the form "vpnname/location/site" eg. "sgo/greenend/sinister"
 local-name "your-site-name";
 local-key rsa-private("/etc/secnet/key");
 
index bfdb19b..f77d6bd 100644 (file)
--- a/netlink.c
+++ b/netlink.c
@@ -8,13 +8,6 @@
    packet to the kernel we check that the tunnel it came over could
    reasonably have produced it. */
 
-/* XXX new feature: "point-to-point" mode.  Instead of specifying a
-   secnet-address in the configuration dictionary, the user specifies
-   the address of the machine at the other end of the (one and only)
-   tunnel.  We bypass all IP packet processing code.  This mode is
-   useful for leafnodes like laptops, which don't require a secnet
-   router address. */
-
 #include "secnet.h"
 #include "util.h"
 #include "ipaddr.h"
@@ -442,8 +435,8 @@ static void netlink_incoming(void *sst, void *cid, struct buffer_if *buf)
 
     /* Check source */
     if (client) {
-       /* Check that the packet source is in 'nets' and its destination is
-          in st->networks */
+       /* Check that the packet source is appropriate for the tunnel
+          it came down */
        if (!subnet_matches_list(client->networks,source)) {
            string_t s,d;
            s=ipaddr_to_string(source);
@@ -455,6 +448,9 @@ static void netlink_incoming(void *sst, void *cid, struct buffer_if *buf)
            return;
        }
     } else {
+       /* Check that the packet originates in our configured local
+          network, and hasn't been forwarded from elsewhere or
+          generated with the wrong source address */
        if (!subnet_matches_list(&st->networks,source)) {
            string_t s,d;
            s=ipaddr_to_string(source);
@@ -466,6 +462,20 @@ static void netlink_incoming(void *sst, void *cid, struct buffer_if *buf)
            return;
        }
     }
+
+    /* If this is a point-to-point device we don't examine the packet at
+       all; we blindly send it down our one-and-only registered tunnel,
+       or to the host, depending on where it came from. */
+    if (st->ptp) {
+       if (client) {
+           st->deliver_to_host(st->dst,NULL,buf);
+       } else {
+           st->clients->deliver(st->clients->dst,NULL,buf);
+       }
+       BUF_ASSERT_FREE(buf);
+       return;
+    }
+
     /* (st->secnet_address needs checking before matching destination
        addresses) */
     if (dest==st->secnet_address) {
@@ -552,14 +562,20 @@ static void *netlink_regnets(void *sst, struct subnet_list *nets,
        Message(M_ERROR,"%s: site %s specifies networks that "
                "intersect with the explicitly excluded remote networks\n",
                st->name,client_name);
-       return False;
+       return NULL;
+    }
+
+    if (st->clients && st->ptp) {
+       fatal("%s: only one site may use a point-to-point netlink device\n",
+             st->name);
+       return NULL;
     }
 
     c=safe_malloc(sizeof(*c),"netlink_regnets");
     c->networks=nets;
     c->deliver=deliver;
     c->dst=dst;
-    c->name=client_name; /* XXX copy it? */
+    c->name=client_name;
     c->options=options;
     c->link_quality=LINK_QUALITY_DOWN;
     c->next=st->clients;
@@ -614,6 +630,13 @@ static void netlink_phase_hook(void *sst, uint32_t new_phase)
     struct netlink_client *c;
     uint32_t i,j;
 
+    if (!st->clients && st->ptp) {
+       /* Point-to-point netlink devices must have precisely one
+          client. If none has registered by now, complain. */
+       fatal("%s: point-to-point netlink devices must have precisely "
+             "one client. This one doesn't have any.\n",st->name);
+    }
+
     /* All the networks serviced by the various tunnels should now
      * have been registered.  We build a routing table by sorting the
      * routes into most-specific-first order.  */
@@ -661,6 +684,8 @@ netlink_deliver_fn *netlink_init(struct netlink *st,
                                 netlink_route_fn *set_route,
                                 netlink_deliver_fn *to_host)
 {
+    item_t *sa, *ptpa;
+
     st->dst=dst;
     st->cl.description=description;
     st->cl.type=CL_NETLINK;
@@ -685,8 +710,23 @@ netlink_deliver_fn *netlink_init(struct netlink *st,
     /* secnet-address does not have to be in local-networks;
        however, it should be advertised in the 'sites' file for the
        local site. */
-    st->secnet_address=string_to_ipaddr(
-       dict_find_item(dict,"secnet-address", True, "netlink", loc),"netlink");
+    sa=dict_find_item(dict,"secnet-address",False,"netlink",loc);
+    ptpa=dict_find_item(dict,"ptp-address", False, "netlink", loc);
+    if (sa && ptpa) {
+       cfgfatal(loc,st->name,"you may not specify secnet-address and "
+                "ptp-address in the same netlink device\n");
+    }
+    if (!(sa || ptpa)) {
+       cfgfatal(loc,st->name,"you must specify secnet-address or "
+                "ptp-address for this netlink device\n");
+    }
+    if (sa) {
+       st->secnet_address=string_to_ipaddr(sa,"netlink");
+       st->ptp=False;
+    } else {
+       st->secnet_address=string_to_ipaddr(ptpa,"netlink");
+       st->ptp=True;
+    }
     st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
     buffer_new(&st->icmp,ICMP_BUFSIZE);
     st->n_routes=0;
index f3f43d5..4cc80af 100644 (file)
--- a/netlink.h
+++ b/netlink.h
@@ -42,7 +42,9 @@ struct netlink {
     uint32_t max_end_pad;
     struct subnet_list networks;
     struct subnet_list exclude_remote_networks;
-    uint32_t secnet_address; /* our own address */
+    uint32_t secnet_address; /* our own address, or possibly the address of
+                               the other end of a point-to-point link */
+    bool_t ptp;
     uint32_t mtu;
     struct netlink_client *clients;
     netlink_deliver_fn *deliver_to_host; /* Provided by driver */
diff --git a/site.c b/site.c
index 8e7a3fe..8223fb3 100644 (file)
--- a/site.c
+++ b/site.c
@@ -629,7 +629,7 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0,
                                       msg0,&transform_err)) {
        /* There's a problem */
        slog(st,LOG_SEC,"transform: %s",transform_err);
-       return False;
+       return initiate_key_setup(st);
     }
     CHECK_AVAIL(msg0,4);
     type=buf_unprepend_uint32(msg0);
index a870449..4c55b45 100644 (file)
@@ -308,10 +308,10 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf,
        is only allowed to increase. */
     seqnum=buf_unprepend_uint32(buf);
     skew=seqnum-ti->lastrecvseq;
-    if (skew<10) {
+    if (skew<0x8fffffff) {
        /* Ok */
        ti->lastrecvseq=seqnum;
-    } else if ((0-skew)<10) {
+    } else if ((0-skew)<ti->max_skew) {
        /* Ok */
     } else {
        /* Too much skew */
diff --git a/tun.c b/tun.c
index efcf6b6..6f42dd2 100644 (file)
--- a/tun.c
+++ b/tun.c
@@ -12,7 +12,7 @@
 #include <linux/if_tun.h>
 #endif
 
-/* XXX where do we find if_tun on other platforms? */
+/* Where do we find if_tun on other platforms? */
 
 /* Connection to the kernel through the universal TUN/TAP driver */
 
@@ -76,8 +76,8 @@ static void tun_deliver_to_kernel(void *sst, void *cid,
     struct tun *st=sst;
 
     BUF_ASSERT_USED(buf);
-
-    /* No error checking, because we'd just throw the packet away anyway */
+    /* No error checking, because we'd just throw the packet away
+       anyway if it didn't work. */
     write(st->fd,buf->start,buf->size);
     BUF_FREE(buf);
 }