-/* $OpenBSD: bgpd.c,v 1.268 2024/09/30 09:42:24 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.269 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
pftable_clear_all();
RB_FOREACH(p, peer_head, &conf->peers)
- pfkey_remove(p);
+ pfkey_remove(&p->auth_state);
while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
&p->conf, sizeof(p->conf)) == -1)
return (-1);
+ if (pfkey_send_conf(ibuf_se, p->conf.id, &p->auth_conf) == -1)
+ return (-1);
if (p->reconf_action == RECONF_REINIT)
- if (pfkey_establish(p) == -1)
+ if (pfkey_establish(&p->auth_state, &p->auth_conf,
+ session_localaddr(p), &p->conf.remote_addr) == -1)
log_peer_warnx(&p->conf, "pfkey setup failed");
}
}
p = getpeerbyid(conf, imsg_get_id(&imsg));
if (p != NULL) {
- if (pfkey_establish(p) == -1)
+ if (pfkey_establish(&p->auth_state,
+ &p->auth_conf, session_localaddr(p),
+ &p->conf.remote_addr) == -1)
log_peer_warnx(&p->conf,
"pfkey setup failed");
}
-/* $OpenBSD: bgpd.h,v 1.496 2024/09/04 15:06:36 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.497 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
AUTH_EALG_AES,
};
-struct peer_auth {
+struct auth_config {
char md5key[TCP_MD5_KEY_LEN];
char auth_key_in[IPSEC_AUTH_KEY_LEN];
char auth_key_out[IPSEC_AUTH_KEY_LEN];
struct bgpd_addr remote_addr;
struct bgpd_addr local_addr_v4;
struct bgpd_addr local_addr_v6;
- struct peer_auth auth;
struct capabilities capabilities;
struct addpath_eval eval;
char group[PEER_DESCR_LEN];
IMSG_RECONF_CONF,
IMSG_RECONF_RIB,
IMSG_RECONF_PEER,
+ IMSG_RECONF_PEER_AUTH,
IMSG_RECONF_FILTER,
IMSG_RECONF_LISTENER,
IMSG_RECONF_CTRL,
-/* $OpenBSD: config.c,v 1.111 2024/09/04 13:30:10 claudio Exp $ */
+/* $OpenBSD: config.c,v 1.112 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
np = getpeerbyid(conf, p->conf.id);
if (np != NULL) {
np->reconf_action = RECONF_KEEP;
- /* copy the auth state since parent uses it */
- np->auth = p->auth;
+ /* keep the auth state since parent needs it */
+ np->auth_state = p->auth_state;
RB_REMOVE(peer_head, &xconf->peers, p);
free(p);
RB_FOREACH_SAFE(p, peer_head, &conf->peers, nextp) {
if (p->reconf_action == RECONF_DELETE) {
/* peer no longer exists, clear pfkey state */
- pfkey_remove(p);
+ pfkey_remove(&p->auth_state);
RB_REMOVE(peer_head, &conf->peers, p);
free(p);
}
-/* $OpenBSD: control.c,v 1.118 2024/08/20 11:59:39 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.119 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
/* special handling for peers since only the stats are sent from RDE */
if (type == IMSG_CTL_SHOW_NEIGHBOR) {
struct rde_peer_stats stats;
+ struct peer peer;
if (p == NULL) {
log_warnx("%s: no such peer: id=%u", __func__,
log_warnx("%s: imsg_get_data", __func__);
return (0);
}
- p->stats.prefix_cnt = stats.prefix_cnt;
- p->stats.prefix_out_cnt = stats.prefix_out_cnt;
- p->stats.prefix_rcvd_update = stats.prefix_rcvd_update;
- p->stats.prefix_rcvd_withdraw = stats.prefix_rcvd_withdraw;
- p->stats.prefix_rcvd_eor = stats.prefix_rcvd_eor;
- p->stats.prefix_sent_update = stats.prefix_sent_update;
- p->stats.prefix_sent_withdraw = stats.prefix_sent_withdraw;
- p->stats.prefix_sent_eor = stats.prefix_sent_eor;
- p->stats.pending_update = stats.pending_update;
- p->stats.pending_withdraw = stats.pending_withdraw;
- p->stats.msg_queue_len = msgbuf_queuelen(&p->wbuf);
+ peer = *p;
+ explicit_bzero(&peer.auth_conf, sizeof(peer.auth_conf));
+ peer.stats.prefix_cnt = stats.prefix_cnt;
+ peer.stats.prefix_out_cnt = stats.prefix_out_cnt;
+ peer.stats.prefix_rcvd_update = stats.prefix_rcvd_update;
+ peer.stats.prefix_rcvd_withdraw = stats.prefix_rcvd_withdraw;
+ peer.stats.prefix_rcvd_eor = stats.prefix_rcvd_eor;
+ peer.stats.prefix_sent_update = stats.prefix_sent_update;
+ peer.stats.prefix_sent_withdraw = stats.prefix_sent_withdraw;
+ peer.stats.prefix_sent_eor = stats.prefix_sent_eor;
+ peer.stats.pending_update = stats.pending_update;
+ peer.stats.pending_withdraw = stats.pending_withdraw;
+ peer.stats.msg_queue_len = msgbuf_queuelen(&p->wbuf);
return imsg_compose(&c->imsgbuf, type, 0, pid, -1,
- p, sizeof(*p));
+ &peer, sizeof(peer));
}
/* if command finished no need to send exit message */
-/* $OpenBSD: parse.y,v 1.468 2024/09/20 02:00:46 jsg Exp $ */
+/* $OpenBSD: parse.y,v 1.469 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
curpeer->conf.max_out_prefix_restart = $4;
}
| TCP MD5SIG PASSWORD string {
- if (curpeer->conf.auth.method) {
+ if (curpeer->auth_conf.method) {
yyerror("auth method cannot be redefined");
free($4);
YYERROR;
}
- if (strlcpy(curpeer->conf.auth.md5key, $4,
- sizeof(curpeer->conf.auth.md5key)) >=
- sizeof(curpeer->conf.auth.md5key)) {
+ if (strlcpy(curpeer->auth_conf.md5key, $4,
+ sizeof(curpeer->auth_conf.md5key)) >=
+ sizeof(curpeer->auth_conf.md5key)) {
yyerror("tcp md5sig password too long: max %zu",
- sizeof(curpeer->conf.auth.md5key) - 1);
+ sizeof(curpeer->auth_conf.md5key) - 1);
free($4);
YYERROR;
}
- curpeer->conf.auth.method = AUTH_MD5SIG;
- curpeer->conf.auth.md5key_len = strlen($4);
+ curpeer->auth_conf.method = AUTH_MD5SIG;
+ curpeer->auth_conf.md5key_len = strlen($4);
free($4);
}
| TCP MD5SIG KEY string {
- if (curpeer->conf.auth.method) {
+ if (curpeer->auth_conf.method) {
yyerror("auth method cannot be redefined");
free($4);
YYERROR;
}
- if (str2key($4, curpeer->conf.auth.md5key,
- sizeof(curpeer->conf.auth.md5key)) == -1) {
+ if (str2key($4, curpeer->auth_conf.md5key,
+ sizeof(curpeer->auth_conf.md5key)) == -1) {
free($4);
YYERROR;
}
- curpeer->conf.auth.method = AUTH_MD5SIG;
- curpeer->conf.auth.md5key_len = strlen($4) / 2;
+ curpeer->auth_conf.method = AUTH_MD5SIG;
+ curpeer->auth_conf.md5key_len = strlen($4) / 2;
free($4);
}
| IPSEC espah IKE {
- if (curpeer->conf.auth.method) {
+ if (curpeer->auth_conf.method) {
yyerror("auth method cannot be redefined");
YYERROR;
}
if ($2)
- curpeer->conf.auth.method = AUTH_IPSEC_IKE_ESP;
+ curpeer->auth_conf.method = AUTH_IPSEC_IKE_ESP;
else
- curpeer->conf.auth.method = AUTH_IPSEC_IKE_AH;
+ curpeer->auth_conf.method = AUTH_IPSEC_IKE_AH;
}
| IPSEC espah inout SPI NUMBER STRING STRING encspec {
enum auth_alg auth_alg;
uint8_t keylen;
- if (curpeer->conf.auth.method &&
- (((curpeer->conf.auth.spi_in && $3 == 1) ||
- (curpeer->conf.auth.spi_out && $3 == 0)) ||
- ($2 == 1 && curpeer->conf.auth.method !=
+ if (curpeer->auth_conf.method &&
+ (((curpeer->auth_conf.spi_in && $3 == 1) ||
+ (curpeer->auth_conf.spi_out && $3 == 0)) ||
+ ($2 == 1 && curpeer->auth_conf.method !=
AUTH_IPSEC_MANUAL_ESP) ||
- ($2 == 0 && curpeer->conf.auth.method !=
+ ($2 == 0 && curpeer->auth_conf.method !=
AUTH_IPSEC_MANUAL_AH))) {
yyerror("auth method cannot be redefined");
free($6);
}
if ($2)
- curpeer->conf.auth.method =
+ curpeer->auth_conf.method =
AUTH_IPSEC_MANUAL_ESP;
else {
if ($8.enc_alg) {
free($7);
YYERROR;
}
- curpeer->conf.auth.method =
+ curpeer->auth_conf.method =
AUTH_IPSEC_MANUAL_AH;
}
}
if ($3 == 1) {
- if (str2key($7, curpeer->conf.auth.auth_key_in,
- sizeof(curpeer->conf.auth.auth_key_in)) ==
+ if (str2key($7, curpeer->auth_conf.auth_key_in,
+ sizeof(curpeer->auth_conf.auth_key_in)) ==
-1) {
free($7);
YYERROR;
}
- curpeer->conf.auth.spi_in = $5;
- curpeer->conf.auth.auth_alg_in = auth_alg;
- curpeer->conf.auth.enc_alg_in = $8.enc_alg;
- memcpy(&curpeer->conf.auth.enc_key_in,
+ curpeer->auth_conf.spi_in = $5;
+ curpeer->auth_conf.auth_alg_in = auth_alg;
+ curpeer->auth_conf.enc_alg_in = $8.enc_alg;
+ memcpy(&curpeer->auth_conf.enc_key_in,
&$8.enc_key,
- sizeof(curpeer->conf.auth.enc_key_in));
- curpeer->conf.auth.enc_keylen_in =
+ sizeof(curpeer->auth_conf.enc_key_in));
+ curpeer->auth_conf.enc_keylen_in =
$8.enc_key_len;
- curpeer->conf.auth.auth_keylen_in = keylen;
+ curpeer->auth_conf.auth_keylen_in = keylen;
} else {
- if (str2key($7, curpeer->conf.auth.auth_key_out,
- sizeof(curpeer->conf.auth.auth_key_out)) ==
+ if (str2key($7, curpeer->auth_conf.auth_key_out,
+ sizeof(curpeer->auth_conf.auth_key_out)) ==
-1) {
free($7);
YYERROR;
}
- curpeer->conf.auth.spi_out = $5;
- curpeer->conf.auth.auth_alg_out = auth_alg;
- curpeer->conf.auth.enc_alg_out = $8.enc_alg;
- memcpy(&curpeer->conf.auth.enc_key_out,
+ curpeer->auth_conf.spi_out = $5;
+ curpeer->auth_conf.auth_alg_out = auth_alg;
+ curpeer->auth_conf.enc_alg_out = $8.enc_alg;
+ memcpy(&curpeer->auth_conf.enc_key_out,
&$8.enc_key,
- sizeof(curpeer->conf.auth.enc_key_out));
- curpeer->conf.auth.enc_keylen_out =
+ sizeof(curpeer->auth_conf.enc_key_out));
+ curpeer->auth_conf.enc_keylen_out =
$8.enc_key_len;
- curpeer->conf.auth.auth_keylen_out = keylen;
+ curpeer->auth_conf.auth_keylen_out = keylen;
}
free($7);
}
}
/* with any form of ipsec local-address is required */
- if ((p->conf.auth.method == AUTH_IPSEC_IKE_ESP ||
- p->conf.auth.method == AUTH_IPSEC_IKE_AH ||
- p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP ||
- p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) &&
+ if ((p->auth_conf.method == AUTH_IPSEC_IKE_ESP ||
+ p->auth_conf.method == AUTH_IPSEC_IKE_AH ||
+ p->auth_conf.method == AUTH_IPSEC_MANUAL_ESP ||
+ p->auth_conf.method == AUTH_IPSEC_MANUAL_AH) &&
local_addr->aid == AID_UNSPEC) {
yyerror("neighbors with any form of IPsec configured "
"need local-address to be specified");
}
/* with static keying we need both directions */
- if ((p->conf.auth.method == AUTH_IPSEC_MANUAL_ESP ||
- p->conf.auth.method == AUTH_IPSEC_MANUAL_AH) &&
- (!p->conf.auth.spi_in || !p->conf.auth.spi_out)) {
+ if ((p->auth_conf.method == AUTH_IPSEC_MANUAL_ESP ||
+ p->auth_conf.method == AUTH_IPSEC_MANUAL_AH) &&
+ (!p->auth_conf.spi_in || !p->auth_conf.spi_out)) {
yyerror("with manual keyed IPsec, SPIs and keys "
"for both directions are required");
return (-1);
-/* $OpenBSD: pfkey.c,v 1.68 2022/11/07 22:39:13 mbuhl Exp $ */
+/* $OpenBSD: pfkey.c,v 1.69 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
static uint32_t pid = 0; /* should pid_t but pfkey needs uint32_t */
static int pfkey_fd;
-int pfkey_reply(int, uint32_t *);
-int pfkey_send(int, uint8_t, uint8_t, uint8_t,
- struct bgpd_addr *, struct bgpd_addr *,
- uint32_t, uint8_t, int, char *, uint8_t, int, char *,
- uint16_t, uint16_t);
+static int pfkey_reply(int, uint32_t *);
+static int pfkey_send(int, uint8_t, uint8_t, uint8_t,
+ const struct bgpd_addr *, const struct bgpd_addr *,
+ uint32_t, uint8_t, int, char *, uint8_t, int, char *,
+ uint16_t, uint16_t);
#define pfkey_flow(fd, satype, cmd, dir, from, to, sport, dport) \
pfkey_send(fd, satype, cmd, dir, from, to, \
0, 0, 0, NULL, 0, 0, NULL, sport, dport)
-static struct bgpd_addr *
-pfkey_localaddr(struct peer *p)
-{
- switch (p->conf.remote_addr.aid) {
- case AID_INET:
- return &p->conf.local_addr_v4;
- case AID_INET6:
- return &p->conf.local_addr_v6;
- }
- fatalx("Unknown AID in pfkey_localaddr");
-}
-
-int
+static int
pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
- struct bgpd_addr *src, struct bgpd_addr *dst, uint32_t spi,
+ const struct bgpd_addr *src, const struct bgpd_addr *dst, uint32_t spi,
uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey,
uint16_t sport, uint16_t dport)
{
return (1);
}
-int
+static int
pfkey_reply(int sd, uint32_t *spi)
{
struct sadb_msg hdr, *msg;
}
static int
-pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, uint8_t keylen,
- char *key, uint32_t *spi)
+pfkey_sa_add(const struct bgpd_addr *src, const struct bgpd_addr *dst,
+ uint8_t keylen, char *key, uint32_t *spi)
{
if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0,
src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
}
static int
-pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, uint32_t *spi)
+pfkey_sa_remove(const struct bgpd_addr *src, const struct bgpd_addr *dst,
+ uint32_t *spi)
{
if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0,
src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
}
static int
-pfkey_md5sig_establish(struct peer *p)
+pfkey_md5sig_establish(struct auth_state *as, struct auth_config *auth,
+ const struct bgpd_addr *local_addr, const struct bgpd_addr *remote_addr)
{
uint32_t spi_out = 0;
uint32_t spi_in = 0;
- if (pfkey_sa_add(pfkey_localaddr(p), &p->conf.remote_addr,
- p->conf.auth.md5key_len, p->conf.auth.md5key,
- &spi_out) == -1)
+ if (pfkey_sa_add(local_addr, remote_addr,
+ auth->md5key_len, auth->md5key, &spi_out) == -1)
goto fail;
- if (pfkey_sa_add(&p->conf.remote_addr, pfkey_localaddr(p),
- p->conf.auth.md5key_len, p->conf.auth.md5key,
- &spi_in) == -1)
+ if (pfkey_sa_add(remote_addr, local_addr,
+ auth->md5key_len, auth->md5key, &spi_in) == -1)
goto fail;
/* cleanup old flow if one was present */
- if (p->auth.established) {
- if (pfkey_remove(p) == -1)
+ if (as->established) {
+ if (pfkey_remove(as) == -1)
return (-1);
}
- p->auth.established = 1;
- p->auth.spi_out = spi_out;
- p->auth.spi_in = spi_in;
+ as->established = 1;
+ as->method = auth->method;
+ as->local_addr = *local_addr;
+ as->remote_addr = *remote_addr;
+ as->spi_out = spi_out;
+ as->spi_in = spi_in;
return (0);
fail:
- log_peer_warn(&p->conf, "failed to insert md5sig");
return (-1);
}
static int
-pfkey_md5sig_remove(struct peer *p)
+pfkey_md5sig_remove(struct auth_state *as)
{
- if (p->auth.spi_out)
- if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
- &p->auth.spi_out) == -1)
+ if (as->spi_out)
+ if (pfkey_sa_remove(&as->local_addr, &as->remote_addr,
+ &as->spi_out) == -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)
+ if (as->spi_in)
+ if (pfkey_sa_remove(&as->remote_addr, &as->local_addr,
+ &as->spi_in) == -1)
goto fail;
- p->auth.established = 0;
- p->auth.spi_out = 0;
- p->auth.spi_in = 0;
+ explicit_bzero(as, sizeof(*as));
return (0);
fail:
- log_peer_warn(&p->conf, "failed to remove md5sig");
return (-1);
}
}
static int
-pfkey_ipsec_establish(struct peer *p)
+pfkey_ipsec_establish(struct auth_state *as, struct auth_config *auth,
+ const struct bgpd_addr *local_addr, const struct bgpd_addr *remote_addr)
{
uint8_t satype = SADB_SATYPE_ESP;
- struct bgpd_addr *local_addr = pfkey_localaddr(p);
/* cleanup first, unlike in the TCP MD5 case */
- if (p->auth.established) {
- if (pfkey_remove(p) == -1)
+ if (as->established) {
+ if (pfkey_remove(as) == -1)
return (-1);
}
- switch (p->auth.method) {
+ switch (auth->method) {
case AUTH_IPSEC_IKE_ESP:
satype = SADB_SATYPE_ESP;
break;
break;
case AUTH_IPSEC_MANUAL_ESP:
case AUTH_IPSEC_MANUAL_AH:
- satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
+ satype = auth->method == AUTH_IPSEC_MANUAL_ESP ?
SADB_SATYPE_ESP : SADB_SATYPE_AH;
if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
- local_addr, &p->conf.remote_addr,
- p->conf.auth.spi_out,
- pfkey_auth_alg(p->conf.auth.auth_alg_out),
- p->conf.auth.auth_keylen_out,
- p->conf.auth.auth_key_out,
- pfkey_enc_alg(p->conf.auth.enc_alg_out),
- p->conf.auth.enc_keylen_out,
- p->conf.auth.enc_key_out,
+ local_addr, remote_addr,
+ auth->spi_out,
+ pfkey_auth_alg(auth->auth_alg_out),
+ auth->auth_keylen_out,
+ auth->auth_key_out,
+ pfkey_enc_alg(auth->enc_alg_out),
+ auth->enc_keylen_out,
+ auth->enc_key_out,
0, 0) == -1)
goto fail_key;
if (pfkey_reply(pfkey_fd, NULL) == -1)
goto fail_key;
if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
- &p->conf.remote_addr, local_addr,
- p->conf.auth.spi_in,
- pfkey_auth_alg(p->conf.auth.auth_alg_in),
- p->conf.auth.auth_keylen_in,
- p->conf.auth.auth_key_in,
- pfkey_enc_alg(p->conf.auth.enc_alg_in),
- p->conf.auth.enc_keylen_in,
- p->conf.auth.enc_key_in,
+ remote_addr, local_addr,
+ auth->spi_in,
+ pfkey_auth_alg(auth->auth_alg_in),
+ auth->auth_keylen_in,
+ auth->auth_key_in,
+ pfkey_enc_alg(auth->enc_alg_in),
+ auth->enc_keylen_in,
+ auth->enc_key_in,
0, 0) == -1)
goto fail_key;
if (pfkey_reply(pfkey_fd, NULL) == -1)
}
if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
- local_addr, &p->conf.remote_addr, 0, BGP_PORT) == -1)
+ local_addr, remote_addr, 0, BGP_PORT) == -1)
goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) == -1)
goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
- local_addr, &p->conf.remote_addr, BGP_PORT, 0) == -1)
+ local_addr, remote_addr, BGP_PORT, 0) == -1)
goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) == -1)
goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
- &p->conf.remote_addr, local_addr, 0, BGP_PORT) == -1)
+ remote_addr, local_addr, 0, BGP_PORT) == -1)
goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) == -1)
goto fail_flow;
if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
- &p->conf.remote_addr, local_addr, BGP_PORT, 0) == -1)
+ remote_addr, local_addr, BGP_PORT, 0) == -1)
goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) == -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;
+ as->established = 1;
+ as->method = auth->method;
+ as->local_addr = *local_addr;
+ as->remote_addr = *remote_addr;
+ as->spi_in = auth->spi_in;
+ as->spi_out = auth->spi_out;
return (0);
fail_key:
- log_peer_warn(&p->conf, "failed to insert ipsec key");
+ log_warn("failed to insert ipsec key");
return (-1);
fail_flow:
- log_peer_warn(&p->conf, "failed to insert ipsec flow");
+ log_warn("failed to insert ipsec flow");
return (-1);
}
static int
-pfkey_ipsec_remove(struct peer *p)
+pfkey_ipsec_remove(struct auth_state *as)
{
uint8_t satype;
- switch (p->auth.method) {
+ switch (as->method) {
case AUTH_IPSEC_IKE_ESP:
satype = SADB_SATYPE_ESP;
break;
break;
case AUTH_IPSEC_MANUAL_ESP:
case AUTH_IPSEC_MANUAL_AH:
- satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
+ satype = as->method == AUTH_IPSEC_MANUAL_ESP ?
SADB_SATYPE_ESP : SADB_SATYPE_AH;
if (pfkey_send(pfkey_fd, satype, SADB_DELETE, 0,
- &p->auth.local_addr, &p->conf.remote_addr,
- p->auth.spi_out, 0, 0, NULL, 0, 0, NULL,
- 0, 0) == -1)
+ &as->local_addr, &as->remote_addr,
+ as->spi_out, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
goto fail_key;
if (pfkey_reply(pfkey_fd, NULL) == -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) == -1)
+ &as->remote_addr, &as->local_addr,
+ as->spi_in, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
goto fail_key;
if (pfkey_reply(pfkey_fd, NULL) == -1)
goto fail_key;
}
if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
- &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) == -1)
+ &as->local_addr, &as->remote_addr, 0, BGP_PORT) == -1)
goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) == -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) == -1)
+ &as->local_addr, &as->remote_addr, BGP_PORT, 0) == -1)
goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) == -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) == -1)
+ &as->remote_addr, &as->local_addr, 0, BGP_PORT) == -1)
goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) == -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) == -1)
+ &as->remote_addr, &as->local_addr, BGP_PORT, 0) == -1)
goto fail_flow;
if (pfkey_reply(pfkey_fd, NULL) == -1)
goto fail_flow;
- p->auth.established = 0;
- p->auth.spi_out = 0;
- p->auth.spi_in = 0;
+ explicit_bzero(as, sizeof(*as));
return (0);
fail_key:
- log_peer_warn(&p->conf, "failed to remove ipsec key");
+ log_warn("failed to remove ipsec key");
return (-1);
fail_flow:
- log_peer_warn(&p->conf, "failed to remove ipsec flow");
+ log_warn("failed to remove ipsec flow");
return (-1);
}
int
-pfkey_establish(struct peer *p)
+pfkey_establish(struct auth_state *as, struct auth_config *auth,
+ const struct bgpd_addr *local_addr, const struct bgpd_addr *remote_addr)
{
int rv;
- switch (p->conf.auth.method) {
+ switch (auth->method) {
case AUTH_NONE:
rv = 0;
- if (p->auth.established)
- rv = pfkey_remove(p);
+ if (as->established)
+ rv = pfkey_remove(as);
break;
case AUTH_MD5SIG:
- rv = pfkey_md5sig_establish(p);
+ rv = pfkey_md5sig_establish(as, auth, local_addr, remote_addr);
break;
default:
- rv = pfkey_ipsec_establish(p);
+ rv = pfkey_ipsec_establish(as, auth, local_addr, remote_addr);
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, SPI are
- * handled by the method specific functions.
- */
- memcpy(&p->auth.local_addr, pfkey_localaddr(p),
- sizeof(p->auth.local_addr));
- p->auth.method = p->conf.auth.method;
-
return (rv);
}
int
-pfkey_remove(struct peer *p)
+pfkey_remove(struct auth_state *as)
{
- if (p->auth.established == 0)
+ if (as->established == 0)
return (0);
- switch (p->auth.method) {
+ switch (as->method) {
case AUTH_NONE:
return (0);
case AUTH_MD5SIG:
- return (pfkey_md5sig_remove(p));
+ return (pfkey_md5sig_remove(as));
default:
- return (pfkey_ipsec_remove(p));
+ return (pfkey_ipsec_remove(as));
}
}
return (pfkey_fd);
}
+int
+pfkey_send_conf(struct imsgbuf *imsgbuf, uint32_t id, struct auth_config *auth)
+{
+ /* SE only needs the auth method */
+ return imsg_compose(imsgbuf, IMSG_RECONF_PEER_AUTH, id, 0, -1,
+ &auth->method, sizeof(auth->method));
+}
+
+int
+pfkey_recv_conf(struct peer *p, struct imsg *imsg)
+{
+ struct auth_config *auth = &p->auth_conf;
+
+ return imsg_get_data(imsg, &auth->method, sizeof(auth->method));
+}
+
/* verify that connection is using TCP MD5UM if required by config */
int
-tcp_md5_check(int fd, struct peer *p)
+tcp_md5_check(int fd, struct auth_config *auth)
{
socklen_t len;
int opt;
- if (p->conf.auth.method == AUTH_MD5SIG) {
+ if (auth->method == AUTH_MD5SIG) {
if (sysdep.no_md5sig) {
- log_peer_warnx(&p->conf,
- "md5sig configured but not available");
+ errno = ENOPROTOOPT;
return -1;
}
len = sizeof(opt);
if (getsockopt(fd, IPPROTO_TCP, TCP_MD5SIG,
&opt, &len) == -1)
- fatal("getsockopt TCP_MD5SIG");
+ return -1;
if (!opt) { /* non-md5'd connection! */
- log_peer_warnx(&p->conf,
- "connection attempt without md5 signature");
+ errno = ECONNREFUSED;
return -1;
}
}
/* enable or set TCP MD5SIG on a new client connection */
int
-tcp_md5_set(int fd, struct peer *p)
+tcp_md5_set(int fd, struct auth_config *auth, struct bgpd_addr *remote_addr)
{
int opt = 1;
- if (p->conf.auth.method == AUTH_MD5SIG) {
+ if (auth->method == AUTH_MD5SIG) {
if (sysdep.no_md5sig) {
- log_peer_warnx(&p->conf,
- "md5sig configured but not available");
+ errno = ENOPROTOOPT;
return -1;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG,
- &opt, sizeof(opt)) == -1) {
- log_peer_warn(&p->conf, "setsockopt md5sig");
+ &opt, sizeof(opt)) == -1)
return -1;
- }
}
return 0;
}
-/* $OpenBSD: printconf.c,v 1.174 2024/08/14 19:09:51 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.175 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
void print_roa(struct roa_tree *);
void print_aspa(struct aspa_tree *);
void print_rtrs(struct rtr_config_head *);
-void print_peer(struct peer_config *, struct bgpd_config *,
- const char *);
+void print_peer(struct peer *, struct bgpd_config *, const char *);
const char *print_auth_alg(enum auth_alg);
const char *print_enc_alg(enum auth_enc_alg);
void print_announce(struct peer_config *, const char *);
}
void
-print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c)
+print_peer(struct peer *peer, struct bgpd_config *conf, const char *c)
{
- char *method;
- struct in_addr ina;
+ struct in_addr ina;
+ char *method;
+ struct peer_config *p = &peer->conf;
+ struct auth_config *auth = &peer->auth_conf;
if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) ||
(p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128))
if (p->flags & PEERFLAG_LOG_UPDATES)
printf("%s\tlog updates\n", c);
- if (p->auth.method == AUTH_MD5SIG)
+ if (auth->method == AUTH_MD5SIG)
printf("%s\ttcp md5sig\n", c);
- else if (p->auth.method == AUTH_IPSEC_MANUAL_ESP ||
- p->auth.method == AUTH_IPSEC_MANUAL_AH) {
- if (p->auth.method == AUTH_IPSEC_MANUAL_ESP)
+ else if (auth->method == AUTH_IPSEC_MANUAL_ESP ||
+ auth->method == AUTH_IPSEC_MANUAL_AH) {
+ if (auth->method == AUTH_IPSEC_MANUAL_ESP)
method = "esp";
else
method = "ah";
printf("%s\tipsec %s in spi %u %s XXXXXX", c, method,
- p->auth.spi_in, print_auth_alg(p->auth.auth_alg_in));
- if (p->auth.enc_alg_in)
- printf(" %s XXXXXX", print_enc_alg(p->auth.enc_alg_in));
+ auth->spi_in, print_auth_alg(auth->auth_alg_in));
+ if (auth->enc_alg_in)
+ printf(" %s XXXXXX", print_enc_alg(auth->enc_alg_in));
printf("\n");
printf("%s\tipsec %s out spi %u %s XXXXXX", c, method,
- p->auth.spi_out, print_auth_alg(p->auth.auth_alg_out));
- if (p->auth.enc_alg_out)
+ auth->spi_out, print_auth_alg(auth->auth_alg_out));
+ if (auth->enc_alg_out)
printf(" %s XXXXXX",
- print_enc_alg(p->auth.enc_alg_out));
+ print_enc_alg(auth->enc_alg_out));
printf("\n");
- } else if (p->auth.method == AUTH_IPSEC_IKE_AH)
+ } else if (auth->method == AUTH_IPSEC_IKE_AH)
printf("%s\tipsec ah ike\n", c);
- else if (p->auth.method == AUTH_IPSEC_IKE_ESP)
+ else if (auth->method == AUTH_IPSEC_IKE_ESP)
printf("%s\tipsec esp ike\n", c);
if (p->ttlsec)
void
print_groups(struct bgpd_config *conf)
{
- struct peer_config **peerlist;
- struct peer *p;
- u_int peer_cnt, i;
- uint32_t prev_groupid;
- const char *tab = "\t";
- const char *nada = "";
- const char *c;
+ struct peer **peerlist;
+ struct peer *p;
+ u_int peer_cnt, i;
+ uint32_t prev_groupid;
+ const char *c;
peer_cnt = 0;
RB_FOREACH(p, peer_head, &conf->peers)
peer_cnt++;
-
- if ((peerlist = calloc(peer_cnt, sizeof(struct peer_config *))) == NULL)
+ if ((peerlist = calloc(peer_cnt, sizeof(*peerlist))) == NULL)
fatal("print_groups calloc");
-
i = 0;
RB_FOREACH(p, peer_head, &conf->peers)
- peerlist[i++] = &p->conf;
+ peerlist[i++] = p;
- qsort(peerlist, peer_cnt, sizeof(struct peer_config *), peer_compare);
+ qsort(peerlist, peer_cnt, sizeof(*peerlist), peer_compare);
prev_groupid = 0;
for (i = 0; i < peer_cnt; i++) {
- if (peerlist[i]->groupid) {
- c = tab;
- if (peerlist[i]->groupid != prev_groupid) {
+ if (peerlist[i]->conf.groupid) {
+ c = "\t";
+ if (peerlist[i]->conf.groupid != prev_groupid) {
if (prev_groupid)
printf("}\n\n");
- printf("group \"%s\" {\n", peerlist[i]->group);
- prev_groupid = peerlist[i]->groupid;
+ printf("group \"%s\" {\n",
+ peerlist[i]->conf.group);
+ prev_groupid = peerlist[i]->conf.groupid;
}
} else
- c = nada;
+ c = "";
print_peer(peerlist[i], conf, c);
}
int
peer_compare(const void *aa, const void *bb)
{
- const struct peer_config * const *a;
- const struct peer_config * const *b;
+ const struct peer * const *a;
+ const struct peer * const *b;
a = aa;
b = bb;
- return ((*a)->groupid - (*b)->groupid);
+ return ((*a)->conf.groupid - (*b)->conf.groupid);
}
void
-/* $OpenBSD: session.c,v 1.482 2024/09/09 12:59:49 claudio Exp $ */
+/* $OpenBSD: session.c,v 1.483 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
}
open:
- if (p->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) {
+ if (p->auth_conf.method != AUTH_NONE && sysdep.no_pfkey) {
log_peer_warnx(&p->conf,
"ipsec or md5sig configured but not available");
close(connfd);
return;
}
- if (tcp_md5_check(connfd, p) == -1) {
+ if (tcp_md5_check(connfd, &p->auth_conf) == -1) {
+ log_peer_warn(&p->conf, "check md5sig");
close(connfd);
return;
}
session_connect(struct peer *peer)
{
struct sockaddr *sa;
- struct bgpd_addr *bind_addr = NULL;
+ struct bgpd_addr *bind_addr;
socklen_t sa_len;
/*
return (-1);
}
- if (peer->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) {
+ if (peer->auth_conf.method != AUTH_NONE && sysdep.no_pfkey) {
log_peer_warnx(&peer->conf,
"ipsec or md5sig configured but not available");
bgp_fsm(peer, EVNT_CON_OPENFAIL);
return (-1);
}
- tcp_md5_set(peer->fd, peer);
+ if (tcp_md5_set(peer->fd, &peer->auth_conf,
+ &peer->conf.remote_addr) == -1)
+ log_peer_warn(&peer->conf, "setting md5sig");
peer->wbuf.fd = peer->fd;
/* if local-address is set we need to bind() */
- switch (peer->conf.remote_addr.aid) {
- case AID_INET:
- bind_addr = &peer->conf.local_addr_v4;
- break;
- case AID_INET6:
- bind_addr = &peer->conf.local_addr_v6;
- break;
- }
+ bind_addr = session_localaddr(peer);
if ((sa = addr2sa(bind_addr, 0, &sa_len)) != NULL) {
if (bind(peer->fd, sa, sa_len) == -1) {
log_peer_warn(&peer->conf, "session_connect bind");
if (RB_INSERT(peer_head, &nconf->peers, p) != NULL)
fatalx("%s: peer tree is corrupt", __func__);
break;
+ case IMSG_RECONF_PEER_AUTH:
+ if (idx != PFD_PIPE_MAIN)
+ fatalx("reconf request not from parent");
+ if ((p = getpeerbyid(nconf, peerid)) == NULL) {
+ log_warnx("no such peer: id=%u", peerid);
+ break;
+ }
+ if (pfkey_recv_conf(p, &imsg) == -1)
+ fatal("pfkey_recv_conf");
+ break;
case IMSG_RECONF_LISTENER:
if (idx != PFD_PIPE_MAIN)
fatalx("reconf request not from parent");
bgp_fsm(peer, EVNT_STOP);
}
+struct bgpd_addr *
+session_localaddr(struct peer *p)
+{
+ switch (p->conf.remote_addr.aid) {
+ case AID_INET:
+ return &p->conf.local_addr_v4;
+ case AID_INET6:
+ return &p->conf.local_addr_v6;
+ }
+ fatalx("Unknown AID in %s", __func__);
+}
+
void
merge_peers(struct bgpd_config *c, struct bgpd_config *nc)
{
}
/* peer no longer uses TCP MD5SIG so deconfigure */
- if (p->conf.auth.method == AUTH_MD5SIG &&
- np->conf.auth.method != AUTH_MD5SIG)
+ if (p->auth_conf.method == AUTH_MD5SIG &&
+ np->auth_conf.method != AUTH_MD5SIG)
tcp_md5_del_listener(c, p);
- else if (np->conf.auth.method == AUTH_MD5SIG)
+ else if (np->auth_conf.method == AUTH_MD5SIG)
tcp_md5_add_listener(c, np);
memcpy(&p->conf, &np->conf, sizeof(p->conf));
RB_REMOVE(peer_head, &nc->peers, np);
if (RB_INSERT(peer_head, &c->peers, np) != NULL)
fatalx("%s: peer tree is corrupt", __func__);
- if (np->conf.auth.method == AUTH_MD5SIG)
+ if (np->auth_conf.method == AUTH_MD5SIG)
tcp_md5_add_listener(c, np);
}
}
-/* $OpenBSD: session.h,v 1.173 2024/09/04 13:30:10 claudio Exp $ */
+/* $OpenBSD: session.h,v 1.174 2024/10/01 11:49:24 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
char last_reason[REASON_LEN];
};
+struct auth_state {
+ struct bgpd_addr local_addr;
+ struct bgpd_addr remote_addr;
+ uint32_t spi_in;
+ uint32_t spi_out;
+ enum auth_method method;
+ uint8_t established;
+};
+
enum Timer {
Timer_None,
Timer_ConnectRetry,
struct capabilities peer;
struct capabilities neg;
} capa;
- struct {
- struct bgpd_addr local_addr;
- uint32_t spi_in;
- uint32_t spi_out;
- enum auth_method method;
- uint8_t established;
- } auth;
+ struct auth_state auth_state;
+ struct auth_config auth_conf;
struct bgpd_addr local;
struct bgpd_addr local_alt;
struct bgpd_addr remote;
/* pfkey.c */
struct sadb_msg;
int pfkey_read(int, struct sadb_msg *);
-int pfkey_establish(struct peer *);
-int pfkey_remove(struct peer *);
+int pfkey_establish(struct auth_state *, struct auth_config *,
+ const struct bgpd_addr *, const struct bgpd_addr *);
+int pfkey_remove(struct auth_state *);
int pfkey_init(void);
-int tcp_md5_check(int, struct peer *);
-int tcp_md5_set(int, struct peer *);
+int pfkey_send_conf(struct imsgbuf *, uint32_t, struct auth_config *);
+int pfkey_recv_conf(struct peer *, struct imsg *);
+int tcp_md5_check(int, struct auth_config *);
+int tcp_md5_set(int, struct auth_config *, struct bgpd_addr *);
int tcp_md5_prep_listener(struct listen_addr *, struct peer_head *);
void tcp_md5_add_listener(struct bgpd_config *, struct peer *);
void tcp_md5_del_listener(struct bgpd_config *, struct peer *);
int imsg_ctl_rde(struct imsg *);
int imsg_ctl_rde_msg(int, uint32_t, pid_t);
void session_stop(struct peer *, uint8_t, const char *);
+struct bgpd_addr *session_localaddr(struct peer *);
/* timer.c */
struct timer *timer_get(struct timer_head *, enum Timer);