Messages:
-1) A->B: *,iA,msg1,A,B,nA
+1) A->B: *,iA,msg1,A,B,protorange-A,nA
-2) B->A: iA,iB,msg2,B,A,nB,nA
+2) B->A: iA,iB,msg2,B,A,chosen-protocol,nB,nA
(The order of B and A reverses in alternate messages so that the same
code can be used to construct them...)
-3) A->B: {iB,iA,msg3,A,B,nA,nB,g^x mod m}_PK_A^-1
+3) A->B: {iB,iA,msg3,A,B,protorange-A,chosen-protocol,nA,nB,g^x mod m}_PK_A^-1
If message 1 was a replay then A will not generate message 3, because
it doesn't recognise nA.
If message 2 was from an attacker then B will not generate message 4,
because it doesn't recognise nB.
-4) B->A: {iA,iB,msg4,B,A,nB,nA,g^y mod m}_PK_B^-1
+If an attacker is trying to manipulate the chosen protocol, B can spot
+this when it sees A's message 3.
+
+4) B->A: {iA,iB,msg4,B,A,protorange-B,chosen-protocol,nB,nA,g^y mod m}_PK_B^-1
At this point, A and B share a key, k. B must keep retransmitting
message 4 until it receives a packet encrypted using key k.
+A can abandon the exchange if the chosen protocol is not the one that
+it would have chosen knowing the acceptable protocol ranges of A and
+B.
+
5) A: iB,iA,msg5,(ping/msg5)_k
6) B: iA,iB,msg6,(pong/msg6)_k
/* User-kernel network link */
-/* We will eventually support a variety of methods for extracting
- packets from the kernel: userv-ipif, ipif on its own (when we run
- as root), the kernel TUN driver, SLIP to a pty, an external netlink
- daemon. There is a performance/security tradeoff. */
+/* We support a variety of methods for extracting packets from the
+ kernel: userv-ipif, ipif on its own (when we run as root), the
+ kernel TUN driver. Possible future methods: SLIP to a pty, an
+ external netlink daemon. There is a performance/security
+ tradeoff. */
/* When dealing with SLIP (to a pty, or ipif) we have separate rx, tx
- and client buffers. When receiving we may read() any amount, not
- just whole packets. When transmitting we need to bytestuff anyway,
+ and client buffers. When receiving we may read() any amount, not
+ just whole packets. When transmitting we need to bytestuff anyway,
and may be part-way through receiving. */
-/* Each netlink device is actually a router, with its own IP
- address. We do things like decreasing the TTL and recalculating the
- header checksum, generating ICMP, responding to pings, etc. */
+/* Each netlink device is actually a router, with its own IP address.
+ We do things like decreasing the TTL and recalculating the header
+ checksum, generating ICMP, responding to pings, etc. */
/* This is where we have the anti-spoofing paranoia - before sending a
packet to the kernel we check that the tunnel it came over could
#include <linux/if_tun.h>
#endif
-/* XXX where do we find if_tun on other architectures? */
+/* XXX where do we find if_tun on other platforms? */
#define DEFAULT_BUFSIZE 2048
#define DEFAULT_MTU 1000
uint32_t max_start_pad;
uint32_t max_end_pad;
struct subnet_list networks;
+ struct subnet_list exclude_remote_networks;
uint32_t local_address; /* host interface address */
uint32_t secnet_address; /* our own address */
uint32_t mtu;
"max_start_pad=%d, max_end_pad=%d\n",
nets->entries,max_start_pad,max_end_pad);
+ /* Check that nets does not intersect with st->networks or
+ st->exclude_remote_networks; refuse to register if it does. */
+ if (subnet_lists_intersect(&st->networks,nets)) {
+ Message(M_ERROR,"%s: site %s specifies networks that "
+ "intersect with our local networks\n",st->name,client_name);
+ return False;
+ }
+ if (subnet_lists_intersect(&st->exclude_remote_networks,nets)) {
+ Message(M_ERROR,"%s: site %s specifies networks that "
+ "intersect with the explicitly excluded remote networks\n",
+ st->name,client_name);
+ return False;
+ }
+
c=safe_malloc(sizeof(*c),"netlink_regnets");
c->networks=nets;
c->deliver=deliver;
if (!st->name) st->name=description;
dict_read_subnet_list(dict, "networks", True, "netlink", loc,
&st->networks);
+ dict_read_subnet_list(dict, "exclude-remote-networks", False, "netlink",
+ loc, &st->exclude_remote_networks);
+ /* local-address and secnet-address do not have to be in local-networks;
+ however, they should be advertised in the 'sites' file for the
+ local site. */
st->local_address=string_to_ipaddr(
dict_find_item(dict,"local-address", True, "netlink", loc),"netlink");
st->secnet_address=string_to_ipaddr(
dict_find_item(dict,"secnet-address", True, "netlink", loc),"netlink");
- if (!subnet_match(&st->networks,st->local_address)) {
- cfgfatal(loc,"netlink","local-address must be in local networks\n");
- }
st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
buffer_new(&st->icmp,ICMP_BUFSIZE);
string_t interface_name;
string_t ifconfig_path;
string_t route_path;
+ bool_t tun_old;
+ bool_t search_for_if; /* Applies to tun-old only */
struct buffer_if *buff; /* We receive packets into here
and send them to the netlink code. */
netlink_deliver_fn *netlink_to_tunnel;
struct netlink_client *c;
int i;
+ if (st->tun_old) {
+ if (st->search_for_if) {
+ string_t dname;
+ int i;
+
+ /* ASSERT st->interface_name */
+ dname=safe_malloc(strlen(st->device_path)+4,"tun_old_apply");
+ st->interface_name=safe_malloc(8,"tun_phase_hook");
+
+ for (i=0; i<255; i++) {
+ sprintf(dname,"%s%d",st->device_path,i);
+ if ((st->fd=open(dname,O_RDWR))>0) {
+ sprintf(st->interface_name,"tun%d",i);
+ Message(M_INFO,"%s: allocated network interface %s "
+ "through %s\n",st->nl.name,st->interface_name,
+ dname);
+ break;
+ }
+ }
+ if (st->fd==-1) {
+ fatal("%s: unable to open any TUN device (%s...)\n",
+ st->nl.name,st->device_path);
+ }
+ } else {
+ st->fd=open(st->device_path,O_RDWR);
+ if (st->fd==-1) {
+ fatal_perror("%s: unable to open TUN device file %s",
+ st->nl.name,st->device_path);
+ }
+ }
+ } else {
+#ifdef HAVE_LINUX_IF_H
+ struct ifreq ifr;
+
+ /* New TUN interface: open the device, then do ioctl TUNSETIFF
+ to set or find out the network interface name. */
+ st->fd=open(st->device_path,O_RDWR);
+ if (st->fd==-1) {
+ fatal_perror("%s: can't open device file %s",st->nl.name,
+ st->device_path);
+ }
+ memset(&ifr,0,sizeof(ifr));
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Just send/receive IP packets,
+ no extra headers */
+ if (st->interface_name)
+ strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ);
+ if (ioctl(st->fd,TUNSETIFF,&ifr)<0) {
+ fatal_perror("%s: ioctl(TUNSETIFF)",st->nl.name);
+ }
+ if (!st->interface_name) {
+ st->interface_name=safe_malloc(strlen(ifr.ifr_name)+1,"tun_apply");
+ strcpy(st->interface_name,ifr.ifr_name);
+ Message(M_INFO,"%s: allocated network interface %s\n",st->nl.name,
+ st->interface_name);
+ }
+#else
+ fatal("netlink.c:tun_phase_hook:!tun_old unexpected\n");
+#endif /* HAVE_LINUX_IF_H */
+ }
/* All the networks we'll be using have been registered. Invoke ifconfig
to set the TUN device's address, and route to add routes to all
our networks. */
struct tun *st;
item_t *item;
dict_t *dict;
- struct ifreq ifr;
st=safe_malloc(sizeof(*st),"tun_apply");
netlink_init(&st->nl,st,loc,dict,
"netlink-tun",tun_deliver_to_kernel);
+ st->tun_old=False;
st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
st->interface_name=dict_read_string(dict,"interface",False,
"tun-netlink",loc);
if (!st->route_path) st->route_path="route";
st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"tun-netlink",loc);
- /* New TUN interface: open the device, then do ioctl TUNSETIFF
- to set or find out the network interface name. */
- st->fd=open(st->device_path,O_RDWR);
- if (st->fd==-1) {
- fatal_perror("%s: can't open device file %s",st->nl.name,
- st->device_path);
- }
- memset(&ifr,0,sizeof(ifr));
- ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Just send/receive IP packets,
- no extra headers */
- if (st->interface_name)
- strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ);
- if (ioctl(st->fd,TUNSETIFF,&ifr)<0) {
- fatal_perror("%s: ioctl(TUNSETIFF)",st->nl.name);
- }
- if (!st->interface_name) {
- st->interface_name=safe_malloc(strlen(ifr.ifr_name)+1,"tun_apply");
- strcpy(st->interface_name,ifr.ifr_name);
- Message(M_INFO,"%s: allocated network interface %s\n",st->nl.name,
- st->interface_name);
- }
-
- add_hook(PHASE_DROPPRIV,tun_phase_hook,st);
+ add_hook(PHASE_GETRESOURCES,tun_phase_hook,st);
return new_closure(&st->nl.cl);
}
struct tun *st;
item_t *item;
dict_t *dict;
- bool_t search_for_if;
st=safe_malloc(sizeof(*st),"tun_old_apply");
netlink_init(&st->nl,st,loc,dict,
"netlink-tun",tun_deliver_to_kernel);
+ st->tun_old=True;
st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
st->interface_name=dict_read_string(dict,"interface",False,
"tun-netlink",loc);
- search_for_if=dict_read_bool(dict,"interface-search",False,"tun-netlink",
- loc,st->device_path==NULL);
+ st->search_for_if=dict_read_bool(dict,"interface-search",False,
+ "tun-netlink",loc,st->device_path==NULL);
st->ifconfig_path=dict_read_string(dict,"ifconfig-path",False,
"tun-netlink",loc);
st->route_path=dict_read_string(dict,"route-path",False,"tun-netlink",loc);
'device' as the prefix and try numbers from 0--255. If it's set
to false, treat 'device' as the whole name, and require than an
appropriate interface name be specified. */
- if (search_for_if) {
- string_t dname;
- int i;
-
- if (st->interface_name) {
- cfgfatal(loc,"tun-old","you may not specify an interface name "
- "in interface-search mode\n");
- }
- dname=safe_malloc(strlen(st->device_path)+4,"tun_old_apply");
- st->interface_name=safe_malloc(8,"tun_old_apply");
-
- for (i=0; i<255; i++) {
- sprintf(dname,"%s%d",st->device_path,i);
- if ((st->fd=open(dname,O_RDWR))>0) {
- sprintf(st->interface_name,"tun%d",i);
- Message(M_INFO,"%s: allocated network interface %s "
- "through %s\n",st->nl.name,st->interface_name,dname);
- break;
- }
- }
- if (st->fd==-1) {
- fatal("%s: unable to open any TUN device (%s...)\n",
- st->nl.name,st->device_path);
- }
- } else {
- if (!st->interface_name) {
- cfgfatal(loc,"tun-old","you must specify an interface name "
- "when you explicitly specify a TUN device file\n");
- }
- st->fd=open(st->device_path,O_RDWR);
- if (st->fd==-1) {
- fatal_perror("%s: unable to open TUN device file %s",
- st->nl.name,st->device_path);
- }
+ if (st->search_for_if && st->interface_name) {
+ cfgfatal(loc,"tun-old","you may not specify an interface name "
+ "in interface-search mode\n");
}
+ if (!st->search_for_if && !st->interface_name) {
+ cfgfatal(loc,"tun-old","you must specify an interface name "
+ "when you explicitly specify a TUN device file\n");
+ }
+
- add_hook(PHASE_DROPPRIV,tun_phase_hook,st);
+ add_hook(PHASE_GETRESOURCES,tun_phase_hook,st);
return new_closure(&st->nl.cl);
}
closure_t cl;
struct comm_if ops;
struct cloc loc;
+ uint16_t port;
int fd;
struct buffer_if *rbuf;
struct notify_list *notify;
return True;
}
+static void udp_phase_hook(void *sst, uint32_t new_phase)
+{
+ struct udp *st=sst;
+ struct sockaddr_in addr;
+
+ st->fd=socket(AF_INET, SOCK_DGRAM, 0);
+ if (st->fd<0) {
+ fatal_perror("udp (%s:%d): socket",st->loc.file,st->loc.line);
+ }
+ if (fcntl(st->fd, F_SETFL, fcntl(st->fd, F_GETFL)|O_NONBLOCK)==-1) {
+ fatal_perror("udp (%s:%d): fcntl(set O_NONBLOCK)",
+ st->loc.file,st->loc.line);
+ }
+ if (fcntl(st->fd, F_SETFD, FD_CLOEXEC)==-1) {
+ fatal_perror("udp (%s:%d): fcntl(set FD_CLOEXEC)",
+ st->loc.file,st->loc.line);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family=AF_INET;
+ addr.sin_port=htons(st->port);
+ if (bind(st->fd, (struct sockaddr *)&addr, sizeof(addr))!=0) {
+ fatal_perror("udp (%s:%d): bind",st->loc.file,st->loc.line);
+ }
+
+ register_for_poll(st,udp_beforepoll,udp_afterpoll,1,"udp");
+}
+
static list_t *udp_apply(closure_t *self, struct cloc loc, dict_t *context,
list_t *args)
{
struct udp *st;
item_t *i;
dict_t *d;
- uint16_t local_port=0;
- struct sockaddr_in addr;
st=safe_malloc(sizeof(*st),"udp_apply(st)");
st->loc=loc;
st->ops.request_notify=request_notify;
st->ops.release_notify=release_notify;
st->ops.sendmsg=udp_sendmsg;
+ st->port=0;
i=list_elem(args,0);
if (!i || i->type!=t_dict) {
}
d=i->data.dict;
- local_port=dict_read_number(d,"port",False,"udp",st->loc,0);
+ st->port=dict_read_number(d,"port",True,"udp",st->loc,0);
st->rbuf=find_cl_if(d,"buffer",CL_BUFFER,True,"udp",st->loc);
- st->fd=socket(AF_INET, SOCK_DGRAM, 0);
- if (st->fd<0) {
- fatal_perror("udp_apply (%s:%d): socket",loc.file,loc.line);
- }
- if (fcntl(st->fd, F_SETFL, fcntl(st->fd, F_GETFL)|O_NONBLOCK)==-1) {
- fatal_perror("udp_apply (%s:%d): fcntl(set O_NONBLOCK)",
- loc.file,loc.line);
- }
- if (fcntl(st->fd, F_SETFD, FD_CLOEXEC)==-1) {
- fatal_perror("udp_apply (%s:%d): fcntl(set FD_CLOEXEC)",
- loc.file,loc.line);
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family=AF_INET;
- if (local_port) {
- addr.sin_port=htons(local_port);
- }
- if (bind(st->fd, (struct sockaddr *)&addr, sizeof(addr))!=0) {
- fatal_perror("udp_apply (%s:%d): bind",loc.file,loc.line);
- }
-
- register_for_poll(st,udp_beforepoll,udp_afterpoll,1,"udp");
+ add_hook(PHASE_GETRESOURCES,udp_phase_hook,st);
return new_closure(&st->cl);
}