summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/net80211/ieee80211_input.c3
-rw-r--r--sys/net80211/ieee80211_node.h11
-rw-r--r--sys/net80211/ieee80211_pae_input.c36
-rw-r--r--sys/net80211/ieee80211_pae_output.c4
-rw-r--r--sys/net80211/ieee80211_proto.c12
5 files changed, 60 insertions, 6 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 84c0caf7c42..4dff49f2d41 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_input.c,v 1.186 2017/02/02 16:47:53 stsp Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.187 2017/03/01 19:28:48 stsp Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
@@ -2319,6 +2319,7 @@ ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m,
*/
if (ic->ic_flags & IEEE80211_F_RSNON) {
/* XXX ic->ic_mgt_timer = 5; */
+ ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
} else if (ic->ic_flags & IEEE80211_F_WEPON)
ni->ni_flags |= IEEE80211_NODE_TXRXPROT;
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index 0be94e5a03c..d1b6067e255 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_node.h,v 1.65 2017/02/02 16:47:53 stsp Exp $ */
+/* $OpenBSD: ieee80211_node.h,v 1.66 2017/03/01 19:28:48 stsp Exp $ */
/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */
/*-
@@ -99,6 +99,14 @@ enum {
RSNA_KEYERROR
};
+/* Supplicant state machine: 4-Way Handshake (not documented in standard) */
+enum {
+ RSNA_SUPP_INITIALIZE, /* not expecting any messages */
+ RSNA_SUPP_PTKSTART, /* awaiting handshake message 1 */
+ RSNA_SUPP_PTKNEGOTIATING, /* got message 1 and derived PTK */
+ RNSA_SUPP_PTKDONE /* got message 3 and authenticated AP */
+};
+
struct ieee80211_rxinfo {
u_int32_t rxi_flags;
u_int32_t rxi_tstamp;
@@ -208,6 +216,7 @@ struct ieee80211_node {
/* RSN */
struct timeout ni_eapol_to;
u_int ni_rsn_state;
+ u_int ni_rsn_supp_state;
u_int ni_rsn_gstate;
u_int ni_rsn_retries;
u_int ni_rsnprotos;
diff --git a/sys/net80211/ieee80211_pae_input.c b/sys/net80211/ieee80211_pae_input.c
index c0a7327ab60..45f5dec238a 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.26 2017/02/02 16:47:53 stsp Exp $ */
+/* $OpenBSD: ieee80211_pae_input.c,v 1.27 2017/03/01 19:28:48 stsp Exp $ */
/*-
* Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>
@@ -193,6 +193,15 @@ ieee80211_recv_4way_msg1(struct ieee80211com *ic,
ic->ic_opmode != IEEE80211_M_IBSS)
return;
#endif
+ /*
+ * Message 1 is always expected while RSN is active since some
+ * APs will rekey the PTK by sending Msg1/4 after some time.
+ */
+ if (ni->ni_rsn_supp_state == RSNA_SUPP_INITIALIZE) {
+ DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_state));
+ return;
+ }
+ /* enforce monotonicity of key request replay counter */
if (ni->ni_replaycnt_ok &&
BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {
ic->ic_stats.is_rx_eapol_replay++;
@@ -343,6 +352,13 @@ ieee80211_recv_4way_msg3(struct ieee80211com *ic,
ic->ic_opmode != IEEE80211_M_IBSS)
return;
#endif
+ /* discard if we're not expecting this message */
+ if (ni->ni_rsn_supp_state != RSNA_SUPP_PTKNEGOTIATING &&
+ ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {
+ DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_state));
+ return;
+ }
+ /* enforce monotonicity of key request replay counter */
if (ni->ni_replaycnt_ok &&
BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {
ic->ic_stats.is_rx_eapol_replay++;
@@ -737,6 +753,12 @@ ieee80211_recv_rsn_group_msg1(struct ieee80211com *ic,
ic->ic_opmode != IEEE80211_M_IBSS)
return;
#endif
+ /* discard if we're not expecting this message */
+ if (ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {
+ DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_state));
+ return;
+ }
+ /* enforce monotonicity of key request replay counter */
if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {
ic->ic_stats.is_rx_eapol_replay++;
return;
@@ -883,6 +905,12 @@ ieee80211_recv_wpa_group_msg1(struct ieee80211com *ic,
ic->ic_opmode != IEEE80211_M_IBSS)
return;
#endif
+ /* discard if we're not expecting this message */
+ if (ni->ni_rsn_supp_state != RNSA_SUPP_PTKDONE) {
+ DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_state));
+ return;
+ }
+ /* enforce monotonicity of key request replay counter */
if (BE_READ_8(key->replaycnt) <= ni->ni_replaycnt) {
ic->ic_stats.is_rx_eapol_replay++;
return;
@@ -975,6 +1003,7 @@ ieee80211_recv_group_msg2(struct ieee80211com *ic,
ni->ni_rsn_gstate));
return;
}
+ /* enforce monotonicity of key request replay counter */
if (BE_READ_8(key->replaycnt) != ni->ni_replaycnt) {
ic->ic_stats.is_rx_eapol_replay++;
return;
@@ -1023,6 +1052,11 @@ ieee80211_recv_eapol_key_req(struct ieee80211com *ic,
ic->ic_opmode != IEEE80211_M_IBSS)
return;
+ /* discard if we're not expecting this message */
+ if (ni->ni_rsn_state != RSNA_PTKINITDONE) {
+ DPRINTF(("unexpected in state: %d\n", ni->ni_rsn_state));
+ return;
+ }
/* enforce monotonicity of key request replay counter */
if (ni->ni_reqreplaycnt_ok &&
BE_READ_8(key->replaycnt) <= ni->ni_reqreplaycnt) {
diff --git a/sys/net80211/ieee80211_pae_output.c b/sys/net80211/ieee80211_pae_output.c
index 340e9a0fa9e..d385b00ad9d 100644
--- a/sys/net80211/ieee80211_pae_output.c
+++ b/sys/net80211/ieee80211_pae_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_pae_output.c,v 1.28 2016/12/17 18:36:22 stsp Exp $ */
+/* $OpenBSD: ieee80211_pae_output.c,v 1.29 2017/03/01 19:28:48 stsp Exp $ */
/*-
* Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>
@@ -310,6 +310,7 @@ ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
u_int16_t info;
u_int8_t *frm;
+ ni->ni_rsn_supp_state = RSNA_SUPP_PTKNEGOTIATING;
m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
(ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?
2 + IEEE80211_WPAIE_MAXLEN :
@@ -438,6 +439,7 @@ ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)
struct mbuf *m;
u_int16_t info;
+ ni->ni_rsn_supp_state = RNSA_SUPP_PTKDONE;
m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
if (m == NULL)
return ENOMEM;
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 776c2e85270..23685291d1f 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_proto.c,v 1.72 2017/02/07 15:07:14 stsp Exp $ */
+/* $OpenBSD: ieee80211_proto.c,v 1.73 2017/03/01 19:28:48 stsp Exp $ */
/* $NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $ */
/*-
@@ -356,8 +356,8 @@ ieee80211_set_shortslottime(struct ieee80211com *ic, int on)
int
ieee80211_keyrun(struct ieee80211com *ic, u_int8_t *macaddr)
{
-#ifndef IEEE80211_STA_ONLY
struct ieee80211_node *ni;
+#ifndef IEEE80211_STA_ONLY
struct ieee80211_pmk *pmk;
#endif
@@ -366,6 +366,7 @@ ieee80211_keyrun(struct ieee80211com *ic, u_int8_t *macaddr)
!(ic->ic_flags & IEEE80211_F_RSNON))
return ENETDOWN;
+ ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
#ifndef IEEE80211_STA_ONLY
if (ic->ic_opmode == IEEE80211_M_STA)
#endif
@@ -731,6 +732,10 @@ ieee80211_auth_open(struct ieee80211com *ic, const struct ieee80211_frame *wh,
}
ieee80211_new_state(ic, IEEE80211_S_AUTH,
wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+
+ /* In IBSS mode no (re)association frames are sent. */
+ if (ic->ic_flags & IEEE80211_F_RSNON)
+ ni->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
break;
case IEEE80211_M_AHDEMO:
@@ -897,6 +902,7 @@ justcleanup:
ieee80211_free_allnodes(ic);
break;
}
+ ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
break;
case IEEE80211_S_SCAN:
ic->ic_flags &= ~IEEE80211_F_SIBSS;
@@ -907,6 +913,7 @@ justcleanup:
ieee80211_chan2mode(ic, ni->ni_chan)];
ni->ni_associd = 0;
ni->ni_rstamp = 0;
+ ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
switch (ostate) {
case IEEE80211_S_INIT:
#ifndef IEEE80211_STA_ONLY
@@ -949,6 +956,7 @@ justcleanup:
}
break;
case IEEE80211_S_AUTH:
+ ni->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
switch (ostate) {
case IEEE80211_S_INIT:
DPRINTF(("invalid transition\n"));