summaryrefslogtreecommitdiff
path: root/proto/babel/babel.c
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2021-06-06 15:22:59 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2021-06-06 16:28:18 +0200
commitb174cc0abc0a9d7e84cc6fae46d9e19b714fbcfb (patch)
tree8bb6d9099e7139a38634e230b8d7ec003cba298d /proto/babel/babel.c
parentb218a28f61e1e9a93c3a4f2e180590f85df62e79 (diff)
Babel: Add MAC authentication support - update
Some cleanups and bugfixes to the previous patch, including: - Fix rate limiting in index mismatch check - Fix missing BABEL_AUTH_INDEX_LEN in auth_tx_overhead computation - Fix missing auth_tx_overhead recalculation during reconfiguration - Fix pseudoheader construction in babel_auth_sign() (sport vs fport) - Fix typecasts for ptrdiffs in log messages - Make auth log messages similar to corresponding RIP/OSPF ones - Change auth log messages for events that happen during regular operation to debug messages - Switch meaning of babel_auth_check*() functions for consistency with corresponding RIP/OSPF ones - Remove requirement for min/max key length, only those required by given MAC code are enforced
Diffstat (limited to 'proto/babel/babel.c')
-rw-r--r--proto/babel/babel.c100
1 files changed, 59 insertions, 41 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 82ba7da1..c322acb6 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1428,94 +1428,113 @@ babel_auth_init_neighbor(struct babel_neighbor *n)
}
static void
-babel_auth_send_challenge(struct babel_iface *ifa, struct babel_neighbor *n)
+babel_auth_send_challenge_request(struct babel_iface *ifa, struct babel_neighbor *n)
{
struct babel_proto *p = ifa->proto;
union babel_msg msg = {};
- TRACE(D_PACKETS, "Sending AUTH challenge to %I on %s",
+ TRACE(D_PACKETS, "Sending challenge request to %I on %s",
n->addr, ifa->ifname);
random_bytes(n->auth_nonce, BABEL_AUTH_NONCE_LEN);
n->auth_nonce_expiry = current_time() + BABEL_AUTH_CHALLENGE_TIMEOUT;
n->auth_next_challenge = current_time() + BABEL_AUTH_CHALLENGE_INTERVAL;
- msg.type = BABEL_TLV_CHALLENGE_REQ;
+ msg.type = BABEL_TLV_CHALLENGE_REQUEST;
msg.challenge.nonce_len = BABEL_AUTH_NONCE_LEN;
msg.challenge.nonce = n->auth_nonce;
babel_send_unicast(&msg, ifa, n->addr);
}
+static void
+babel_auth_send_challenge_reply(struct babel_iface *ifa, struct babel_neighbor *n, struct babel_msg_auth *rcv)
+{
+ struct babel_proto *p = ifa->proto;
+ union babel_msg msg = {};
+
+ TRACE(D_PACKETS, "Sending challenge reply to %I on %s",
+ n->addr, ifa->ifname);
+
+ n->auth_next_challenge_reply = current_time() + BABEL_AUTH_CHALLENGE_INTERVAL;
+
+ msg.type = BABEL_TLV_CHALLENGE_REPLY;
+ msg.challenge.nonce_len = rcv->challenge_len;
+ msg.challenge.nonce = rcv->challenge;
+
+ babel_send_unicast(&msg, ifa, n->addr);
+}
+
int
babel_auth_check_pc(struct babel_iface *ifa, struct babel_msg_auth *msg)
{
struct babel_proto *p = ifa->proto;
struct babel_neighbor *n;
- TRACE(D_PACKETS, "Handling MAC check from %I on %s",
- msg->sender, ifa->ifname);
-
- /* We create the neighbour entry at this point because it makes it easier to
+ /*
+ * We create the neighbour entry at this point because it makes it easier to
* rate limit challenge replies; this is explicitly allowed by the spec (see
- * Section 4.3).
+ * Section 4.3).
*/
n = babel_get_neighbor(ifa, msg->sender);
- if (msg->challenge_seen && n->auth_next_challenge_reply <= current_time())
- {
- union babel_msg resp = {};
- TRACE(D_PACKETS, "Sending MAC challenge response to %I", msg->sender);
- resp.type = BABEL_TLV_CHALLENGE_REPLY;
- resp.challenge.nonce_len = msg->challenge_len;
- resp.challenge.nonce = msg->challenge;
- n->auth_next_challenge_reply = current_time() + BABEL_AUTH_CHALLENGE_INTERVAL;
- babel_send_unicast(&resp, ifa, msg->sender);
- }
+ /* (3b) Handle challenge request */
+ if (msg->challenge_seen && (n->auth_next_challenge_reply <= current_time()))
+ babel_auth_send_challenge_reply(ifa, n, msg);
- if (msg->index_len > BABEL_AUTH_INDEX_LEN || !msg->pc_seen)
+ /* (4a) If PC TLV is missing, drop the packet */
+ if (!msg->pc_seen)
{
- LOG_PKT_AUTH("Invalid index or no PC from %I on %s",
+ LOG_PKT_AUTH("Authentication failed for %I on %s - missing or invalid PC",
msg->sender, ifa->ifname);
- return 1;
+ return 0;
}
- /* On successful challenge, update PC and index to current values */
+ /* (4b) On successful challenge, update PC and index to current values */
if (msg->challenge_reply_seen &&
- n->auth_nonce_expiry &&
- n->auth_nonce_expiry >= current_time() &&
+ (n->auth_nonce_expiry > current_time()) &&
!memcmp(msg->challenge_reply, n->auth_nonce, BABEL_AUTH_NONCE_LEN))
{
n->auth_index_len = msg->index_len;
memcpy(n->auth_index, msg->index, msg->index_len);
+
n->auth_pc = msg->pc;
+ n->auth_expiry = current_time() + BABEL_AUTH_NEIGHBOR_TIMEOUT;
+ n->auth_passed = 1;
+
+ return 1;
}
- /* If index differs, send challenge */
- if ((n->auth_index_len != msg->index_len ||
- memcmp(n->auth_index, msg->index, msg->index_len)) &&
- n->auth_next_challenge <= current_time())
+ /* (5) If index differs, send challenge and drop the packet */
+ if ((n->auth_index_len != msg->index_len) ||
+ memcmp(n->auth_index, msg->index, msg->index_len))
{
- LOG_PKT_AUTH("Index mismatch from %I on %s; sending challenge",
- msg->sender, ifa->ifname);
- babel_auth_send_challenge(ifa, n);
- return 1;
+ TRACE(D_PACKETS, "Index mismatch for packet from %I via %s",
+ msg->sender, ifa->ifname);
+
+ if (n->auth_next_challenge <= current_time())
+ babel_auth_send_challenge_request(ifa, n);
+
+ return 0;
}
- /* Index matches; only accept if PC is greater than last */
+ /* (6) Index matches; only accept if PC is greater than last */
if (n->auth_pc >= msg->pc)
{
- LOG_PKT_AUTH("Packet counter too low from %I on %s",
- msg->sender, ifa->ifname);
- return 1;
+ LOG_PKT_AUTH("Authentication failed for %I on %s - "
+ "lower packet counter (rcv %u, old %u)",
+ msg->sender, ifa->ifname, msg->pc, n->auth_pc);
+ return 0;
}
n->auth_pc = msg->pc;
n->auth_expiry = current_time() + BABEL_AUTH_NEIGHBOR_TIMEOUT;
n->auth_passed = 1;
- return 0;
+
+ return 1;
}
+
/*
* Babel interfaces
*/
@@ -1854,7 +1873,9 @@ babel_reconfigure_iface(struct babel_proto *p, struct babel_iface *ifa, struct b
ifa->next_hop_ip4 = ipa_nonzero(new->next_hop_ip4) ? new->next_hop_ip4 : addr4;
ifa->next_hop_ip6 = ipa_nonzero(new->next_hop_ip6) ? new->next_hop_ip6 : ifa->addr;
- if (new->auth_type != BABEL_AUTH_NONE && old->auth_type != new->auth_type)
+ babel_iface_update_buffers(ifa);
+
+ if ((new->auth_type != BABEL_AUTH_NONE) && (new->auth_type != old->auth_type))
babel_auth_reset_index(ifa);
if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
@@ -1866,9 +1887,6 @@ babel_reconfigure_iface(struct babel_proto *p, struct babel_iface *ifa, struct b
if (ifa->next_regular > (current_time() + new->update_interval))
ifa->next_regular = current_time() + (random() % new->update_interval);
- if ((new->tx_length != old->tx_length) || (new->rx_buffer != old->rx_buffer))
- babel_iface_update_buffers(ifa);
-
if (new->check_link != old->check_link)
babel_iface_update_state(ifa);