summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/bgpd.c6
-rw-r--r--usr.sbin/bgpd/config.c5
-rw-r--r--usr.sbin/bgpd/pfkey.c196
3 files changed, 128 insertions, 79 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index be8bec14fc4..f252a83781f 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.218 2019/05/27 09:14:32 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.219 2019/05/29 08:48:00 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -799,11 +799,9 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx, struct bgpd_config *conf)
log_warnx("pfkey reload: no such peer: id=%u",
imsg.hdr.peerid);
else {
- pfkey_remove(p);
- if (pfkey_establish(p) == -1) {
+ if (pfkey_establish(p) == -1)
log_peer_warnx(&p->conf,
"pfkey setup failed");
- }
}
break;
case IMSG_CTL_RELOAD:
diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c
index 845c0b59017..32057ec5d70 100644
--- a/usr.sbin/bgpd/config.c
+++ b/usr.sbin/bgpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.89 2019/05/27 09:14:32 claudio Exp $ */
+/* $OpenBSD: config.c,v 1.90 2019/05/29 08:48:00 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -322,6 +322,9 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf)
np->reconf_action = RECONF_KEEP;
/* copy the auth state since parent uses it */
np->auth = p->auth;
+ } else {
+ /* peer no longer exists, clear pfkey state */
+ pfkey_remove(p);
}
RB_REMOVE(peer_head, &xconf->peers, p);
diff --git a/usr.sbin/bgpd/pfkey.c b/usr.sbin/bgpd/pfkey.c
index 964559ddd2f..3db0ff0efae 100644
--- a/usr.sbin/bgpd/pfkey.c
+++ b/usr.sbin/bgpd/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.55 2019/05/08 12:41:55 claudio Exp $ */
+/* $OpenBSD: pfkey.c,v 1.56 2019/05/29 08:48:00 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -50,13 +50,6 @@ int pfkey_send(int, uint8_t, uint8_t, uint8_t,
struct bgpd_addr *, struct bgpd_addr *,
u_int32_t, uint8_t, int, char *, uint8_t, int, char *,
uint16_t, uint16_t);
-int pfkey_sa_add(struct bgpd_addr *, struct bgpd_addr *, u_int8_t, char *,
- u_int32_t *);
-int pfkey_sa_remove(struct bgpd_addr *, struct bgpd_addr *, u_int32_t *);
-int pfkey_md5sig_establish(struct peer *);
-int pfkey_md5sig_remove(struct peer *);
-int pfkey_ipsec_establish(struct peer *);
-int pfkey_ipsec_remove(struct peer *);
#define pfkey_flow(fd, satype, cmd, dir, from, to, sport, dport) \
pfkey_send(fd, satype, cmd, dir, from, to, \
@@ -404,7 +397,7 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
} while (n == -1 && (errno == EAGAIN || errno == EINTR));
if (n == -1) {
- log_warn("writev (%d/%d)", iov_cnt, len);
+ log_warn("%s: writev (%d/%d)", __func__, iov_cnt, len);
return (-1);
}
@@ -502,7 +495,7 @@ pfkey_reply(int sd, u_int32_t *spi)
return (0);
}
-int
+static int
pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen,
char *key, u_int32_t *spi)
{
@@ -519,7 +512,7 @@ pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen,
return (0);
}
-int
+static int
pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t *spi)
{
if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0,
@@ -531,47 +524,71 @@ pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t *spi)
return (0);
}
-int
+static int
pfkey_md5sig_establish(struct peer *p)
{
- sleep(1);
-
- if (!p->auth.spi_out)
- if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr,
- p->conf.auth.md5key_len, p->conf.auth.md5key,
- &p->auth.spi_out) == -1)
- return (-1);
- if (!p->auth.spi_in)
- if (pfkey_sa_add(&p->conf.remote_addr, &p->auth.local_addr,
- p->conf.auth.md5key_len, p->conf.auth.md5key,
- &p->auth.spi_in) == -1)
+ u_int32_t spi_out = 0;
+ u_int32_t spi_in = 0;
+
+ if (pfkey_sa_add(&p->conf.local_addr, &p->conf.remote_addr,
+ p->conf.auth.md5key_len, p->conf.auth.md5key,
+ &spi_out) == -1)
+ goto fail;
+
+ if (pfkey_sa_add(&p->conf.remote_addr, &p->conf.local_addr,
+ p->conf.auth.md5key_len, p->conf.auth.md5key,
+ &spi_in) == -1)
+ goto fail;
+
+ /* cleanup old flow if one was present */
+ if (p->auth.established) {
+ if (pfkey_remove(p) == -1)
return (-1);
+ }
p->auth.established = 1;
+ p->auth.spi_out = spi_out;
+ p->auth.spi_in = spi_in;
return (0);
+
+fail:
+ log_peer_warn(&p->conf, "%s: failed to insert md5sig", __func__);
+ return (-1);
}
-int
+static int
pfkey_md5sig_remove(struct peer *p)
{
if (p->auth.spi_out)
if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
&p->auth.spi_out) == -1)
- return (-1);
+ goto fail;
if (p->auth.spi_in)
if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
&p->auth.spi_in) == -1)
- return (-1);
+ goto fail;
p->auth.established = 0;
+ p->auth.spi_out = 0;
+ p->auth.spi_in = 0;
return (0);
+
+fail:
+ log_peer_warn(&p->conf, "%s: failed to remove md5sig", __func__);
+ return (-1);
}
-int
+static int
pfkey_ipsec_establish(struct peer *p)
{
uint8_t satype = SADB_SATYPE_ESP;
+ /* cleanup first, unlike in the TCP MD5 case */
+ if (p->auth.established) {
+ if (pfkey_remove(p) == -1)
+ return (-1);
+ }
+
switch (p->auth.method) {
case AUTH_IPSEC_IKE_ESP:
satype = SADB_SATYPE_ESP;
@@ -584,8 +601,8 @@ pfkey_ipsec_establish(struct peer *p)
satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
SADB_SATYPE_ESP : SADB_SATYPE_AH;
if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
- &p->auth.local_addr, &p->conf.remote_addr,
- p->auth.spi_out,
+ &p->conf.local_addr, &p->conf.remote_addr,
+ p->conf.auth.spi_out,
p->conf.auth.auth_alg_out,
p->conf.auth.auth_keylen_out,
p->conf.auth.auth_key_out,
@@ -593,12 +610,12 @@ pfkey_ipsec_establish(struct peer *p)
p->conf.auth.enc_keylen_out,
p->conf.auth.enc_key_out,
0, 0) < 0)
- return (-1);
+ goto fail_key;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_key;
if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
- &p->conf.remote_addr, &p->auth.local_addr,
- p->auth.spi_in,
+ &p->conf.remote_addr, &p->conf.local_addr,
+ p->conf.auth.spi_in,
p->conf.auth.auth_alg_in,
p->conf.auth.auth_keylen_in,
p->conf.auth.auth_key_in,
@@ -606,44 +623,53 @@ pfkey_ipsec_establish(struct peer *p)
p->conf.auth.enc_keylen_in,
p->conf.auth.enc_key_in,
0, 0) < 0)
- return (-1);
+ goto fail_key;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_key;
break;
default:
return (-1);
- break;
}
if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
- &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0)
- return (-1);
+ &p->conf.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0)
+ goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
- &p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0) < 0)
- return (-1);
+ &p->conf.local_addr, &p->conf.remote_addr, BGP_PORT, 0) < 0)
+ goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
- &p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT) < 0)
- return (-1);
+ &p->conf.remote_addr, &p->conf.local_addr, 0, BGP_PORT) < 0)
+ goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
- &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0)
- return (-1);
+ &p->conf.remote_addr, &p->conf.local_addr, BGP_PORT, 0) < 0)
+ goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_flow;
+ /* save SPI so that they can be removed later on */
+ p->auth.spi_in = p->conf.auth.spi_in;
+ p->auth.spi_out = p->conf.auth.spi_out;
p->auth.established = 1;
return (0);
+
+fail_key:
+ log_peer_warn(&p->conf, "%s: failed to insert ipsec key", __func__);
+ return (-1);
+fail_flow:
+ log_peer_warn(&p->conf, "%s: failed to insert flow", __func__);
+ return (-1);
}
-int
+static int
pfkey_ipsec_remove(struct peer *p)
{
uint8_t satype;
@@ -663,84 +689,106 @@ pfkey_ipsec_remove(struct peer *p)
&p->auth.local_addr, &p->conf.remote_addr,
p->auth.spi_out, 0, 0, NULL, 0, 0, NULL,
0, 0) < 0)
- return (-1);
+ goto fail_key;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_key;
if (pfkey_send(pfkey_fd, satype, SADB_DELETE, 0,
&p->conf.remote_addr, &p->auth.local_addr,
p->auth.spi_in, 0, 0, NULL, 0, 0, NULL,
0, 0) < 0)
- return (-1);
+ goto fail_key;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_key;
break;
default:
return (-1);
- break;
}
if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
&p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
&p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
&p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
&p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0)
- return (-1);
+ goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) < 0)
- return (-1);
+ goto fail_flow;
p->auth.established = 0;
+ p->auth.spi_out = 0;
+ p->auth.spi_in = 0;
return (0);
+
+fail_key:
+ log_peer_warn(&p->conf, "%s: failed to remove ipsec key", __func__);
+ return (-1);
+fail_flow:
+ log_peer_warn(&p->conf, "%s: failed to remove flow", __func__);
+ return (-1);
}
int
pfkey_establish(struct peer *p)
{
+ int rv;
+
+ switch (p->conf.auth.method) {
+ case AUTH_NONE:
+ rv = 0;
+ if (p->auth.established)
+ rv = pfkey_remove(p);
+ break;
+ case AUTH_MD5SIG:
+ rv = pfkey_md5sig_establish(p);
+ break;
+ default:
+ rv = pfkey_ipsec_establish(p);
+ break;
+ }
/*
* make sure we keep copies of everything we need to
* remove SAs and flows later again, even if the
* info in p->conf changed due to reload.
* We need: SPIs, method, local_addr, remote_addr.
- * remote_addr cannot change, so no copy.
+ * remote_addr cannot change, so no copy, SPI are
+ * handled by the method specific functions.
*/
memcpy(&p->auth.local_addr, &p->conf.local_addr,
sizeof(p->auth.local_addr));
p->auth.method = p->conf.auth.method;
- p->auth.spi_in = p->conf.auth.spi_in;
- p->auth.spi_out = p->conf.auth.spi_out;
- if (!p->auth.method)
- return (0);
- else if (p->auth.method == AUTH_MD5SIG)
- return (pfkey_md5sig_establish(p));
- else
- return (pfkey_ipsec_establish(p));
+ return (rv);
}
int
pfkey_remove(struct peer *p)
{
- if (!p->auth.established)
+ if (p->auth.established == 0)
+ return (0);
+
+ switch (p->auth.method) {
+ case AUTH_NONE:
return (0);
- else if (p->auth.method == AUTH_MD5SIG)
+ case AUTH_MD5SIG:
return (pfkey_md5sig_remove(p));
- else
+ default:
return (pfkey_ipsec_remove(p));
+ }
}
int