From: Stephen Early Date: Tue, 16 Oct 2001 13:05:00 +0000 (+0100) Subject: Import release 0.1.8 X-Git-Tag: v0.1.8 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=secnet.git;a=commitdiff_plain;h=c6f79b178fe27ee315055dccb371b63ca1a6183a Import release 0.1.8 --- diff --git a/Makefile.in b/Makefile.in index abc8528..5faf2f6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 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 --- 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 --- 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 index 1249dd1..0000000 --- a/example-sites-file +++ /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"); - }; - -}; diff --git a/example.conf b/example.conf index 03e5f43..189b442 100644 --- a/example.conf +++ b/example.conf @@ -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"); diff --git a/netlink.c b/netlink.c index bfdb19b..f77d6bd 100644 --- 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; diff --git a/netlink.h b/netlink.h index f3f43d5..4cc80af 100644 --- 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 --- 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); diff --git a/transform.c b/transform.c index a870449..4c55b45 100644 --- a/transform.c +++ b/transform.c @@ -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)max_skew) { /* Ok */ } else { /* Too much skew */ diff --git a/tun.c b/tun.c index efcf6b6..6f42dd2 100644 --- a/tun.c +++ b/tun.c @@ -12,7 +12,7 @@ #include #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); }