add vendor VSA to set additional key and IGTK support
IGTK == Management Frame Protection
This commit is contained in:
parent
ac135e16c4
commit
a488af66cf
@ -423,6 +423,23 @@ struct ieee80211_ie_erp {
|
||||
/* 802.11 RSN information element */
|
||||
#define IEEE80211_IE_RSN_INFORMATION 48
|
||||
|
||||
|
||||
/* cipher suite selectors */
|
||||
#define IEEE80211_CIPHER_SUITE_USE_GROUP 0x000FAC00
|
||||
#define IEEE80211_CIPHER_SUITE_WEP40 0x000FAC01
|
||||
#define IEEE80211_CIPHER_SUITE_TKIP 0x000FAC02
|
||||
/* reserved: 0x000FAC03 */
|
||||
#define IEEE80211_CIPHER_SUITE_CCMP 0x000FAC04
|
||||
#define IEEE80211_CIPHER_SUITE_WEP104 0x000FAC05
|
||||
#define IEEE80211_CIPHER_SUITE_AES_CMAC 0x000FAC06
|
||||
#define IEEE80211_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
|
||||
#define IEEE80211_CIPHER_SUITE_GCMP 0x000FAC08
|
||||
#define IEEE80211_CIPHER_SUITE_GCMP_256 0x000FAC09
|
||||
#define IEEE80211_CIPHER_SUITE_CCMP_256 0x000FAC0A
|
||||
#define IEEE80211_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B
|
||||
#define IEEE80211_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C
|
||||
#define IEEE80211_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D
|
||||
|
||||
/* 802.11 Extended Supported Rates information element */
|
||||
#define IEEE80211_IE_EXTENDED_SUPPORTED_RATES 50
|
||||
#define IEEE80211_IE_EXTENDED_SUPPORTED_MIN_LENGTH 1
|
||||
|
@ -94,7 +94,8 @@ static const struct capwap_message_elements_ops * capwap_vendor_travelping_messa
|
||||
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_WTP_TIMESTAMP_TYPE, capwap_element_vendor_travelping_wtp_timestamp_ops),
|
||||
element_ops(CAPWAP_ELEMENT_80211N_RADIO_CONF_TYPE, capwap_element_80211n_radioconf_ops),
|
||||
element_ops(CAPWAP_ELEMENT_80211N_STATION_INFO_TYPE, capwap_element_80211n_station_info_ops),
|
||||
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_TYPE, capwap_element_vendor_travelping_80211_encryption_capability_ops)
|
||||
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_ENCRYPTION_CAPABILITY_TYPE, capwap_element_vendor_travelping_80211_encryption_capability_ops),
|
||||
element_ops(CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_TYPE, capwap_element_vendor_travelping_80211_update_key_ops)
|
||||
};
|
||||
#undef element_ops
|
||||
|
||||
|
108
src/common/capwap_element_vendor_travelping_80211_update_key.c
Normal file
108
src/common/capwap_element_vendor_travelping_80211_update_key.c
Normal file
@ -0,0 +1,108 @@
|
||||
#include "capwap.h"
|
||||
#include "capwap_element.h"
|
||||
|
||||
/*
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Radio ID | WLAN ID | Key Index | Key Status |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Cipher Suite |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Key... |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* IEEE 802.11 Update Key
|
||||
*
|
||||
* Vendor Id: 18681 (Travelping GmbH)
|
||||
* Type: 19
|
||||
*
|
||||
* Length: >= 6
|
||||
*
|
||||
*/
|
||||
|
||||
/* */
|
||||
static void
|
||||
capwap_vendor_travelping_80211_update_key_element_create(void *data,
|
||||
capwap_message_elements_handle handle,
|
||||
struct capwap_write_message_elements_ops *func)
|
||||
{
|
||||
struct capwap_vendor_travelping_80211_update_key_element *element =
|
||||
(struct capwap_vendor_travelping_80211_update_key_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
|
||||
func->write_u8(handle, element->radioid);
|
||||
func->write_u8(handle, element->wlanid);
|
||||
func->write_u8(handle, element->keyindex);
|
||||
func->write_u8(handle, element->keystatus);
|
||||
func->write_u32(handle, element->ciphersuite);
|
||||
if (element->keylength > 0)
|
||||
func->write_block(handle, element->key, element->keylength);
|
||||
}
|
||||
|
||||
/* */
|
||||
static void *
|
||||
capwap_vendor_travelping_80211_update_key_element_parsing(capwap_message_elements_handle handle,
|
||||
struct capwap_read_message_elements_ops *func)
|
||||
{
|
||||
unsigned short length;
|
||||
struct capwap_vendor_travelping_80211_update_key_element *data;
|
||||
|
||||
ASSERT(handle != NULL);
|
||||
ASSERT(func != NULL);
|
||||
|
||||
length = func->read_ready(handle);
|
||||
if (length < 8) {
|
||||
log_printf(LOG_DEBUG, "Invalid Vendor Travelping IEEE 802.11 Update Key element");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length -= 8;
|
||||
|
||||
/* */
|
||||
data = (struct capwap_vendor_travelping_80211_update_key_element *)
|
||||
capwap_alloc(sizeof(struct capwap_vendor_travelping_80211_update_key_element) + length);
|
||||
memset(data, 0, sizeof(struct capwap_vendor_travelping_80211_update_key_element) + length);
|
||||
|
||||
/* Retrieve data */
|
||||
func->read_u8(handle, &data->radioid);
|
||||
func->read_u8(handle, &data->wlanid);
|
||||
func->read_u8(handle, &data->keyindex);
|
||||
func->read_u8(handle, &data->keystatus);
|
||||
func->read_u32(handle, &data->ciphersuite);
|
||||
data->keylength = length;
|
||||
func->read_block(handle, data->key, data->keylength);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* */
|
||||
static void *capwap_vendor_travelping_80211_update_key_element_clone(void *data)
|
||||
{
|
||||
struct capwap_vendor_travelping_80211_update_key_element *element =
|
||||
(struct capwap_vendor_travelping_80211_update_key_element*)data;
|
||||
|
||||
ASSERT(data != NULL);
|
||||
|
||||
return capwap_clone(data, sizeof(struct capwap_vendor_travelping_80211_update_key_element) +
|
||||
element->keylength);
|
||||
}
|
||||
|
||||
/* */
|
||||
static void capwap_vendor_travelping_80211_update_key_element_free(void *data)
|
||||
{
|
||||
ASSERT(data != NULL);
|
||||
|
||||
capwap_free(data);
|
||||
}
|
||||
|
||||
/* */
|
||||
const struct capwap_message_elements_ops capwap_element_vendor_travelping_80211_update_key_ops = {
|
||||
.category = CAPWAP_MESSAGE_ELEMENT_ARRAY,
|
||||
.create = capwap_vendor_travelping_80211_update_key_element_create,
|
||||
.parse = capwap_vendor_travelping_80211_update_key_element_parsing,
|
||||
.clone = capwap_vendor_travelping_80211_update_key_element_clone,
|
||||
.free = capwap_vendor_travelping_80211_update_key_element_free
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
#ifndef __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_HEADER__
|
||||
#define __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_HEADER__
|
||||
|
||||
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_VENDOR CAPWAP_VENDOR_TRAVELPING_ID
|
||||
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_TYPE 19
|
||||
#define CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY \
|
||||
(struct capwap_message_element_id){ \
|
||||
.vendor = CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_VENDOR, \
|
||||
.type = CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_TYPE \
|
||||
}
|
||||
|
||||
#define CAPWAP_UPDATE_WLAN_KEY_STATUS_REKEYING 2
|
||||
#define CAPWAP_UPDATE_WLAN_KEY_STATUS_COMPLETE 3
|
||||
|
||||
struct capwap_vendor_travelping_80211_update_key_element {
|
||||
uint8_t radioid;
|
||||
uint8_t wlanid;
|
||||
uint8_t keyindex;
|
||||
uint8_t keystatus;
|
||||
uint32_t ciphersuite;
|
||||
uint16_t keylength;
|
||||
uint8_t key[];
|
||||
};
|
||||
|
||||
extern const struct capwap_message_elements_ops capwap_element_vendor_travelping_80211_update_key_ops;
|
||||
|
||||
#endif /* __CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY_HEADER__ */
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "capwap_element_vendor_travelping_wtp_timestamp.h"
|
||||
#include "capwap_element_vendor_travelping_80211_encryption_capability.h"
|
||||
#include "capwap_element_vendor_travelping_80211_update_key.h"
|
||||
|
||||
/* draft-ietf-opsawg-capwap-extension-06 */
|
||||
#include "capwap_element_80211n_radioconf.h"
|
||||
|
@ -2123,6 +2123,41 @@ static struct ieee80211_ie *rsn_from_ie(uint8_t radioid, uint8_t wlanid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define broadcast_ether_addr (const uint8_t *) "\xff\xff\xff\xff\xff\xff"
|
||||
|
||||
static int update_keys(struct wifi_wlan* wlan, struct capwap_array *keys)
|
||||
{
|
||||
int i, result = 0;
|
||||
|
||||
log_printf(LOG_DEBUG, "Wifi Update Keys: %p", keys);
|
||||
if (!keys)
|
||||
return 0;
|
||||
|
||||
log_printf(LOG_DEBUG, "Wifi Update Keys: #%ld", keys->count);
|
||||
for (i = 0; i < keys->count; i++) {
|
||||
struct capwap_vendor_travelping_80211_update_key_element *key =
|
||||
*(struct capwap_vendor_travelping_80211_update_key_element **)
|
||||
capwap_array_get_item_pointer(keys, i);
|
||||
|
||||
log_printf(LOG_DEBUG, "Wifi Update Keys: Update: Status: %d, CipherSuite: %08x, Index: %d, Len: %d",
|
||||
key->keystatus, key->ciphersuite, key->keyindex, key->keylength);
|
||||
switch (key->keystatus) {
|
||||
case 3:
|
||||
result = wlan_set_key(wlan, key->ciphersuite, broadcast_ether_addr,
|
||||
key->keyindex, 1, NULL, 0,
|
||||
key->keylength ? key->key : NULL, key->keylength);
|
||||
|
||||
log_printf(LOG_INFO, "Update KEY on interface: %s, SSID: '%s', result: %d",
|
||||
wlan->virtname, wlan->ssid, result);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params)
|
||||
{
|
||||
@ -2167,18 +2202,19 @@ int wifi_wlan_startap(struct wifi_wlan* wlan, struct wlan_startap_params* params
|
||||
|
||||
/* Start AP */
|
||||
result = wlan_startap(wlan);
|
||||
if (!result) {
|
||||
wlan->device->wlanactive++;
|
||||
log_printf(LOG_INFO, "Configured interface: %s, SSID: '%s'", wlan->virtname, wlan->ssid);
|
||||
} else {
|
||||
if (result) {
|
||||
wifi_wlan_stopap(wlan);
|
||||
return result;
|
||||
}
|
||||
|
||||
update_keys(wlan, params->updatekeys);
|
||||
|
||||
wlan->device->wlanactive++;
|
||||
log_printf(LOG_INFO, "Configured interface: %s, SSID: '%s'", wlan->virtname, wlan->ssid);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define broadcast_ether_addr (const uint8_t *) "\xff\xff\xff\xff\xff\xff"
|
||||
|
||||
/* */
|
||||
int wifi_wlan_updateap(struct wifi_wlan* wlan, struct wlan_updateap_params* params)
|
||||
{
|
||||
@ -2237,6 +2273,9 @@ int wifi_wlan_updateap(struct wifi_wlan* wlan, struct wlan_updateap_params* para
|
||||
break;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
update_keys(wlan, params->updatekeys);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,7 @@ struct wlan_startap_params {
|
||||
uint8_t *key;
|
||||
|
||||
struct capwap_array *ie;
|
||||
struct capwap_array *updatekeys;
|
||||
};
|
||||
|
||||
struct wlan_updateap_params {
|
||||
@ -118,6 +119,7 @@ struct wlan_updateap_params {
|
||||
uint8_t *key;
|
||||
|
||||
struct capwap_array *ie;
|
||||
struct capwap_array *updatekeys;
|
||||
};
|
||||
|
||||
/* */
|
||||
|
@ -1060,7 +1060,12 @@ static int nl80211_set_key(struct wifi_wlan* wlan,
|
||||
msg = nl80211_wlan_msg(wlan, 0, NL80211_CMD_SET_KEY);
|
||||
if (!msg ||
|
||||
nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) ||
|
||||
nla_put_flag(msg, NL80211_ATTR_KEY_DEFAULT))
|
||||
nla_put_flag(msg, (alg == IEEE80211_CIPHER_SUITE_AES_CMAC ||
|
||||
alg == IEEE80211_CIPHER_SUITE_BIP_GMAC_128 ||
|
||||
alg == IEEE80211_CIPHER_SUITE_BIP_GMAC_256 ||
|
||||
alg == IEEE80211_CIPHER_SUITE_BIP_CMAC_256) ?
|
||||
NL80211_ATTR_KEY_DEFAULT_MGMT :
|
||||
NL80211_ATTR_KEY_DEFAULT))
|
||||
goto fail;
|
||||
|
||||
types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
|
||||
|
@ -652,6 +652,47 @@ void wtp_radio_receive_data_packet(uint8_t radioid, unsigned short binding, cons
|
||||
}
|
||||
}
|
||||
|
||||
static struct capwap_array *wtp_radio_set_update_keys(struct capwap_parsed_packet *packet,
|
||||
uint8_t radioid, uint8_t wlanid)
|
||||
{
|
||||
int i;
|
||||
struct capwap_array *keys;
|
||||
struct capwap_array *updatekeys = NULL;
|
||||
|
||||
ASSERT(packet != NULL);
|
||||
|
||||
keys = (struct capwap_array *)
|
||||
capwap_get_message_element_data(packet, CAPWAP_ELEMENT_VENDOR_TRAVELPING_80211_UPDATE_KEY);
|
||||
log_printf(LOG_DEBUG, "Set Update Keys: %p", keys);
|
||||
if (!keys)
|
||||
return NULL;
|
||||
|
||||
log_printf(LOG_DEBUG, "Set Update Keys: #%ld", keys->count);
|
||||
for (i = 0; i < keys->count; i++) {
|
||||
struct capwap_vendor_travelping_80211_update_key_element *key =
|
||||
*(struct capwap_vendor_travelping_80211_update_key_element **)
|
||||
capwap_array_get_item_pointer(keys, i);
|
||||
|
||||
log_printf(LOG_DEBUG, "RadioId: %d .. %d, WlanId: %d .. %d",
|
||||
key->radioid, radioid,
|
||||
key->wlanid, wlanid);
|
||||
|
||||
if (key->radioid != radioid || key->wlanid != wlanid)
|
||||
continue;
|
||||
|
||||
if (!updatekeys)
|
||||
updatekeys = capwap_array_create(sizeof(void *), 0, 0);
|
||||
if (!updatekeys) {
|
||||
log_printf(LOG_DEBUG, "Update WLAN: Out of Memory");
|
||||
return NULL;
|
||||
}
|
||||
*(void **)capwap_array_get_item_pointer(updatekeys, updatekeys->count) = key;
|
||||
log_printf(LOG_DEBUG, "Set Update Keys: Update #%ld", updatekeys->count);
|
||||
}
|
||||
|
||||
return updatekeys;
|
||||
}
|
||||
|
||||
/* source http://stackoverflow.com/a/16994674 */
|
||||
static uint16_t reverse(register uint16_t x)
|
||||
{
|
||||
@ -721,6 +762,7 @@ uint32_t wtp_radio_create_wlan(struct capwap_parsed_packet* packet,
|
||||
params.key = addwlan->key;
|
||||
|
||||
params.ie = (struct capwap_array *)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE);
|
||||
params.updatekeys = wtp_radio_set_update_keys(packet, addwlan->radioid, addwlan->wlanid);
|
||||
|
||||
/* Start AP */
|
||||
if (wifi_wlan_startap(wlan->wlanhandle, ¶ms)) {
|
||||
@ -788,6 +830,7 @@ uint32_t wtp_radio_update_wlan(struct capwap_parsed_packet* packet)
|
||||
params.key = updatewlan->key;
|
||||
|
||||
params.ie = (struct capwap_array *)capwap_get_message_element_data(packet, CAPWAP_ELEMENT_80211_IE);
|
||||
params.updatekeys = wtp_radio_set_update_keys(packet, updatewlan->radioid, updatewlan->wlanid);
|
||||
|
||||
/* Update AP */
|
||||
if (wifi_wlan_updateap(wlan->wlanhandle, ¶ms)) {
|
||||
|
Loading…
Reference in New Issue
Block a user