summaryrefslogtreecommitdiff
path: root/sys
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 /sys
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@
Diffstat (limited to 'sys')
-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;