summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2008-04-21 19:01:02 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2008-04-21 19:01:02 +0000
commit394e31e63e85d156e4f3c05c040cc0345e58805e (patch)
tree538bbb212b08f02d552fb82ff4f55e1d6bc6d7f3
parent39d1536c6cc6d559b01d29fc82188ff400989145 (diff)
- do not process ethernet PAE frames if RSN is not enabled
- add a ieee80211_recv_action() function (will be used later) - some cleanup, remove unused prototypes, get rid of the IEEE80211_VERIFY_* macros
-rw-r--r--sys/net80211/ieee80211_crypto.c4
-rw-r--r--sys/net80211/ieee80211_crypto.h3
-rw-r--r--sys/net80211/ieee80211_input.c238
3 files changed, 120 insertions, 125 deletions
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 779d6487e4d..954a15e7800 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto.c,v 1.39 2008/04/18 09:16:14 djm Exp $ */
+/* $OpenBSD: ieee80211_crypto.c,v 1.40 2008/04/21 19:01:01 damien Exp $ */
/*-
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
@@ -57,8 +57,6 @@ void ieee80211_prf(const u_int8_t *, size_t, struct vector *, int,
u_int8_t *, size_t);
void ieee80211_derive_pmkid(const u_int8_t *, size_t, const u_int8_t *,
const u_int8_t *, u_int8_t *);
-void ieee80211_derive_gtk(const u_int8_t *, size_t, const u_int8_t *,
- const u_int8_t *, u_int8_t *, size_t);
void
ieee80211_crypto_attach(struct ifnet *ifp)
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
index d4e956b64d5..67f96ae5f25 100644
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_crypto.h,v 1.11 2008/04/18 09:16:14 djm Exp $ */
+/* $OpenBSD: ieee80211_crypto.h,v 1.12 2008/04/21 19:01:01 damien Exp $ */
/* $NetBSD: ieee80211_crypto.h,v 1.2 2003/09/14 01:14:55 dyoung Exp $ */
/*-
@@ -92,7 +92,6 @@ extern void ieee80211_crypto_detach(struct ifnet *);
extern const u_int8_t *ieee80211_get_pmk(struct ieee80211com *,
struct ieee80211_node *, const u_int8_t *);
-
extern struct ieee80211_key *ieee80211_get_txkey(struct ieee80211com *,
const struct ieee80211_frame *, struct ieee80211_node *);
extern struct mbuf *ieee80211_encrypt(struct ieee80211com *, struct mbuf *,
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 5fb03fe658e..15c5ebe51ac 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,5 +1,5 @@
/* $NetBSD: ieee80211_input.c,v 1.24 2004/05/31 11:12:24 dyoung Exp $ */
-/* $OpenBSD: ieee80211_input.c,v 1.74 2008/04/21 16:14:25 damien Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.75 2008/04/21 19:01:01 damien Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
@@ -82,8 +82,7 @@ int ieee80211_parse_rsn(struct ieee80211com *, const u_int8_t *,
int ieee80211_parse_wpa(struct ieee80211com *, const u_int8_t *,
struct ieee80211_rsnparams *);
int ieee80211_save_ie(const u_int8_t *, u_int8_t **);
-void ieee80211_recv_pspoll(struct ieee80211com *, struct mbuf *, int,
- u_int32_t);
+void ieee80211_recv_pspoll(struct ieee80211com *, struct mbuf *);
int ieee80211_do_slow_print(struct ieee80211com *, int *);
void ieee80211_recv_probe_resp(struct ieee80211com *, struct mbuf *,
struct ieee80211_node *, int, u_int32_t, int);
@@ -99,6 +98,8 @@ void ieee80211_recv_deauth(struct ieee80211com *, struct mbuf *,
struct ieee80211_node *);
void ieee80211_recv_disassoc(struct ieee80211com *, struct mbuf *,
struct ieee80211_node *);
+void ieee80211_recv_action(struct ieee80211com *, struct mbuf *,
+ struct ieee80211_node *);
void ieee80211_recv_4way_msg1(struct ieee80211com *,
struct ieee80211_eapol_key *, struct ieee80211_node *);
void ieee80211_recv_4way_msg2(struct ieee80211com *,
@@ -169,12 +170,6 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
if (ni == NULL)
panic("null node");
- /* trim CRC here so WEP can find its own CRC at the end of packet. */
- if (m->m_flags & M_HASFCS) {
- m_adj(m, -IEEE80211_CRC_LEN);
- m->m_flags &= ~M_HASFCS;
- }
-
/*
* In monitor mode, send everything directly to bpf.
* XXX may want to include the CRC
@@ -459,7 +454,8 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
if (ifp->if_bpf && m1 == NULL)
bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif
- if (eh->ether_type == htons(ETHERTYPE_PAE)) {
+ if ((ic->ic_flags & IEEE80211_F_RSNON) &&
+ eh->ether_type == htons(ETHERTYPE_PAE)) {
(*ic->ic_recv_eapol)(ic, m, ni);
m_freem(m);
} else
@@ -545,7 +541,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
printf("%s: got power save probe from %s\n",
ifp->if_xname,
ether_sprintf(wh->i_addr2));
- ieee80211_recv_pspoll(ic, m, rssi, rstamp);
+ ieee80211_recv_pspoll(ic, m);
}
goto out;
@@ -698,78 +694,6 @@ ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
return ieee80211_fix_rate(ic, ni, flags);
}
-/* Verify the existence and length of __elem or get out. */
-#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \
- if ((__elem) == NULL) { \
- IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n", \
- __func__, ieee80211_mgt_subtype_name[ \
- (wh->i_fc[0] & \
- IEEE80211_FC0_SUBTYPE_MASK) >> \
- IEEE80211_FC0_SUBTYPE_SHIFT])); \
- ic->ic_stats.is_rx_elem_missing++; \
- return; \
- } \
- if ((__elem)[1] > (__maxlen)) { \
- IEEE80211_DPRINTF(("%s: bad " #__elem " len %d in %s " \
- "frame from %s\n", __func__, (__elem)[1], \
- ieee80211_mgt_subtype_name[(wh->i_fc[0] & \
- IEEE80211_FC0_SUBTYPE_MASK) >> \
- IEEE80211_FC0_SUBTYPE_SHIFT], \
- ether_sprintf((u_int8_t *)wh->i_addr2))); \
- ic->ic_stats.is_rx_elem_toobig++; \
- return; \
- } \
-} while (0)
-
-#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \
- if ((_len) < (_minlen)) { \
- IEEE80211_DPRINTF(("%s: %s frame too short from %s\n", \
- __func__, \
- ieee80211_mgt_subtype_name[(wh->i_fc[0] & \
- IEEE80211_FC0_SUBTYPE_MASK) >> \
- IEEE80211_FC0_SUBTYPE_SHIFT], \
- ether_sprintf((u_int8_t *)wh->i_addr2))); \
- ic->ic_stats.is_rx_elem_toosmall++; \
- return; \
- } \
-} while (0)
-
-#ifdef IEEE80211_DEBUG
-void
-ieee80211_ssid_mismatch(struct ieee80211com *, const char *,
- const u_int8_t[IEEE80211_ADDR_LEN], const u_int8_t *);
-void
-ieee80211_ssid_mismatch(struct ieee80211com *ic, const char *tag,
- const u_int8_t mac[IEEE80211_ADDR_LEN], const u_int8_t *ssid)
-{
- printf("[%s] %s req ssid mismatch: ",
- ether_sprintf((u_int8_t *)mac), tag);
- ieee80211_print_essid(ssid + 2, ssid[1]);
- printf("\n");
-}
-
-#define IEEE80211_VERIFY_SSID(_ni, _ssid, _packet_type) do { \
- if ((_ssid)[1] != 0 && \
- ((_ssid)[1] != (_ni)->ni_esslen || \
- memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \
- if (ieee80211_debug) \
- ieee80211_ssid_mismatch(ic, _packet_type, \
- wh->i_addr2, _ssid); \
- ic->ic_stats.is_rx_ssidmismatch++; \
- return; \
- } \
-} while (0)
-#else /* !IEEE80211_DEBUG */
-#define IEEE80211_VERIFY_SSID(_ni, _ssid, _packet_type) do { \
- if ((_ssid)[1] != 0 && \
- ((_ssid)[1] != (_ni)->ni_esslen || \
- memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) { \
- ic->ic_stats.is_rx_ssidmismatch++; \
- return; \
- } \
-} while (0)
-#endif /* !IEEE80211_DEBUG */
-
void
ieee80211_auth_open(struct ieee80211com *ic, const struct ieee80211_frame *wh,
struct ieee80211_node *ni, int rssi, u_int32_t rstamp, u_int16_t seq,
@@ -1170,10 +1094,15 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0,
frm = (const u_int8_t *)&wh[1];
efrm = mtod(m0, u_int8_t *) + m0->m_len;
- IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
+ /* make sure all mandatory fixed fields are present */
+ if (efrm - frm < 12) {
+ IEEE80211_DPRINTF(("%s: frame too short\n", __func__));
+ return;
+ }
tstamp = frm; frm += 8;
bintval = LE_READ_2(frm); frm += 2;
capinfo = LE_READ_2(frm); frm += 2;
+
ssid = rates = xrates = edcaie = wmmie = rsnie = wpaie = NULL;
bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
chan = bchan;
@@ -1255,9 +1184,17 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m0,
}
frm += 2 + frm[1];
}
- IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
- IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
-
+ /* supported rates element is mandatory */
+ if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) {
+ IEEE80211_DPRINTF(("%s: invalid supported rates element\n",
+ __func__));
+ return;
+ }
+ /* SSID element is mandatory */
+ if (ssid == NULL || ssid[1] > IEEE80211_NWID_LEN) {
+ IEEE80211_DPRINTF(("%s: invalid SSID element\n", __func__));
+ return;
+ }
if (
#if IEEE80211_CHAN_MAX < 255
chan > IEEE80211_CHAN_MAX ||
@@ -1483,12 +1420,27 @@ ieee80211_recv_probe_req(struct ieee80211com *ic, struct mbuf *m0,
}
frm += 2 + frm[1];
}
- IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
- IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
- IEEE80211_VERIFY_SSID(ic->ic_bss, ssid, "probe");
- if ((ic->ic_flags & IEEE80211_F_HIDENWID) && ssid[1] == 0) {
- IEEE80211_DPRINTF(("%s: no ssid "
- "with ssid suppression enabled", __func__));
+ /* supported rates element is mandatory */
+ if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) {
+ IEEE80211_DPRINTF(("%s: invalid supported rates element\n",
+ __func__));
+ return;
+ }
+ /* SSID element is mandatory */
+ if (ssid == NULL || ssid[1] > IEEE80211_NWID_LEN) {
+ IEEE80211_DPRINTF(("%s: invalid SSID element\n", __func__));
+ return;
+ }
+ /* check that the specified SSID (if not wildcard) matches ours */
+ if (ssid[1] != 0 && (ssid[1] != ni->ni_esslen ||
+ memcmp(&ssid[2], ni->ni_essid, ni->ni_esslen) != 0)) {
+ IEEE80211_DPRINTF(("%s: SSID mismatch\n", __func__));
+ ic->ic_stats.is_rx_ssidmismatch++;
+ return;
+ }
+ /* refuse wildcard SSID if we're hiding our SSID in beacons */
+ if (ssid[1] == 0 && (ic->ic_flags & IEEE80211_F_HIDENWID)) {
+ IEEE80211_DPRINTF(("%s: wildcard SSID rejected", __func__));
ic->ic_stats.is_rx_ssidmismatch++;
return;
}
@@ -1531,16 +1483,19 @@ ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0,
frm = (const u_int8_t *)&wh[1];
efrm = mtod(m0, u_int8_t *) + m0->m_len;
- IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
+ /* make sure all mandatory fixed fields are present */
+ if (efrm - frm < 6) {
+ IEEE80211_DPRINTF(("%s: frame too short\n", __func__));
+ return;
+ }
algo = LE_READ_2(frm); frm += 2;
seq = LE_READ_2(frm); frm += 2;
status = LE_READ_2(frm); frm += 2;
IEEE80211_DPRINTF(("%s: auth %d seq %d from %s\n",
__func__, algo, seq, ether_sprintf((u_int8_t *)wh->i_addr2)));
- if (algo == IEEE80211_AUTH_ALG_OPEN)
- ieee80211_auth_open(ic, wh, ni, rssi, rstamp, seq, status);
- else {
+ /* only "open" auth mode is supported */
+ if (algo != IEEE80211_AUTH_ALG_OPEN) {
IEEE80211_DPRINTF(("%s: unsupported authentication "
"algorithm %d from %s\n",
__func__, algo, ether_sprintf((u_int8_t *)wh->i_addr2)));
@@ -1551,7 +1506,9 @@ ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0,
IEEE80211_FC0_SUBTYPE_AUTH,
(seq+1) | (IEEE80211_STATUS_ALG<<16));
}
+ return;
}
+ ieee80211_auth_open(ic, wh, ni, rssi, rstamp, seq, status);
}
/*-
@@ -1588,7 +1545,11 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0,
resp = reassoc ? IEEE80211_FC0_SUBTYPE_REASSOC_RESP :
IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
- IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
+ /* make sure all mandatory fixed fields are present */
+ if (efrm - frm < (reassoc ? 10 : 4)) {
+ IEEE80211_DPRINTF(("%s: frame too short\n", __func__));
+ return;
+ }
if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
IEEE80211_DPRINTF(("%s: ignore other bss from %s\n",
__func__, ether_sprintf((u_int8_t *)wh->i_addr2)));
@@ -1599,6 +1560,7 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0,
bintval = LE_READ_2(frm); frm += 2;
if (reassoc)
frm += IEEE80211_ADDR_LEN; /* skip current AP address */
+
ssid = rates = xrates = rsnie = wpaie = NULL;
while (frm + 2 <= efrm) {
if (frm + 2 + frm[1] > efrm) {
@@ -1633,10 +1595,25 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0,
}
frm += 2 + frm[1];
}
- IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
- IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
- IEEE80211_VERIFY_SSID(ic->ic_bss, ssid,
- reassoc ? "reassoc" : "assoc");
+ /* supported rates element is mandatory */
+ if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) {
+ IEEE80211_DPRINTF(("%s: invalid supported rates element\n",
+ __func__));
+ return;
+ }
+ /* SSID element is mandatory */
+ if (ssid == NULL || ssid[1] > IEEE80211_NWID_LEN) {
+ IEEE80211_DPRINTF(("%s: invalid SSID element\n", __func__));
+ return;
+ }
+ /* check that the specified SSID (if not wildcard) matches ours */
+ if (ssid[1] != 0 && (ssid[1] != ni->ni_esslen ||
+ memcmp(&ssid[2], ni->ni_essid, ni->ni_esslen) != 0)) {
+ IEEE80211_DPRINTF(("%s: SSID mismatch\n", __func__));
+ ic->ic_stats.is_rx_ssidmismatch++;
+ return;
+ }
+
if (ni->ni_state != IEEE80211_STA_AUTH &&
ni->ni_state != IEEE80211_STA_ASSOC) {
IEEE80211_DPRINTF(
@@ -1652,13 +1629,6 @@ ieee80211_recv_assoc_req(struct ieee80211com *ic, struct mbuf *m0,
ic->ic_stats.is_rx_assoc_notauth++;
return;
}
- if (reassoc && ni->ni_state != IEEE80211_STA_ASSOC) {
- IEEE80211_DPRINTF(("%s: deny reassoc from %s, not "
- "associated\n", __func__,
- ether_sprintf((u_int8_t *)wh->i_addr2)));
- status = IEEE80211_STATUS_NOT_ASSOCED;
- goto end;
- }
if (!(capinfo & IEEE80211_CAPINFO_ESS)) {
ic->ic_stats.is_rx_assoc_capmismatch++;
@@ -1793,10 +1763,14 @@ ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m0,
frm = (const u_int8_t *)&wh[1];
efrm = mtod(m0, u_int8_t *) + m0->m_len;
- IEEE80211_VERIFY_LENGTH(efrm - frm, 6);
+ /* make sure all mandatory fixed fields are present */
+ if (efrm - frm < 6) {
+ IEEE80211_DPRINTF(("%s: frame too short\n", __func__));
+ return;
+ }
capinfo = LE_READ_2(frm); frm += 2;
status = LE_READ_2(frm); frm += 2;
- if (status != 0) {
+ if (status != IEEE80211_STATUS_SUCCESS) {
if (ifp->if_flags & IFF_DEBUG)
printf("%s: %sassociation failed (reason %d)"
" for %s\n", ifp->if_xname,
@@ -1838,8 +1812,12 @@ ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m0,
}
frm += 2 + frm[1];
}
-
- IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
+ /* supported rates element is mandatory */
+ if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) {
+ IEEE80211_DPRINTF(("%s: invalid supported rates element\n",
+ __func__));
+ return;
+ }
rate = ieee80211_setup_rates(ic, ni, rates, xrates,
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO |
IEEE80211_F_DODEL);
@@ -1911,8 +1889,13 @@ ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0,
frm = (const u_int8_t *)&wh[1];
efrm = mtod(m0, u_int8_t *) + m0->m_len;
- IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
+ /* make sure all mandatory fixed fields are present */
+ if (efrm - frm < 2) {
+ IEEE80211_DPRINTF(("%s: frame too short\n", __func__));
+ return;
+ }
reason = LE_READ_2(frm);
+
ic->ic_stats.is_rx_deauth++;
switch (ic->ic_opmode) {
case IEEE80211_M_STA:
@@ -1952,8 +1935,13 @@ ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0,
frm = (const u_int8_t *)&wh[1];
efrm = mtod(m0, u_int8_t *) + m0->m_len;
- IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
+ /* make sure all mandatory fixed fields are present */
+ if (efrm - frm < 2) {
+ IEEE80211_DPRINTF(("%s: frame too short\n", __func__));
+ return;
+ }
reason = LE_READ_2(frm);
+
ic->ic_stats.is_rx_disassoc++;
switch (ic->ic_opmode) {
case IEEE80211_M_STA:
@@ -1976,6 +1964,17 @@ ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0,
}
}
+/*-
+ * Action frame format:
+ * [1] Action
+ */
+void
+ieee80211_recv_action(struct ieee80211com *ic, struct mbuf *m0,
+ struct ieee80211_node *ni)
+{
+ /* TBD */
+}
+
void
ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
@@ -2011,6 +2010,9 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
case IEEE80211_FC0_SUBTYPE_DISASSOC:
ieee80211_recv_disassoc(ic, m0, ni);
break;
+ case IEEE80211_FC0_SUBTYPE_ACTION:
+ ieee80211_recv_action(ic, m0, ni);
+ break;
default:
IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not "
"handled\n", __func__, subtype));
@@ -2018,9 +2020,6 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
break;
}
}
-#undef IEEE80211_VERIFY_LENGTH
-#undef IEEE80211_VERIFY_ELEMENT
-#undef IEEE80211_VERIFY_SSID
/* unaligned big endian access */
#define BE_READ_2(p) \
@@ -2878,8 +2877,7 @@ ieee80211_recv_eapol(struct ieee80211com *ic, struct mbuf *m0,
}
void
-ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0, int rssi,
- u_int32_t rstamp)
+ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0)
{
struct ifnet *ifp = &ic->ic_if;
struct ieee80211_frame *wh;