mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Merge branch 'master' into int-new
This commit is contained in:
@@ -104,15 +104,29 @@ rip_iface_start:
|
||||
|
||||
rip_iface_finish:
|
||||
{
|
||||
/* Default mode is broadcast for RIPv1, multicast for RIPv2 and RIPng */
|
||||
if (!RIP_IFACE->mode)
|
||||
RIP_IFACE->mode = (rip_cfg_is_v2() && (RIP_IFACE->version == RIP_V1)) ?
|
||||
RIP_IM_BROADCAST : RIP_IM_MULTICAST;
|
||||
|
||||
RIP_IFACE->passwords = get_passwords();
|
||||
|
||||
if (!RIP_IFACE->auth_type != !RIP_IFACE->passwords)
|
||||
log(L_WARN "Authentication and password options should be used together");
|
||||
|
||||
/* Default mode is broadcast for RIPv1, multicast for RIPv2 and RIPng */
|
||||
if (!RIP_IFACE->mode)
|
||||
RIP_IFACE->mode = (rip_cfg_is_v2() && (RIP_IFACE->version == RIP_V1)) ?
|
||||
RIP_IM_BROADCAST : RIP_IM_MULTICAST;
|
||||
if (RIP_IFACE->passwords)
|
||||
{
|
||||
struct password_item *pass;
|
||||
WALK_LIST(pass, *RIP_IFACE->passwords)
|
||||
{
|
||||
if (pass->alg && (RIP_IFACE->auth_type != RIP_AUTH_CRYPTO))
|
||||
cf_error("Password algorithm option requires cryptographic authentication");
|
||||
|
||||
/* Set default crypto algorithm (MD5) */
|
||||
if (!pass->alg && (RIP_IFACE->auth_type == RIP_AUTH_CRYPTO))
|
||||
pass->alg = ALG_MD5;
|
||||
}
|
||||
}
|
||||
|
||||
RIP_CFG->min_timeout_time = MIN_(RIP_CFG->min_timeout_time, RIP_IFACE->timeout_time);
|
||||
RIP_CFG->max_garbage_time = MAX_(RIP_CFG->max_garbage_time, RIP_IFACE->garbage_time);
|
||||
@@ -153,7 +167,7 @@ rip_auth:
|
||||
NONE { $$ = RIP_AUTH_NONE; }
|
||||
| PLAINTEXT { $$ = RIP_AUTH_PLAIN; }
|
||||
| CRYPTOGRAPHIC { $$ = RIP_AUTH_CRYPTO; }
|
||||
| MD5 { $$ = RIP_AUTH_CRYPTO; }
|
||||
| MD5 { $$ = RIP_AUTH_CRYPTO; } /* For backward compatibility */
|
||||
;
|
||||
|
||||
rip_iface_opts:
|
||||
|
@@ -12,16 +12,14 @@
|
||||
#undef LOCAL_DEBUG
|
||||
|
||||
#include "rip.h"
|
||||
#include "lib/md5.h"
|
||||
#include "lib/mac.h"
|
||||
|
||||
|
||||
#define RIP_CMD_REQUEST 1 /* want info */
|
||||
#define RIP_CMD_RESPONSE 2 /* responding to request */
|
||||
|
||||
#define RIP_BLOCK_LENGTH 20
|
||||
|
||||
#define RIP_PASSWD_LENGTH 16
|
||||
#define RIP_MD5_LENGTH 16
|
||||
|
||||
#define RIP_AF_IPV4 2
|
||||
#define RIP_AF_AUTH 0xffff
|
||||
@@ -74,7 +72,7 @@ struct rip_auth_tail
|
||||
{
|
||||
u16 must_be_ffff;
|
||||
u16 must_be_0001;
|
||||
byte auth_data[];
|
||||
byte auth_data[0];
|
||||
};
|
||||
|
||||
/* Internal representation of RTE block data */
|
||||
@@ -132,7 +130,7 @@ rip_put_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
|
||||
}
|
||||
|
||||
static inline void
|
||||
rip_put_next_hop(struct rip_proto *p, byte *pos, struct rip_block *rte)
|
||||
rip_put_next_hop(struct rip_proto *p UNUSED, byte *pos, struct rip_block *rte)
|
||||
{
|
||||
struct rip_block_ng *block = (void *) pos;
|
||||
block->prefix = ip6_hton(ipa_to_ip6(rte->next_hop));
|
||||
@@ -221,16 +219,24 @@ rip_fill_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_p
|
||||
auth->auth_type = htons(RIP_AUTH_CRYPTO);
|
||||
auth->packet_len = htons(*plen);
|
||||
auth->key_id = pass->id;
|
||||
auth->auth_len = sizeof(struct rip_auth_tail) + RIP_MD5_LENGTH;
|
||||
auth->auth_len = mac_type_length(pass->alg);
|
||||
auth->seq_num = ifa->csn_ready ? htonl(ifa->csn) : 0;
|
||||
auth->unused1 = 0;
|
||||
auth->unused2 = 0;
|
||||
ifa->csn_ready = 1;
|
||||
|
||||
if (pass->alg < ALG_HMAC)
|
||||
auth->auth_len += sizeof(struct rip_auth_tail);
|
||||
|
||||
/*
|
||||
* Note that RFC 4822 is unclear whether auth_len should cover whole
|
||||
* authentication trailer or just auth_data length.
|
||||
*
|
||||
* FIXME: We should use just auth_data length by default. Currently we put
|
||||
* the whole auth trailer length in keyed hash case to keep old behavior,
|
||||
* but we put just auth_data length in the new HMAC case. Note that Quagga
|
||||
* has config option for this.
|
||||
*
|
||||
* Crypto sequence numbers are increased by sender in rip_update_csn().
|
||||
* First CSN should be zero, this is handled by csn_ready.
|
||||
*/
|
||||
@@ -238,14 +244,18 @@ rip_fill_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_p
|
||||
struct rip_auth_tail *tail = (void *) ((byte *) pkt + *plen);
|
||||
tail->must_be_ffff = htons(0xffff);
|
||||
tail->must_be_0001 = htons(0x0001);
|
||||
strncpy(tail->auth_data, pass->password, RIP_MD5_LENGTH);
|
||||
|
||||
*plen += sizeof(struct rip_auth_tail) + RIP_MD5_LENGTH;
|
||||
uint auth_len = mac_type_length(pass->alg);
|
||||
*plen += sizeof(struct rip_auth_tail) + auth_len;
|
||||
|
||||
struct md5_context ctx;
|
||||
md5_init(&ctx);
|
||||
md5_update(&ctx, (byte *) pkt, *plen);
|
||||
memcpy(tail->auth_data, md5_final(&ctx), RIP_MD5_LENGTH);
|
||||
/* Append key for keyed hash, append padding for HMAC (RFC 4822 2.5) */
|
||||
if (pass->alg < ALG_HMAC)
|
||||
strncpy(tail->auth_data, pass->password, auth_len);
|
||||
else
|
||||
memset32(tail->auth_data, HMAC_MAGIC, auth_len / 4);
|
||||
|
||||
mac_fill(pass->alg, pass->password, pass->length,
|
||||
(byte *) pkt, *plen, tail->auth_data);
|
||||
return;
|
||||
|
||||
default:
|
||||
@@ -288,13 +298,25 @@ rip_check_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_
|
||||
DROP("no suitable password found", auth->key_id);
|
||||
|
||||
uint data_len = ntohs(auth->packet_len);
|
||||
uint auth_len = sizeof(struct rip_auth_tail) + RIP_MD5_LENGTH;
|
||||
uint auth_len = mac_type_length(pass->alg);
|
||||
uint auth_len2 = sizeof(struct rip_auth_tail) + auth_len;
|
||||
|
||||
if (data_len + auth_len != *plen)
|
||||
DROP("packet length mismatch", data_len);
|
||||
/*
|
||||
* Ideally, first check should be check for internal consistency:
|
||||
* (data_len + sizeof(struct rip_auth_tail) + auth->auth_len) != *plen
|
||||
*
|
||||
* Second one should check expected code length:
|
||||
* auth->auth_len != auth_len
|
||||
*
|
||||
* But as auth->auth_len has two interpretations, we simplify this
|
||||
*/
|
||||
|
||||
if ((auth->auth_len != RIP_MD5_LENGTH) && (auth->auth_len != auth_len))
|
||||
DROP("authentication data length mismatch", auth->auth_len);
|
||||
if (data_len + auth_len2 != *plen)
|
||||
DROP("packet length mismatch", *plen);
|
||||
|
||||
/* Warning: two interpretations of auth_len field */
|
||||
if ((auth->auth_len != auth_len) && (auth->auth_len != auth_len2))
|
||||
DROP("wrong authentication length", auth->auth_len);
|
||||
|
||||
struct rip_auth_tail *tail = (void *) ((byte *) pkt + data_len);
|
||||
if ((tail->must_be_ffff != htons(0xffff)) || (tail->must_be_0001 != htons(0x0001)))
|
||||
@@ -312,17 +334,18 @@ rip_check_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_
|
||||
return 0;
|
||||
}
|
||||
|
||||
char received[RIP_MD5_LENGTH];
|
||||
memcpy(received, tail->auth_data, RIP_MD5_LENGTH);
|
||||
strncpy(tail->auth_data, pass->password, RIP_MD5_LENGTH);
|
||||
byte *auth_data = alloca(auth_len);
|
||||
memcpy(auth_data, tail->auth_data, auth_len);
|
||||
|
||||
struct md5_context ctx;
|
||||
md5_init(&ctx);
|
||||
md5_update(&ctx, (byte *) pkt, *plen);
|
||||
char *computed = md5_final(&ctx);
|
||||
/* Append key for keyed hash, append padding for HMAC (RFC 4822 2.5) */
|
||||
if (pass->alg < ALG_HMAC)
|
||||
strncpy(tail->auth_data, pass->password, auth_len);
|
||||
else
|
||||
memset32(tail->auth_data, HMAC_MAGIC, auth_len / 4);
|
||||
|
||||
if (memcmp(received, computed, RIP_MD5_LENGTH))
|
||||
DROP("wrong MD5 digest", pass->id);
|
||||
if (!mac_verify(pass->alg, pass->password, pass->length,
|
||||
(byte *) pkt, *plen, auth_data))
|
||||
DROP("wrong authentication code", pass->id);
|
||||
|
||||
*plen = data_len;
|
||||
n->csn = rcv_csn;
|
||||
@@ -632,7 +655,7 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
|
||||
}
|
||||
|
||||
static int
|
||||
rip_rx_hook(sock *sk, int len)
|
||||
rip_rx_hook(sock *sk, uint len)
|
||||
{
|
||||
struct rip_iface *ifa = sk->data;
|
||||
struct rip_proto *p = ifa->rip;
|
||||
|
@@ -575,7 +575,7 @@ rip_iface_update_buffers(struct rip_iface *ifa)
|
||||
ifa->tx_plen = tbsize - headers;
|
||||
|
||||
if (ifa->cf->auth_type == RIP_AUTH_CRYPTO)
|
||||
ifa->tx_plen -= RIP_AUTH_TAIL_LENGTH;
|
||||
ifa->tx_plen -= RIP_AUTH_TAIL_LENGTH + max_mac_length(ifa->cf->passwords);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -687,12 +687,11 @@ rip_reconfigure_iface(struct rip_proto *p, struct rip_iface *ifa, struct rip_ifa
|
||||
|
||||
ifa->cf = new;
|
||||
|
||||
rip_iface_update_buffers(ifa);
|
||||
|
||||
if (ifa->next_regular > (now + new->update_time))
|
||||
ifa->next_regular = now + (random() % new->update_time) + 1;
|
||||
|
||||
if ((new->tx_length != old->tx_length) || (new->rx_buffer != old->rx_buffer))
|
||||
rip_iface_update_buffers(ifa);
|
||||
|
||||
if (new->check_link != old->check_link)
|
||||
rip_iface_update_state(ifa);
|
||||
|
||||
@@ -1011,7 +1010,7 @@ rip_prepare_attrs(struct linpool *pool, ea_list *next, u8 metric, u16 tag)
|
||||
}
|
||||
|
||||
static int
|
||||
rip_import_control(struct proto *P, struct rte **rt, struct ea_list **attrs, struct linpool *pool)
|
||||
rip_import_control(struct proto *P UNUSED, struct rte **rt, struct ea_list **attrs, struct linpool *pool)
|
||||
{
|
||||
/* Prepare attributes with initial values */
|
||||
if ((*rt)->attrs->source != RTS_RIP)
|
||||
@@ -1145,7 +1144,7 @@ rip_reconfigure(struct proto *P, struct proto_config *CF)
|
||||
}
|
||||
|
||||
static void
|
||||
rip_get_route_info(rte *rte, byte *buf, ea_list *attrs)
|
||||
rip_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
|
||||
{
|
||||
buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric);
|
||||
|
||||
|
@@ -34,7 +34,7 @@
|
||||
#define RIP_NG_PORT 521 /* RIPng */
|
||||
|
||||
#define RIP_MAX_PKT_LENGTH 532 /* 512 + IP4_HEADER_LENGTH */
|
||||
#define RIP_AUTH_TAIL_LENGTH 20 /* 4 + MD5 length */
|
||||
#define RIP_AUTH_TAIL_LENGTH 4 /* Without auth_data */
|
||||
|
||||
#define RIP_DEFAULT_ECMP_LIMIT 16
|
||||
#define RIP_DEFAULT_INFINITY 16
|
||||
|
Reference in New Issue
Block a user