From d51aa2819005a03e4cfb6f62333be6ccadfb3c06 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 26 Oct 2008 22:42:39 +0100 Subject: Implementation of MD5 authentication of BGP sessions. --- sysdep/linux/sysio.h | 21 +++++++++++++++ sysdep/unix/io.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) (limited to 'sysdep') diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h index 3a29cdc..b0aff71 100644 --- a/sysdep/linux/sysio.h +++ b/sysdep/linux/sysio.h @@ -139,3 +139,24 @@ static inline char *sysio_mcast_join(sock *s) #endif #endif + +#include +#include + +/* For the case that we have older kernel headers */ +/* Copied from Linux kernel file include/linux/tcp.h */ + +#ifndef TCP_MD5SIG + +#define TCP_MD5SIG 14 +#define TCP_MD5SIG_MAXKEYLEN 80 + +struct tcp_md5sig { + struct __kernel_sockaddr_storage tcpm_addr; /* address associated */ + __u16 __tcpm_pad1; /* zero */ + __u16 tcpm_keylen; /* key length */ + __u32 __tcpm_pad2; /* zero */ + __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */ +}; + +#endif diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 7dcca21..6faa176 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -546,6 +546,7 @@ sk_new(pool *p) s->err_hook = NULL; s->fd = -1; s->rbuf_alloc = s->tbuf_alloc = NULL; + s->password = NULL; return s; } @@ -642,6 +643,71 @@ bad: return err; } + +/* FIXME: check portability */ + +static int +sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd) +{ + struct tcp_md5sig md5; + + memset(&md5, 0, sizeof(md5)); + memcpy(&md5.tcpm_addr, (struct sockaddr *) sa, sizeof(*sa)); + + if (passwd) + { + int len = strlen(passwd); + + if (len > TCP_MD5SIG_MAXKEYLEN) + { + log(L_ERR "MD5 password too long"); + return -1; + } + + md5.tcpm_keylen = len; + memcpy(&md5.tcpm_key, passwd, len); + } + + int rv = setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &md5, sizeof(md5)); + + if (rv < 0) + { + if (errno == ENOPROTOOPT) + log(L_ERR "Kernel does not support TCP MD5 signatures"); + else + log(L_ERR "sk_set_md5_auth_int: setsockopt: %m"); + } + + return rv; +} + +/** + * sk_set_md5_auth - add / remove MD5 security association for given socket. + * @s: socket + * @a: IP address of the other side + * @passwd: password used for MD5 authentication + * + * In TCP MD5 handling code in kernel, there is a set of pairs + * (address, password) used to choose password according to + * address of the other side. This function is useful for + * listening socket, for active sockets it is enough to set + * s->password field. + * + * When called with passwd != NULL, the new pair is added, + * When called with passwd == NULL, the existing pair is removed. + * + * Result: 0 for success, -1 for an error. + */ + +int +sk_set_md5_auth(sock *s, ip_addr a, char *passwd) +{ + sockaddr sa; + fill_in_sockaddr(&sa, a, 0); + return sk_set_md5_auth_int(s, &sa, passwd); +} + + static void sk_tcp_connected(sock *s) { @@ -805,6 +871,14 @@ sk_open(sock *s) ERR("bind"); } fill_in_sockaddr(&sa, s->daddr, s->dport); + + if (s->password) + { + int rv = sk_set_md5_auth_int(s, &sa, s->password); + if (rv < 0) + goto bad_no_log; + } + switch (type) { case SK_TCP_ACTIVE: @@ -846,6 +920,7 @@ sk_open(sock *s) bad: log(L_ERR "sk_open: %s: %m", err); +bad_no_log: close(fd); s->fd = -1; return -1; -- cgit v1.2.3 From 1567edea8d3da7da08092eef15bb3bd4544c6464 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 26 Oct 2008 23:09:46 +0100 Subject: Bugfix for routing table breaking bug. Here is a patch fixing a bug that causes breakage of a local routing table during shutdown of Bird. The problem was caused by shutdown of 'device' protocol before shutdown of 'kernel' protocol. When 'device' protocol went down, the route (with local network prefix) From different protocol (BGP or OSPF) became preferred and installed to the kernel routing table. Such routes were broken (like 192.168.1.0/24 via 192.168.1.2). I think it is also the cause of problem reported by Martin Kraus. The patch disables updating of kernel routing table during shutdown of Bird. I am not sure whether this is the best way to fix it, I would prefer to forbid 'kernel' protocol to overwrite routes with 'proto kernel'. The patch also fixes a problem that during shutdown sometimes routes created by Bird remained in the kernel routing table. --- sysdep/linux/netlink/netlink.c | 9 ++++----- sysdep/unix/krt-set.c | 2 ++ sysdep/unix/krt.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'sysdep') diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c index a70428e..98c63f0 100644 --- a/sysdep/linux/netlink/netlink.c +++ b/sysdep/linux/netlink/netlink.c @@ -498,6 +498,8 @@ nl_send_route(struct krt_proto *p, rte *e, int new) nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw); break; case RTD_DEVICE: + if (!a->iface) + return; r.r.rtm_type = RTN_UNICAST; nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index); break; @@ -531,11 +533,8 @@ krt_set_notify(struct krt_proto *p, net *n UNUSED, rte *new, rte *old) else { if (old) - { - if (!old->attrs->iface || (old->attrs->iface->flags & IF_UP)) - nl_send_route(p, old, 0); - /* else the kernel has already flushed it */ - } + nl_send_route(p, old, 0); + if (new) nl_send_route(p, new, 1); } diff --git a/sysdep/unix/krt-set.c b/sysdep/unix/krt-set.c index bd56448..23cbe5c 100644 --- a/sysdep/unix/krt-set.c +++ b/sysdep/unix/krt-set.c @@ -61,6 +61,8 @@ krt_ioctl(int ioc, rte *e, char *name) re.rt_flags |= RTF_GATEWAY; break; case RTD_DEVICE: + if (!a->iface) + return; re.rt_dev = a->iface->name; break; #ifdef RTF_REJECT diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index a6d1727..5269eb7 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -684,7 +684,7 @@ krt_notify(struct proto *P, net *net, rte *new, rte *old, struct ea_list *attrs { struct krt_proto *p = (struct krt_proto *) P; - if (shutting_down && KRT_CF->persist) + if (shutting_down) return; if (new && (!krt_capable(new) || new->attrs->source == RTS_INHERIT)) new = NULL; -- cgit v1.2.3