summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2008-08-02 08:20:17 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2008-08-02 08:20:17 +0000
commit030ed887c3898c59480eff565ffe1f6861df249d (patch)
treee325f8ae08d4ab6be73fea6a66d0e98abeb02c97
parent163c5153ed3152ac34387e524a941ec941c199b5 (diff)
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@
-rw-r--r--sys/net80211/ieee80211_input.c30
-rw-r--r--sys/net80211/ieee80211_node.c5
-rw-r--r--sys/net80211/ieee80211_node.h8
-rw-r--r--sys/net80211/ieee80211_output.c8
-rw-r--r--sys/net80211/ieee80211_pae_input.c9
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 <damien.bergamini@free.fr>
@@ -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;