diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index c0ba19b5db89..7f30c3b95245 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -69,24 +69,36 @@ static struct ieee80211_channel *findchannel(struct ieee80211com *, static int ieee80211_scanreq(struct ieee80211vap *, struct ieee80211_scan_req *); +/* + * Read the key out into userland. + * + * Enforce that userland supplied a large enough buffer for the given + * key. + */ static int ieee80211_ioctl_getkey(u_long cmd, struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; - struct ieee80211req_key ik; + struct ieee80211req_key_hdr ik, *ikh; struct ieee80211_key *wk; const struct ieee80211_cipher *cip; u_int kid; int error; + /* Check we have a minimum size for the key header */ if (ireq->i_len != sizeof(ik)) return EINVAL; + + /* Copy in the header contents */ error = copyin(ireq->i_data, &ik, sizeof(ik)); if (error) return error; + kid = ik.ik_keyix; + + /* Handle the fixed unicast key, or the group/WEP key index */ if (kid == IEEE80211_KEYIX_NONE) { ni = ieee80211_find_vap_node(&ic->ic_sta, vap, ik.ik_macaddr); if (ni == NULL) @@ -99,12 +111,16 @@ ieee80211_ioctl_getkey(u_long cmd, struct ieee80211vap *vap, IEEE80211_ADDR_COPY(&ik.ik_macaddr, vap->iv_bss->ni_macaddr); ni = NULL; } + + /* Look up the cipher, fetch in the cipher key length */ cip = wk->wk_cipher; ik.ik_type = cip->ic_cipher; ik.ik_keylen = wk->wk_keylen; ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); if (wk->wk_keyix == vap->iv_def_txkey) ik.ik_flags |= IEEE80211_KEY_DEFAULT; + + /* Copy out the key contents, or a blank key */ if (ieee80211_priv_check_vap_getkey(cmd, vap, NULL) == 0) { /* NB: only root can read key data */ ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID]; diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index 7d11d708f4b8..fcc054941bdb 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -279,6 +279,21 @@ struct ieee80211_stats { #define IEEE80211_IOCTL_KEYDATA_SIZE \ (IEEE80211_IOCTL_KEYBUF_SIZE + IEEE80211_IOCTL_MICBUF_SIZE) +struct ieee80211req_key_hdr { + uint8_t ik_type; /* key/cipher type */ + uint8_t ik_pad; + uint16_t ik_keyix; /* key index */ + uint8_t ik_keylen; /* key length in bytes */ + uint8_t ik_flags; + uint8_t ik_macaddr[IEEE80211_ADDR_LEN]; + uint64_t ik_keyrsc; /* key receive sequence counter */ + uint64_t ik_keytsc; /* key transmit sequence counter */ +}; + +#define IEEE80211_REQ_KEY_SIZE(keylen, miclen) \ + (sizeof(struct ieee80211req_key_hdr) + \ + (keylen) + (miclen)) + struct ieee80211req_key { uint8_t ik_type; /* key/cipher type */ uint8_t ik_pad;