aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-01-14 23:21:55 (GMT)
committerJouni Malinen <j@w1.fi>2009-01-14 23:21:55 (GMT)
commit11ef8d3578f0c57d9503bbee97cbb8e5c0c42207 (patch)
tree3b517a406bd104fd007d7568b23f0edb09bf91f3 /wpa_supplicant
parent4bb081f1b457b958ad735f1b4c01074bc816c909 (diff)
downloadhostap-11ef8d3578f0c57d9503bbee97cbb8e5c0c42207.zip
hostap-11ef8d3578f0c57d9503bbee97cbb8e5c0c42207.tar.gz
hostap-11ef8d3578f0c57d9503bbee97cbb8e5c0c42207.tar.bz2
Added initial step for IBSS RSN support
This commit adds a new build option, CONFIG_IBSS_RSN=y, that can be used to enable RSN support for IBSS. This links in RSN Authenticator code from hostapd and adds code for managing per-peer information for IBSS. A new wpa_cli command or driver event can be used to request RSN authentication with an IBSS peer. New RSN Authenticator and Supplicant will be allocated for each peer. The basic state machine setup code is included in this commit, but the state machines are not properly started yet. In addition, some of the callback functions are not yet complete.
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/Makefile15
-rw-r--r--wpa_supplicant/ctrl_iface.c26
-rw-r--r--wpa_supplicant/events.c17
-rw-r--r--wpa_supplicant/ibss_rsn.c319
-rw-r--r--wpa_supplicant/ibss_rsn.h40
-rw-r--r--wpa_supplicant/wpa_cli.c23
-rw-r--r--wpa_supplicant/wpa_supplicant.c14
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h3
8 files changed, 457 insertions, 0 deletions
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index c5a8132..65adf53 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -941,6 +941,21 @@ else
CFLAGS += -DCONFIG_NO_WPA -DCONFIG_NO_WPA2
endif
+ifdef CONFIG_IBSS_RSN
+CFLAGS += -DCONFIG_IBSS_RSN
+OBJS += ibss_rsn.o
+OBJS += ../hostapd/wpa.o
+OBJS += ../hostapd/wpa_auth_ie.o
+OBJS += ../hostapd/pmksa_cache.o
+OBJS += ../src/radius/radius.o
+ifdef CONFIG_IEEE80211R
+OBJS += ../hostapd/wpa_ft.o
+endif
+ifdef CONFIG_PEERKEY
+OBJS += ../hostapd/peerkey.o
+endif
+endif
+
ifdef CONFIG_NO_WPA2
CFLAGS += -DCONFIG_NO_WPA2
endif
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index d627dc6..7bb871a 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -29,6 +29,7 @@
#include "ieee802_11_defs.h"
#include "wps_supplicant.h"
#include "wps/wps.h"
+#include "ibss_rsn.h"
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
char *buf, int len);
@@ -227,6 +228,26 @@ static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_WPS */
+#ifdef CONFIG_IBSS_RSN
+static int wpa_supplicant_ctrl_iface_ibss_rsn(
+ struct wpa_supplicant *wpa_s, char *addr)
+{
+ u8 peer[ETH_ALEN];
+
+ if (hwaddr_aton(addr, peer)) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
+ "address '%s'", peer);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
+ MAC2STR(peer));
+
+ return ibss_rsn_start(wpa_s->ibss_rsn, peer);
+}
+#endif /* CONFIG_IBSS_RSN */
+
+
static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
char *rsp)
{
@@ -1566,6 +1587,11 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
reply_len = -1;
#endif /* CONFIG_WPS */
+#ifdef CONFIG_IBSS_RSN
+ } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
+ if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
+ reply_len = -1;
+#endif /* CONFIG_IBSS_RSN */
} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
{
if (wpa_supplicant_ctrl_iface_ctrl_rsp(
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 32b87e9..e169949 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -32,6 +32,7 @@
#include "blacklist.h"
#include "wpas_glue.h"
#include "wps_supplicant.h"
+#include "ibss_rsn.h"
static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
@@ -1067,6 +1068,17 @@ wpa_supplicant_event_ft_response(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IBSS_RSN
+static void wpa_supplicant_event_ibss_rsn_start(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ if (data == NULL)
+ return;
+ ibss_rsn_start(wpa_s->ibss_rsn, data->ibss_rsn_start.peer);
+}
+#endif /* CONFIG_IBSS_RSN */
+
+
void wpa_supplicant_event(void *ctx, wpa_event_type event,
union wpa_event_data *data)
{
@@ -1106,6 +1118,11 @@ void wpa_supplicant_event(void *ctx, wpa_event_type event,
wpa_supplicant_event_ft_response(wpa_s, data);
break;
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IBSS_RSN
+ case EVENT_IBSS_RSN_START:
+ wpa_supplicant_event_ibss_rsn_start(wpa_s, data);
+ break;
+#endif /* CONFIG_IBSS_RSN */
default:
wpa_printf(MSG_INFO, "Unknown event %d", event);
break;
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
new file mode 100644
index 0000000..691a84e
--- /dev/null
+++ b/wpa_supplicant/ibss_rsn.c
@@ -0,0 +1,319 @@
+/*
+ * wpa_supplicant - IBSS RSN
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "wpa_supplicant_i.h"
+#include "wpa.h"
+#include "wpa_ie.h"
+#include "../hostapd/wpa.h"
+#include "ibss_rsn.h"
+
+
+static void ibss_rsn_free(struct ibss_rsn_peer *peer)
+{
+ wpa_auth_sta_deinit(peer->auth);
+ wpa_sm_deinit(peer->supp);
+ os_free(peer);
+}
+
+
+static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
+ size_t len)
+{
+ /* struct ibss_rsn_peer *peer = ctx; */
+
+ wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x "
+ "len=%lu)",
+ __func__, MAC2STR(dest), proto, (unsigned long) len);
+
+ /* TODO: send EAPOL frame */
+
+ return 0;
+}
+
+
+static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data,
+ u16 data_len, size_t *msg_len, void **data_pos)
+{
+ struct ieee802_1x_hdr *hdr;
+
+ wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)",
+ __func__, type, data_len);
+
+ *msg_len = sizeof(*hdr) + data_len;
+ hdr = os_malloc(*msg_len);
+ if (hdr == NULL)
+ return NULL;
+
+ hdr->version = 2;
+ hdr->type = type;
+ hdr->length = host_to_be16(data_len);
+
+ if (data)
+ os_memcpy(hdr + 1, data, data_len);
+ else
+ os_memset(hdr + 1, 0, data_len);
+
+ if (data_pos)
+ *data_pos = hdr + 1;
+
+ return (u8 *) hdr;
+}
+
+
+static int supp_get_beacon_ie(void *ctx)
+{
+ wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
+ /* TODO */
+ return -1;
+}
+
+
+static int supp_set_key(void *ctx, wpa_alg alg,
+ const u8 *addr, int key_idx, int set_tx,
+ const u8 *seq, size_t seq_len,
+ const u8 *key, size_t key_len)
+{
+ wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d "
+ "set_tx=%d)",
+ __func__, alg, MAC2STR(addr), key_idx, set_tx);
+ wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len);
+ wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len);
+ return 0;
+}
+
+
+static int supp_mlme_setprotection(void *ctx, const u8 *addr,
+ int protection_type, int key_type)
+{
+ wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d "
+ "key_type=%d)",
+ __func__, MAC2STR(addr), protection_type, key_type);
+ return 0;
+}
+
+
+static void supp_cancel_auth_timeout(void *ctx)
+{
+ wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
+}
+
+
+int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr,
+ const u8 *psk)
+{
+ struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx));
+ if (ctx == NULL)
+ return -1;
+
+ ctx->ctx = peer;
+ ctx->ether_send = supp_ether_send;
+ ctx->get_beacon_ie = supp_get_beacon_ie;
+ ctx->alloc_eapol = supp_alloc_eapol;
+ ctx->set_key = supp_set_key;
+ ctx->mlme_setprotection = supp_mlme_setprotection;
+ ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
+ peer->supp = wpa_sm_init(ctx);
+ if (peer->supp == NULL) {
+ wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
+ return -1;
+ }
+
+ wpa_sm_set_own_addr(peer->supp, own_addr);
+ wpa_sm_set_param(peer->supp, WPA_PARAM_RSN_ENABLED, 1);
+ wpa_sm_set_param(peer->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN);
+ wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP);
+ wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
+ wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK);
+ wpa_sm_set_pmk(peer->supp, psk, PMK_LEN);
+
+#if 0 /* TODO? */
+ peer->supp_ie_len = sizeof(peer->supp_ie);
+ if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie,
+ &peer->supp_ie_len) < 0) {
+ wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()"
+ " failed");
+ return -1;
+ }
+#endif
+
+ wpa_sm_notify_assoc(peer->supp, peer->addr);
+
+ return 0;
+}
+
+
+static void auth_logger(void *ctx, const u8 *addr, logger_level level,
+ const char *txt)
+{
+ if (addr)
+ wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s",
+ MAC2STR(addr), txt);
+ else
+ wpa_printf(MSG_DEBUG, "AUTH: %s", txt);
+}
+
+
+static const u8 * auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk)
+{
+ struct ibss_rsn *ibss_rsn = ctx;
+ wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
+ __func__, MAC2STR(addr), prev_psk);
+ if (prev_psk)
+ return NULL;
+ return ibss_rsn->psk;
+}
+
+
+static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data,
+ size_t data_len, int encrypt)
+{
+ /* struct ibss_rsn *ibss_rsn = ctx; */
+
+ wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu "
+ "encrypt=%d)",
+ __func__, MAC2STR(addr), (unsigned long) data_len, encrypt);
+
+ /* TODO: send EAPOL frame */
+
+ return 0;
+}
+
+
+static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn,
+ const u8 *own_addr)
+{
+ struct wpa_auth_config conf;
+ struct wpa_auth_callbacks cb;
+
+ wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
+
+ os_memset(&conf, 0, sizeof(conf));
+ conf.wpa = 2;
+ conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK;
+ conf.wpa_pairwise = WPA_CIPHER_CCMP;
+ conf.rsn_pairwise = WPA_CIPHER_CCMP;
+ conf.wpa_group = WPA_CIPHER_CCMP;
+ conf.eapol_version = 2;
+
+ os_memset(&cb, 0, sizeof(cb));
+ cb.ctx = ibss_rsn;
+ cb.logger = auth_logger;
+ cb.send_eapol = auth_send_eapol;
+ cb.get_psk = auth_get_psk;
+
+ ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb);
+ if (ibss_rsn->auth_group == NULL) {
+ wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn,
+ struct ibss_rsn_peer *peer)
+{
+ peer->auth = wpa_auth_sta_init(ibss_rsn->auth_group, peer->addr);
+ if (peer->auth == NULL) {
+ wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed");
+ return -1;
+ }
+
+#if 0 /* TODO: get peer RSN IE with Probe Request */
+ if (wpa_validate_wpa_ie(ibss_rsn->auth_group, peer->auth, PEER_IE,
+ PEER_IE_LEN, NULL, 0) != WPA_IE_OK) {
+ wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed");
+ return -1;
+ }
+#endif
+
+ wpa_auth_sm_event(peer->auth, WPA_ASSOC);
+
+ wpa_auth_sta_associated(ibss_rsn->auth_group, peer->auth);
+
+ return 0;
+}
+
+
+int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr)
+{
+ struct ibss_rsn_peer *peer;
+
+ wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Authenticator and "
+ "Supplicant for peer " MACSTR, MAC2STR(addr));
+
+ peer = os_zalloc(sizeof(*peer));
+ if (peer == NULL)
+ return -1;
+
+ os_memcpy(peer->addr, addr, ETH_ALEN);
+
+ if (ibss_rsn_supp_init(peer, ibss_rsn->wpa_s->own_addr, ibss_rsn->psk)
+ < 0) {
+ ibss_rsn_free(peer);
+ return -1;
+ }
+
+ if (ibss_rsn_auth_init(ibss_rsn, peer) < 0) {
+ ibss_rsn_free(peer);
+ return -1;
+ }
+
+ peer->next = ibss_rsn->peers;
+ ibss_rsn->peers = peer;
+
+ return 0;
+}
+
+
+struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s)
+{
+ struct ibss_rsn *ibss_rsn;
+
+ ibss_rsn = os_zalloc(sizeof(*ibss_rsn));
+ if (ibss_rsn == NULL)
+ return NULL;
+ ibss_rsn->wpa_s = wpa_s;
+
+ if (ibss_rsn_auth_init_group(ibss_rsn, wpa_s->own_addr) < 0) {
+ ibss_rsn_deinit(ibss_rsn);
+ return NULL;
+ }
+
+ return ibss_rsn;
+}
+
+
+void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn)
+{
+ struct ibss_rsn_peer *peer, *prev;
+
+ if (ibss_rsn == NULL)
+ return;
+
+ peer = ibss_rsn->peers;
+ while (peer) {
+ prev = peer;
+ peer = peer->next;
+ ibss_rsn_free(prev);
+ }
+
+ wpa_deinit(ibss_rsn->auth_group);
+ os_free(ibss_rsn);
+
+}
diff --git a/wpa_supplicant/ibss_rsn.h b/wpa_supplicant/ibss_rsn.h
new file mode 100644
index 0000000..d301907
--- /dev/null
+++ b/wpa_supplicant/ibss_rsn.h
@@ -0,0 +1,40 @@
+/*
+ * wpa_supplicant - IBSS RSN
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef IBSS_RSN_H
+#define IBSS_RSN_H
+
+struct ibss_rsn_peer {
+ struct ibss_rsn_peer *next;
+
+ u8 addr[ETH_ALEN];
+
+ struct wpa_sm *supp;
+
+ struct wpa_state_machine *auth;
+};
+
+struct ibss_rsn {
+ struct wpa_supplicant *wpa_s;
+ struct wpa_authenticator *auth_group;
+ struct ibss_rsn_peer *peers;
+ u8 psk[PMK_LEN];
+};
+
+
+struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s);
+void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn);
+int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr);
+
+#endif /* IBSS_RSN_H */
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index c49b674..791155d 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -465,6 +465,26 @@ static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ if (argc != 1) {
+ printf("Invalid IBSS_RSN command: needs one argument "
+ "(Peer STA MAC address)\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
+ if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ printf("Too long IBSS_RSN command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
@@ -1239,6 +1259,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "wps_reg", wpa_cli_cmd_wps_reg,
cli_cmd_flag_sensitive,
"<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
+ { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
+ cli_cmd_flag_none,
+ "<addr> = request RSN authentication with <addr> in IBSS" },
{ NULL, NULL, cli_cmd_flag_none, NULL }
};
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index d2c4552..71daf8d 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -39,6 +39,7 @@
#include "blacklist.h"
#include "wpas_glue.h"
#include "wps_supplicant.h"
+#include "ibss_rsn.h"
const char *wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
@@ -385,6 +386,11 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
ieee80211_sta_deinit(wpa_s);
wpas_wps_deinit(wpa_s);
+
+#ifdef CONFIG_IBSS_RSN
+ ibss_rsn_deinit(wpa_s->ibss_rsn);
+ wpa_s->ibss_rsn = NULL;
+#endif /* CONFIG_IBSS_RSN */
}
@@ -1859,6 +1865,14 @@ static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s)
wpa_s->driver_4way_handshake = 1;
}
+#ifdef CONFIG_IBSS_RSN
+ wpa_s->ibss_rsn = ibss_rsn_init(wpa_s);
+ if (!wpa_s->ibss_rsn) {
+ wpa_printf(MSG_DEBUG, "Failed to init IBSS RSN");
+ return -1;
+ }
+#endif /* CONFIG_IBSS_RSN */
+
return 0;
}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index f39709f..c629a7e 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -33,6 +33,7 @@ extern struct wpa_driver_ops *wpa_supplicant_drivers[];
struct wpa_scan_result;
struct wpa_sm;
struct wpa_supplicant;
+struct ibss_rsn;
/*
* Forward declarations of private structures used within the ctrl_iface
@@ -355,6 +356,8 @@ struct wpa_supplicant {
int mic_errors_seen; /* Michael MIC errors with the current PTK */
struct wps_context *wps;
+
+ struct ibss_rsn *ibss_rsn;
};