From 01ad6d9f8461fc2c0c12089971b1b053188ce72c Mon Sep 17 00:00:00 2001 From: damien Date: Sat, 2 Aug 2008 08:20:16 +0000 Subject: [PATCH] Drop frames that are received unencrypted when WEP is on or when WPA is on and RX protection for TA is on. Keep track of the TX/RX protection for each node when WPA is on. tested by djm@ (ral+wpa), ckuethe@ (ath-noenc) and krw@ (wpi<->ral+wpa). hints from bluhm@ has been in snaps for a few days. pointed out by bluhm@ something like 1 year ago but we did not have the right infrastructure to fix it properly at that time. ok deraadt@ --- sys/net80211/ieee80211_input.c | 30 ++++++++++++++++++++---------- sys/net80211/ieee80211_node.c | 5 ++++- sys/net80211/ieee80211_node.h | 8 ++++++-- sys/net80211/ieee80211_output.c | 8 +++++--- sys/net80211/ieee80211_pae_input.c | 9 ++++++++- 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index a9d0c146bd8..9e69f369c06 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_input.c,v 1.87 2008/07/28 19:42:13 damien Exp $ */ +/* $OpenBSD: ieee80211_input.c,v 1.88 2008/08/02 08:20:16 damien Exp $ */ /*- * Copyright (c) 2001 Atsushi Onoe @@ -331,22 +331,31 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni, goto out; } - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - if (ic->ic_flags & - (IEEE80211_F_WEPON | IEEE80211_F_RSNON)) { + if ((ic->ic_flags & IEEE80211_F_WEPON) || + ((ic->ic_flags & IEEE80211_F_RSNON) && + (ni->ni_flags & IEEE80211_NODE_RXPROT))) { + /* protection is on for Rx */ + if (!(rxi->rxi_flags & IEEE80211_RXI_HWDEC)) { + if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) { + /* drop unencrypted */ + ic->ic_stats.is_rx_unencrypted++; + goto err; + } + /* do software decryption */ m = ieee80211_decrypt(ic, m, ni); if (m == NULL) { ic->ic_stats.is_rx_wepfail++; goto err; } wh = mtod(m, struct ieee80211_frame *); - } else { - ic->ic_stats.is_rx_nowep++; - goto out; } - } else if (!(rxi->rxi_flags & IEEE80211_RXI_HWDEC)) { - /* XXX */ + } else if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) || + (rxi->rxi_flags & IEEE80211_RXI_HWDEC)) { + /* frame encrypted but protection off for Rx */ + ic->ic_stats.is_rx_nowep++; + goto out; } + #if NBPFILTER > 0 /* copy to listener after decrypt */ if (ic->ic_rawbpf) @@ -361,7 +370,8 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni, } eh = mtod(m, struct ether_header *); - if ((ic->ic_flags & IEEE80211_F_RSNON) && !ni->ni_port_valid && + if ((ic->ic_flags & IEEE80211_F_RSNON) && + !ni->ni_port_valid && eh->ether_type != htons(ETHERTYPE_PAE)) { DPRINTF(("port not valid: %s\n", ether_sprintf(wh->i_addr2))); diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index ef2404910b3..dfbcde24ab2 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_node.c,v 1.37 2008/07/28 19:42:13 damien Exp $ */ +/* $OpenBSD: ieee80211_node.c,v 1.38 2008/08/02 08:20:16 damien Exp $ */ /* $NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $ */ /*- @@ -329,6 +329,7 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan) * multicast frames using the group key we've just configured. */ ni->ni_port_valid = 1; + ni->ni_flags |= IEEE80211_NODE_TXPROT; /* schedule a GTK rekeying after 3600s */ timeout_add(&ic->ic_rsn_timeout, 3600 * hz); @@ -1086,6 +1087,7 @@ ieee80211_node_join_rsn(struct ieee80211com *ic, struct ieee80211_node *ni) ni->ni_key_count = 0; ni->ni_port_valid = 0; + ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT; ni->ni_replaycnt = -1; /* XXX */ ni->ni_rsn_retries = 0; ni->ni_rsncipher = ni->ni_rsnciphers; @@ -1222,6 +1224,7 @@ ieee80211_node_leave_rsn(struct ieee80211com *ic, struct ieee80211_node *ni) timeout_del(&ni->ni_rsn_timeout); ni->ni_rsn_retries = 0; + ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT; ni->ni_port_valid = 0; (*ic->ic_delete_key)(ic, ni, &ni->ni_pairwise_key); } diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index ab37a300429..581697897dc 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_node.h,v 1.28 2008/07/27 18:24:01 damien Exp $ */ +/* $OpenBSD: ieee80211_node.h,v 1.29 2008/08/02 08:20:16 damien Exp $ */ /* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */ /*- @@ -181,7 +181,11 @@ struct ieee80211_node { u_int8_t ni_flags; /* special-purpose state */ #define IEEE80211_NODE_ERP 0x01 #define IEEE80211_NODE_QOS 0x02 -#define IEEE80211_NODE_REKEY 0x04 +#define IEEE80211_NODE_REKEY 0x04 /* GTK rekying in progress */ +#define IEEE80211_NODE_RXPROT 0x08 /* RX protection ON */ +#define IEEE80211_NODE_TXPROT 0x10 /* TX protection ON */ +#define IEEE80211_NODE_TXRXPROT \ + (IEEE80211_NODE_TXPROT | IEEE80211_NODE_RXPROT) }; RB_HEAD(ieee80211_tree, ieee80211_node); diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 7ed7b2b9d00..982d7664143 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_output.c,v 1.63 2008/07/27 14:21:15 damien Exp $ */ +/* $OpenBSD: ieee80211_output.c,v 1.64 2008/08/02 08:20:16 damien Exp $ */ /* $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $ */ /*- @@ -501,7 +501,8 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni) goto bad; } - if ((ic->ic_flags & IEEE80211_F_RSNON) && !ni->ni_port_valid && + if ((ic->ic_flags & IEEE80211_F_RSNON) && + !ni->ni_port_valid && eh.ether_type != htons(ETHERTYPE_PAE)) { DPRINTF(("port not valid: %s\n", ether_sprintf(eh.ether_dhost))); @@ -581,7 +582,8 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni) } if ((ic->ic_flags & IEEE80211_F_WEPON) || - ((ic->ic_flags & IEEE80211_F_RSNON) && ni->ni_port_valid)) + ((ic->ic_flags & IEEE80211_F_RSNON) && + (ni->ni_flags & IEEE80211_NODE_TXPROT))) wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; *pni = ni; diff --git a/sys/net80211/ieee80211_pae_input.c b/sys/net80211/ieee80211_pae_input.c index 446185636c3..321f3a06f08 100644 --- a/sys/net80211/ieee80211_pae_input.c +++ b/sys/net80211/ieee80211_pae_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_pae_input.c,v 1.3 2008/07/27 14:21:15 damien Exp $ */ +/* $OpenBSD: ieee80211_pae_input.c,v 1.4 2008/08/02 08:20:16 damien Exp $ */ /*- * Copyright (c) 2007,2008 Damien Bergamini @@ -461,6 +461,7 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic, reason = IEEE80211_REASON_AUTH_LEAVE; goto deauth; } + ni->ni_flags |= IEEE80211_NODE_RXPROT; } if (gtk != NULL) { u_int64_t rsc; @@ -488,7 +489,11 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic, goto deauth; } } + if (info & EAPOL_KEY_INSTALL) + ni->ni_flags |= IEEE80211_NODE_TXRXPROT; + if (info & EAPOL_KEY_SECURE) { + ni->ni_flags |= IEEE80211_NODE_TXRXPROT; if (ic->ic_opmode != IEEE80211_M_IBSS || ++ni->ni_key_count == 2) { DPRINTF(("marking port %s valid\n", @@ -546,6 +551,7 @@ ieee80211_recv_4way_msg4(struct ieee80211com *ic, ieee80211_node_leave(ic, ni); return; } + ni->ni_flags |= IEEE80211_NODE_TXRXPROT; } if (ic->ic_opmode != IEEE80211_M_IBSS || ++ni->ni_key_count == 2) { DPRINTF(("marking port %s valid\n", @@ -829,6 +835,7 @@ ieee80211_recv_group_msg2(struct ieee80211com *ic, --ic->ic_rsn_keydonesta == 0) ieee80211_setkeysdone(ic); ni->ni_flags &= ~IEEE80211_NODE_REKEY; + ni->ni_flags |= IEEE80211_NODE_TXRXPROT; ni->ni_rsn_gstate = RSNA_IDLE; ni->ni_rsn_retries = 0; -- 2.20.1