summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nest/config.Y8
-rw-r--r--proto/ospf/config.Y18
-rw-r--r--proto/ospf/ospf.h3
-rw-r--r--proto/ospf/packet.c30
4 files changed, 47 insertions, 12 deletions
diff --git a/nest/config.Y b/nest/config.Y
index 48940ff..e843777 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -22,7 +22,13 @@ static list *this_p_list;
static struct password_item *this_p_item;
static int password_id;
-static list *
+static inline void
+reset_passwords(void)
+{
+ this_p_list = NULL;
+}
+
+static inline list *
get_passwords(void)
{
list *rv = this_p_list;
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 00b6be7..bfe2d9c 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -19,6 +19,18 @@ static struct iface_patt *this_ipatt;
static struct nbma_node *this_nbma;
static struct area_net_config *this_pref;
+static void
+finish_iface_config(struct ospf_iface_patt *ip)
+{
+ ip->passwords = get_passwords();
+
+ if ((ip->autype == OSPF_AUTH_CRYPT) && (ip->helloint < 5))
+ log(L_WARN "Hello or poll interval less that 5 makes cryptographic authenication prone to replay attacks");
+
+ if ((ip->autype == OSPF_AUTH_NONE) && (ip->passwords != NULL))
+ log(L_WARN "Password option without authentication option does not make sense");
+}
+
CF_DECLS
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG)
@@ -83,7 +95,7 @@ ospf_area_item:
;
ospf_vlink:
- ospf_vlink_start '{' ospf_vlink_opts '}' { OSPF_PATT->passwords = get_passwords(); }
+ ospf_vlink_start '{' ospf_vlink_opts '}' { finish_iface_config(OSPF_PATT); }
| ospf_vlink_start
;
@@ -121,6 +133,7 @@ ospf_vlink_start: VIRTUAL LINK idval
OSPF_PATT->type = OSPF_IT_VLINK;
init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype = OSPF_AUTH_NONE;
+ reset_passwords();
}
;
@@ -223,6 +236,7 @@ ospf_iface_start:
OSPF_PATT->stub = 0;
init_list(&OSPF_PATT->nbma_list);
OSPF_PATT->autype = OSPF_AUTH_NONE;
+ reset_passwords();
}
;
@@ -237,7 +251,7 @@ ospf_iface_opt_list:
;
ospf_iface:
- ospf_iface_start iface_patt ospf_iface_opt_list { OSPF_PATT->passwords = get_passwords(); }
+ ospf_iface_start iface_patt ospf_iface_opt_list { finish_iface_config(OSPF_PATT); }
;
ospf_iface_list:
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 4e37c18..fb78af4 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -161,7 +161,8 @@ struct ospf_iface
u16 autype;
u16 helloint; /* number of seconds between hello sending */
list *passwords;
- u32 csn; /* Crypt seq num. that will be sent net */
+ u32 csn; /* Last used crypt seq number */
+ bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
ip_addr drip; /* Designated router */
u32 drid;
ip_addr bdrip; /* Backup DR */
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c
index c6b233f..23785fe 100644
--- a/proto/ospf/packet.c
+++ b/proto/ospf/packet.c
@@ -75,13 +75,25 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
pkt->checksum = 0;
+ /* Perhaps use random value to prevent replay attacks after
+ reboot when system does not have independent RTC? */
if (!ifa->csn)
- ifa->csn = (u32) time(NULL);
+ {
+ ifa->csn = (u32) now;
+ ifa->csn_use = now;
+ }
+
+ /* We must have sufficient delay between sending a packet and increasing
+ CSN to prevent reordering of packets (in a network) with different CSNs */
+ if ((now - ifa->csn_use) > 1)
+ ifa->csn++;
+
+ ifa->csn_use = now;
pkt->u.md5.keyid = passwd->id;
pkt->u.md5.len = OSPF_AUTH_CRYPT_SIZE;
pkt->u.md5.zero = 0;
- pkt->u.md5.csn = htonl(ifa->csn++);
+ pkt->u.md5.csn = htonl(ifa->csn);
tail = ((void *)pkt) + ntohs(pkt->length);
MD5Init(&ctxt);
MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
@@ -184,12 +196,14 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
if (n)
{
- if(ntohs(pkt->u.md5.csn) < n->csn)
- {
- OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number");
- return 0;
- }
- n->csn = ntohs(pkt->u.md5.csn);
+ u32 rcv_csn = ntohl(pkt->u.md5.csn);
+ if(rcv_csn < n->csn)
+ {
+ OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn);
+ return 0;
+ }
+
+ n->csn = rcv_csn;
}
MD5Init(&ctxt);