[Madwifi-cvs] revision 1676 committed
Status: Beta
Brought to you by:
otaku
From: Brian E. <svn...@ma...> - 2006-07-06 03:23:16
|
Project : madwifi Revision : 1676 Author : brian (Brian Eaton) Date : 2006-07-06 05:23:08 +0200 (Thu, 06 Jul 2006) Log Message : Drop unencrypted EAPOL, clean up specification of WEP authentication algorithm. Fixes ticket #566. Affected Files: * trunk/net80211/ieee80211_input.c updated * trunk/net80211/ieee80211_ioctl.h updated * trunk/net80211/ieee80211_var.h updated * trunk/net80211/ieee80211_wireless.c updated Modified: trunk/net80211/ieee80211_input.c =================================================================== --- trunk/net80211/ieee80211_input.c 2006-07-05 07:29:38 UTC (rev 1675) +++ trunk/net80211/ieee80211_input.c 2006-07-06 03:23:08 UTC (rev 1676) @@ -118,7 +118,10 @@ static void ieee80211_send_error(struct ieee80211_node *, const u_int8_t *, int, int); static void ieee80211_recv_pspoll(struct ieee80211_node *, struct sk_buff *); +static int accept_data_frame(struct ieee80211vap *, struct ieee80211_node *, + struct ieee80211_key *, struct sk_buff *, struct ether_header *); + #ifdef ATH_SUPERG_FF static void athff_decap(struct sk_buff *); #endif @@ -675,40 +678,10 @@ goto err; } eh = (struct ether_header *) skb->data; - if (!ieee80211_node_is_authorized(ni)) { - /* - * Deny any non-PAE frames received prior to - * authorization. For open/shared-key - * authentication the port is mark authorized - * after authentication completes. For 802.1x - * the port is not marked authorized by the - * authenticator until the handshake has completed. - */ - if (eh->ether_type != __constant_htons(ETHERTYPE_PAE)) { - IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, - eh->ether_shost, "data", - "unauthorized port: ether type 0x%x len %u", - eh->ether_type, skb->len); - vap->iv_stats.is_rx_unauth++; - IEEE80211_NODE_STAT(ni, rx_unauth); - goto err; - } - } else { - /* - * When denying unencrypted frames, discard - * any non-PAE frames received without encryption. - */ - if ((vap->iv_flags & IEEE80211_F_DROPUNENC) && - key == NULL && - eh->ether_type != __constant_htons(ETHERTYPE_PAE)) { - /* - * Drop unencrypted frames. - */ - vap->iv_stats.is_rx_unencrypted++; - IEEE80211_NODE_STAT(ni, rx_unencrypted); - goto out; - } - } + + if (! accept_data_frame(vap, ni, key, skb, eh)) + goto out; + vap->iv_devstats.rx_packets++; vap->iv_devstats.rx_bytes += skb->len; IEEE80211_NODE_STAT(ni, rx_data); @@ -865,7 +838,76 @@ } EXPORT_SYMBOL(ieee80211_input); + /* + * Determines whether a frame should be accepted, based on information + * about the frame's origin and encryption, and policy for this vap. + */ +static int accept_data_frame(struct ieee80211vap *vap, + struct ieee80211_node *ni, struct ieee80211_key *key, + struct sk_buff *skb, struct ether_header *eh) +{ +#define IS_EAPOL(eh) ((eh)->ether_type == __constant_htons(ETHERTYPE_PAE)) +#define PAIRWISE_SET(vap) ((vap)->iv_nw_keys[0].wk_cipher != &ieee80211_cipher_none) + if (IS_EAPOL(eh)) { + /* encrypted eapol is always OK */ + if (key) + return 1; + /* cleartext eapol is OK if we don't have pairwise keys yet */ + if (! PAIRWISE_SET(vap)) + return 1; + /* cleartext eapol is OK if configured to allow it */ + if (! IEEE80211_VAP_DROPUNENC_EAPOL(vap)) + return 1; + /* cleartext eapol is OK if other unencrypted is OK */ + if (! (vap->iv_flags & IEEE80211_F_DROPUNENC)) + return 1; + /* not OK */ + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, + eh->ether_shost, "data", + "unauthorized port: ether type 0x%x len %u", + eh->ether_type, skb->len); + vap->iv_stats.is_rx_unauth++; + vap->iv_devstats.rx_errors++; + IEEE80211_NODE_STAT(ni, rx_unauth); + return 0; + } + + if (!ieee80211_node_is_authorized(ni)) { + /* + * Deny any non-PAE frames received prior to + * authorization. For open/shared-key + * authentication the port is mark authorized + * after authentication completes. For 802.1x + * the port is not marked authorized by the + * authenticator until the handshake has completed. + */ + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, + eh->ether_shost, "data", + "unauthorized port: ether type 0x%x len %u", + eh->ether_type, skb->len); + vap->iv_stats.is_rx_unauth++; + vap->iv_devstats.rx_errors++; + IEEE80211_NODE_STAT(ni, rx_unauth); + return 0; + } else { + /* + * When denying unencrypted frames, discard + * any non-PAE frames received without encryption. + */ + if ((vap->iv_flags & IEEE80211_F_DROPUNENC) && key == NULL) { + IEEE80211_NODE_STAT(ni, rx_unencrypted); + return 0; + } + } + return 1; + +#undef IS_EAPOL +#undef PAIRWISE_SET +} + + +/* * Context: softIRQ (tasklet) */ int Modified: trunk/net80211/ieee80211_ioctl.h =================================================================== --- trunk/net80211/ieee80211_ioctl.h 2006-07-05 07:29:38 UTC (rev 1675) +++ trunk/net80211/ieee80211_ioctl.h 2006-07-06 03:23:08 UTC (rev 1676) @@ -591,6 +591,7 @@ IEEE80211_PARAM_EOSPDROP = 57, /* force uapsd EOSP drop (ap only) */ IEEE80211_PARAM_MARKDFS = 58, /* mark a dfs interference channel when found */ IEEE80211_PARAM_REGCLASS = 59, /* enable regclass ids in country IE */ + IEEE80211_PARAM_DROPUNENC_EAPOL = 60, /* drop unencrypted eapol frames */ }; #define SIOCG80211STATS (SIOCDEVPRIVATE+2) Modified: trunk/net80211/ieee80211_var.h =================================================================== --- trunk/net80211/ieee80211_var.h 2006-07-05 07:29:38 UTC (rev 1675) +++ trunk/net80211/ieee80211_var.h 2006-07-06 03:23:08 UTC (rev 1676) @@ -450,6 +450,7 @@ #define IEEE80211_FEXT_REGCLASS 0x00000100 /* CONF: send regclassids in country ie */ #define IEEE80211_FEXT_ERPUPDATE 0x00000200 /* STATUS: update ERP element */ #define IEEE80211_FEXT_SWBMISS 0x00000400 /* CONF: use software beacon timer */ +#define IEEE80211_FEXT_DROPUNENC_EAPOL 0x00000800 /* CONF: drop unencrypted eapol frames */ #define IEEE80211_COM_UAPSD_ENABLE(_ic) ((_ic)->ic_flags_ext |= IEEE80211_FEXT_UAPSD) #define IEEE80211_COM_UAPSD_DISABLE(_ic) ((_ic)->ic_flags_ext &= ~IEEE80211_FEXT_UAPSD) @@ -467,7 +468,11 @@ #define IEEE80211_VAP_EOSPDROP_ENABLE(_v) ((_v)->iv_flags_ext |= IEEE80211_FEXT_EOSPDROP) #define IEEE80211_VAP_EOSPDROP_DISABLE(_v) ((_v)->iv_flags_ext &= ~IEEE80211_FEXT_EOSPDROP) #define IEEE80211_VAP_EOSPDROP_ENABLED(_v) ((_v)->iv_flags_ext & IEEE80211_FEXT_EOSPDROP) +#define IEEE80211_VAP_DROPUNENC_EAPOL_ENABLE(_v) ((_v)->iv_flags_ext |= IEEE80211_FEXT_DROPUNENC_EAPOL) +#define IEEE80211_VAP_DROPUNENC_EAPOL_DISABLE(_v) ((_v)->iv_flags_ext &= ~IEEE80211_FEXT_DROPUNENC_EAPOL) +#define IEEE80211_VAP_DROPUNENC_EAPOL(_v) ((_v)->iv_flags_ext & IEEE80211_FEXT_DROPUNENC_EAPOL) + /* ic_caps */ #define IEEE80211_C_WEP 0x00000001 /* CAPABILITY: WEP available */ #define IEEE80211_C_TKIP 0x00000002 /* CAPABILITY: TKIP available */ Modified: trunk/net80211/ieee80211_wireless.c =================================================================== --- trunk/net80211/ieee80211_wireless.c 2006-07-05 07:29:38 UTC (rev 1675) +++ trunk/net80211/ieee80211_wireless.c 2006-07-06 03:23:08 UTC (rev 1676) @@ -2006,18 +2006,15 @@ } switch (value) { case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ - vap->iv_flags |= IEEE80211_F_PRIVACY; value = IEEE80211_AUTH_8021X; break; case IEEE80211_AUTH_OPEN: /* open */ - vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); + vap->iv_flags &= ~(IEEE80211_F_WPA); break; case IEEE80211_AUTH_SHARED: /* shared-key */ case IEEE80211_AUTH_AUTO: /* auto */ case IEEE80211_AUTH_8021X: /* 802.1x */ vap->iv_flags &= ~IEEE80211_F_WPA; - /* both require a key so mark the PRIVACY capability */ - vap->iv_flags |= IEEE80211_F_PRIVACY; break; } /* NB: authenticator attach/detach happens on state change */ @@ -2132,6 +2129,12 @@ else vap->iv_flags &= ~IEEE80211_F_DROPUNENC; break; + case IEEE80211_PARAM_DROPUNENC_EAPOL: + if (value) + IEEE80211_VAP_DROPUNENC_EAPOL_ENABLE(vap); + else + IEEE80211_VAP_DROPUNENC_EAPOL_DISABLE(vap); + break; case IEEE80211_PARAM_COUNTERMEASURES: if (value) { if ((vap->iv_flags & IEEE80211_F_WPA) == 0) @@ -2593,6 +2596,9 @@ case IEEE80211_PARAM_DROPUNENCRYPTED: param[0] = (vap->iv_flags & IEEE80211_F_DROPUNENC) != 0; break; + case IEEE80211_PARAM_DROPUNENC_EAPOL: + param[0] = IEEE80211_VAP_DROPUNENC_EAPOL(vap); + break; case IEEE80211_PARAM_COUNTERMEASURES: param[0] = (vap->iv_flags & IEEE80211_F_COUNTERM) != 0; break; @@ -3939,18 +3945,30 @@ } -/* - * The exact meaning of the IW_AUTH_ALG_* values is a little unclear. - * For example, wpa_supplicant uses IW_AUTH_ALG_OPEN_SYSTEM for WPA-PSK - * APs, unless you happen to set the auth_alg=SHARED option in your config - * file in which case it uses IW_AUTH_ALG_SHARED_KEY. Fortunately, - * neither makes a any difference to madwifi, so for now we ignore it. - */ static int siwauth_80211_auth_alg(struct net_device *dev, struct iw_request_info *info, struct iw_param *erq, char *buf) { - return -EOPNOTSUPP; +#define VALID_ALGS_MASK (IW_AUTH_ALG_OPEN_SYSTEM|IW_AUTH_ALG_SHARED_KEY|IW_AUTH_ALG_LEAP) + int mode = erq->value; + int args[2]; + + args[0] = IEEE80211_PARAM_AUTHMODE; + + if (mode & ~VALID_ALGS_MASK) { + return -EINVAL; + } + if (mode & IW_AUTH_ALG_LEAP) { + args[1] = IEEE80211_AUTH_8021X; + } else if ((mode & IW_AUTH_ALG_SHARED_KEY) && + (mode & IW_AUTH_ALG_OPEN_SYSTEM)) { + args[1] = IEEE80211_AUTH_AUTO; + } else if (mode & IW_AUTH_ALG_SHARED_KEY) { + args[1] = IEEE80211_AUTH_SHARED; + } else { + args[1] = IEEE80211_AUTH_OPEN; + } + return ieee80211_ioctl_setparam(dev, NULL, NULL, (char*)args); } static int @@ -3969,23 +3987,20 @@ return ieee80211_ioctl_setparam(dev, NULL, NULL, (char*)args); } -/* - * The wext API says that user space gets to decide whether EAPOL frames are - * supposed to be encrypted or in cleartext. The code in WPA supplicant - * indicates that if the AP is using 802.1x authentication but not WPA for - * key mgmt the eapol frames should be encrypted. However, even if I set - * up my AP (linkys WRT54G, fw 1.00.2) for that config, it sends eapol frames - * in the clear. I'm uncertain whether my AP is violating the specification, - * or if wpa_supplicant is doing the wrong thing. But if I let wpa_supplicant - * tell madwifi to drop unencrypted eapol frames, it breaks the authentication. - * - * Thus, madwifi ignores this parameter. - */ static int siwauth_rx_unencrypted_eapol(struct net_device *dev, struct iw_request_info *info, struct iw_param *erq, char *buf) { - return -EOPNOTSUPP; + int rxunenc = erq->value; + int args[2]; + + args[0] = IEEE80211_PARAM_DROPUNENC_EAPOL; + if (rxunenc) + args[1] = 1; + else + args[1] = 0; + + return ieee80211_ioctl_setparam(dev, NULL, NULL, (char*)args); } static int @@ -4765,6 +4780,10 @@ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "regclass" }, { IEEE80211_PARAM_REGCLASS, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_regclass" }, + { IEEE80211_PARAM_DROPUNENC_EAPOL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dropunenceapol" }, + { IEEE80211_PARAM_DROPUNENC_EAPOL, + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_dropunencea" }, /* * NB: these should be roamrssi* etc, but iwpriv usurps all * strings that start with roam! |