wpa: Import wpa 2.10 (second part)

WPA is in fact two distfiles. Import the second distfile.
This commit is contained in:
Cy Schubert 2022-01-17 13:12:36 -08:00
parent 03f33dd077
commit df0c787c3e
234 changed files with 170785 additions and 0 deletions

81
hs20/client/Android.mk Normal file
View File

@ -0,0 +1,81 @@
LOCAL_PATH := $(call my-dir)
INCLUDES = $(LOCAL_PATH)
INCLUDES += $(LOCAL_PATH)/../../src/utils
INCLUDES += $(LOCAL_PATH)/../../src/common
INCLUDES += $(LOCAL_PATH)/../../src
INCLUDES += external/libxml2/include
INCLUDES += external/curl/include
INCLUDES += external/webkit/Source/WebKit/gtk
# We try to keep this compiling against older platform versions.
# The new icu location (external/icu) exports its own headers, but
# the older versions in external/icu4c don't, and we need to add those
# headers to the include path by hand.
ifeq ($(wildcard external/icu),)
INCLUDES += external/icu4c/common
else
# The LOCAL_EXPORT_C_INCLUDE_DIRS from ICU did not seem to fully resolve the
# build (e.g., "mm -B" failed to build, but following that with "mm" allowed
# the build to complete). For now, add the include directory manually here for
# Android 5.0.
ver = $(filter 5.0%,$(PLATFORM_VERSION))
ifneq (,$(strip $(ver)))
INCLUDES += external/icu/icu4c/source/common
endif
endif
L_CFLAGS += -DCONFIG_CTRL_IFACE
L_CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
OBJS = spp_client.c
OBJS += oma_dm_client.c
OBJS += osu_client.c
OBJS += est.c
OBJS += ../../src/common/wpa_ctrl.c
OBJS += ../../src/common/wpa_helpers.c
OBJS += ../../src/utils/xml-utils.c
#OBJS += ../../src/utils/browser-android.c
OBJS += ../../src/utils/browser-wpadebug.c
OBJS += ../../src/utils/wpabuf.c
OBJS += ../../src/utils/eloop.c
OBJS += ../../src/wps/httpread.c
OBJS += ../../src/wps/http_server.c
OBJS += ../../src/utils/xml_libxml2.c
OBJS += ../../src/utils/http_curl.c
OBJS += ../../src/utils/base64.c
OBJS += ../../src/utils/os_unix.c
L_CFLAGS += -DCONFIG_DEBUG_FILE
OBJS += ../../src/utils/wpa_debug.c
OBJS += ../../src/utils/common.c
OBJS += ../../src/crypto/crypto_internal.c
OBJS += ../../src/crypto/md5-internal.c
OBJS += ../../src/crypto/sha1-internal.c
OBJS += ../../src/crypto/sha256-internal.c
OBJS += ../../src/crypto/tls_openssl_ocsp.c
L_CFLAGS += -DEAP_TLS_OPENSSL
L_CFLAGS += -Wno-unused-parameter
########################
include $(CLEAR_VARS)
LOCAL_MODULE := hs20-osu-client
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := libc libcutils
LOCAL_SHARED_LIBRARIES += libcrypto libssl
#LOCAL_SHARED_LIBRARIES += libxml2
LOCAL_STATIC_LIBRARIES += libxml2
LOCAL_SHARED_LIBRARIES += libicuuc
LOCAL_SHARED_LIBRARIES += libcurl
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(OBJS)
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)
########################

81
hs20/client/Makefile Normal file
View File

@ -0,0 +1,81 @@
ALL=hs20-osu-client
include ../../src/build.rules
CFLAGS += -I../../src/utils
CFLAGS += -I../../src/common
CFLAGS += -I../../src
ifndef CONFIG_NO_BROWSER
ifndef CONFIG_BROWSER_SYSTEM
TEST_WK := $(shell pkg-config --silence-errors --cflags webkitgtk-3.0)
ifeq ($(TEST_WK),)
# Try webkit2
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkit2gtk-4.0)
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkit2gtk-4.0)
CFLAGS += -DUSE_WEBKIT2
else
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0)
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0)
endif
CFLAGS += $(GTKCFLAGS)
LIBS += $(GTKLIBS)
endif
endif
OBJS=spp_client.o
OBJS += oma_dm_client.o
OBJS += osu_client.o
OBJS += est.o
OBJS += ../../src/utils/xml-utils.o
CFLAGS += -DCONFIG_CTRL_IFACE
CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
OBJS += ../../src/common/wpa_ctrl.o ../../src/common/wpa_helpers.o
ifdef CONFIG_NO_BROWSER
CFLAGS += -DCONFIG_NO_BROWSER
else
ifdef CONFIG_BROWSER_SYSTEM
OBJS += ../../src/utils/eloop.o
OBJS += ../../src/utils/wpabuf.o
OBJS += ../../src/wps/httpread.o
OBJS += ../../src/wps/http_server.o
OBJS += ../../src/utils/browser-system.o
else
OBJS += ../../src/utils/browser.o
endif
endif
OBJS += ../../src/utils/xml_libxml2.o
OBJS += ../../src/utils/http_curl.o
OBJS += ../../src/utils/base64.o
OBJS += ../../src/utils/os_unix.o
CFLAGS += -DCONFIG_DEBUG_FILE
OBJS += ../../src/utils/wpa_debug.o
OBJS += ../../src/utils/common.o
OBJS += ../../src/crypto/crypto_internal.o
OBJS += ../../src/crypto/md5-internal.o
OBJS += ../../src/crypto/sha1-internal.o
OBJS += ../../src/crypto/sha256-internal.o
CFLAGS += $(shell xml2-config --cflags)
LIBS += $(shell xml2-config --libs)
# Allow static/custom linking of libcurl.
ifdef CUST_CURL_LINKAGE
LIBS += ${CUST_CURL_LINKAGE}
else
LIBS += -lcurl
endif
CFLAGS += -DEAP_TLS_OPENSSL
OBJS += ../../src/crypto/tls_openssl_ocsp.o
LIBS += -lssl -lcrypto
_OBJS_VAR := OBJS
include ../../src/objs.mk
hs20-osu-client: $(OBJS)
$(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS)
@$(E) " LD " $@
clean: common-clean
rm -f core *~

47
hs20/client/devdetail.xml Normal file
View File

@ -0,0 +1,47 @@
<DevDetail xmlns="urn:oma:mo:oma-dm-devdetail:1.0">
<Ext>
<org.wi-fi>
<Wi-Fi>
<EAPMethodList>
<EAPMethod1>
<EAPType>13</EAPType>
</EAPMethod1>
<EAPMethod2>
<EAPType>21</EAPType>
<InnerMethod>MS-CHAP-V2</InnerMethod>
</EAPMethod2>
<EAPMethod3>
<EAPType>18</EAPType>
</EAPMethod3>
<EAPMethod4>
<EAPType>23</EAPType>
</EAPMethod4>
<EAPMethod5>
<EAPType>50</EAPType>
</EAPMethod5>
</EAPMethodList>
<ManufacturingCertificate>false</ManufacturingCertificate>
<Wi-FiMACAddress>020102030405</Wi-FiMACAddress>
<IMSI>310026000000000</IMSI>
<IMEI_MEID>imei:490123456789012</IMEI_MEID>
<ClientTriggerRedirectURI>http://localhost:12345/</ClientTriggerRedirectURI>
<Ops>
<launchBrowserToURI></launchBrowserToURI>
<negotiateClientCertTLS></negotiateClientCertTLS>
<getCertificate></getCertificate>
</Ops>
</Wi-Fi>
</org.wi-fi>
</Ext>
<URI>
<MaxDepth>0</MaxDepth>
<MaxTotLen>0</MaxTotLen>
<MaxSegLen>0</MaxSegLen>
</URI>
<DevType>MobilePhone</DevType>
<OEM>Manufacturer</OEM>
<FwV>1.0</FwV>
<SwV>1.0</SwV>
<HwV>1.0</HwV>
<LrgObj>false</LrgObj>
</DevDetail>

7
hs20/client/devinfo.xml Normal file
View File

@ -0,0 +1,7 @@
<DevInfo xmlns="urn:oma:mo:oma-dm-devinfo:1.0">
<DevId>urn:Example:HS20-station:123456</DevId>
<Man>Manufacturer</Man>
<Mod>HS20-station</Mod>
<DmV>1.2</DmV>
<Lang>en</Lang>
</DevInfo>

769
hs20/client/est.c Normal file
View File

@ -0,0 +1,769 @@
/*
* Hotspot 2.0 OSU client - EST client
* Copyright (c) 2012-2014, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/pkcs7.h>
#include <openssl/rsa.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/opensslv.h>
#ifdef OPENSSL_IS_BORINGSSL
#include <openssl/buf.h>
#endif /* OPENSSL_IS_BORINGSSL */
#include "common.h"
#include "utils/base64.h"
#include "utils/xml-utils.h"
#include "utils/http-utils.h"
#include "osu_client.h"
static int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7,
size_t len, char *pem_file, char *der_file)
{
#ifdef OPENSSL_IS_BORINGSSL
CBS pkcs7_cbs;
#else /* OPENSSL_IS_BORINGSSL */
PKCS7 *p7 = NULL;
const unsigned char *p = pkcs7;
#endif /* OPENSSL_IS_BORINGSSL */
STACK_OF(X509) *certs;
int i, num, ret = -1;
BIO *out = NULL;
#ifdef OPENSSL_IS_BORINGSSL
certs = sk_X509_new_null();
if (!certs)
goto fail;
CBS_init(&pkcs7_cbs, pkcs7, len);
if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
ERR_error_string(ERR_get_error(), NULL));
write_result(ctx, "Could not parse PKCS#7 object from EST");
goto fail;
}
#else /* OPENSSL_IS_BORINGSSL */
p7 = d2i_PKCS7(NULL, &p, len);
if (p7 == NULL) {
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
ERR_error_string(ERR_get_error(), NULL));
write_result(ctx, "Could not parse PKCS#7 object from EST");
goto fail;
}
switch (OBJ_obj2nid(p7->type)) {
case NID_pkcs7_signed:
certs = p7->d.sign->cert;
break;
case NID_pkcs7_signedAndEnveloped:
certs = p7->d.signed_and_enveloped->cert;
break;
default:
certs = NULL;
break;
}
#endif /* OPENSSL_IS_BORINGSSL */
if (!certs || ((num = sk_X509_num(certs)) == 0)) {
wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object");
write_result(ctx, "No certificates found in PKCS#7 object");
goto fail;
}
if (der_file) {
FILE *f = fopen(der_file, "wb");
if (f == NULL)
goto fail;
i2d_X509_fp(f, sk_X509_value(certs, 0));
fclose(f);
}
if (pem_file) {
out = BIO_new(BIO_s_file());
if (out == NULL ||
BIO_write_filename(out, pem_file) <= 0)
goto fail;
for (i = 0; i < num; i++) {
X509 *cert = sk_X509_value(certs, i);
X509_print(out, cert);
PEM_write_bio_X509(out, cert);
BIO_puts(out, "\n");
}
}
ret = 0;
fail:
#ifdef OPENSSL_IS_BORINGSSL
if (certs)
sk_X509_pop_free(certs, X509_free);
#else /* OPENSSL_IS_BORINGSSL */
PKCS7_free(p7);
#endif /* OPENSSL_IS_BORINGSSL */
if (out)
BIO_free_all(out);
return ret;
}
int est_load_cacerts(struct hs20_osu_client *ctx, const char *url)
{
char *buf, *resp;
size_t buflen;
unsigned char *pkcs7;
size_t pkcs7_len, resp_len;
int res;
buflen = os_strlen(url) + 100;
buf = os_malloc(buflen);
if (buf == NULL)
return -1;
os_snprintf(buf, buflen, "%s/cacerts", url);
wpa_printf(MSG_INFO, "Download EST cacerts from %s", buf);
write_summary(ctx, "Download EST cacerts from %s", buf);
ctx->no_osu_cert_validation = 1;
http_ocsp_set(ctx->http, 1);
res = http_download_file(ctx->http, buf, "Cert/est-cacerts.txt",
ctx->ca_fname);
http_ocsp_set(ctx->http,
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
ctx->no_osu_cert_validation = 0;
if (res < 0) {
wpa_printf(MSG_INFO, "Failed to download EST cacerts from %s",
buf);
write_result(ctx, "Failed to download EST cacerts from %s",
buf);
os_free(buf);
return -1;
}
os_free(buf);
resp = os_readfile("Cert/est-cacerts.txt", &resp_len);
if (resp == NULL) {
wpa_printf(MSG_INFO, "Could not read Cert/est-cacerts.txt");
write_result(ctx, "Could not read EST cacerts");
return -1;
}
pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 && pkcs7_len < resp_len / 2) {
wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary",
(unsigned int) pkcs7_len, (unsigned int) resp_len);
os_free(pkcs7);
pkcs7 = NULL;
}
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
pkcs7 = os_malloc(resp_len);
if (pkcs7) {
os_memcpy(pkcs7, resp, resp_len);
pkcs7_len = resp_len;
}
}
os_free(resp);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "Could not fetch PKCS7 cacerts");
write_result(ctx, "Could not fetch EST PKCS#7 cacerts");
return -1;
}
res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est-cacerts.pem",
NULL);
os_free(pkcs7);
if (res < 0) {
wpa_printf(MSG_INFO, "Could not parse CA certs from PKCS#7 cacerts response");
write_result(ctx, "Could not parse CA certs from EST PKCS#7 cacerts response");
return -1;
}
unlink("Cert/est-cacerts.txt");
return 0;
}
/*
* CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID
*
* AttrOrOID ::= CHOICE {
* oid OBJECT IDENTIFIER,
* attribute Attribute }
*
* Attribute ::= SEQUENCE {
* type OBJECT IDENTIFIER,
* values SET SIZE(1..MAX) OF OBJECT IDENTIFIER }
*/
typedef struct {
ASN1_OBJECT *type;
STACK_OF(ASN1_OBJECT) *values;
} Attribute;
typedef struct {
int type;
union {
ASN1_OBJECT *oid;
Attribute *attribute;
} d;
} AttrOrOID;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
DEFINE_STACK_OF(AttrOrOID)
#endif
typedef struct {
int type;
STACK_OF(AttrOrOID) *attrs;
} CsrAttrs;
ASN1_SEQUENCE(Attribute) = {
ASN1_SIMPLE(Attribute, type, ASN1_OBJECT),
ASN1_SET_OF(Attribute, values, ASN1_OBJECT)
} ASN1_SEQUENCE_END(Attribute);
ASN1_CHOICE(AttrOrOID) = {
ASN1_SIMPLE(AttrOrOID, d.oid, ASN1_OBJECT),
ASN1_SIMPLE(AttrOrOID, d.attribute, Attribute)
} ASN1_CHOICE_END(AttrOrOID);
ASN1_CHOICE(CsrAttrs) = {
ASN1_SEQUENCE_OF(CsrAttrs, attrs, AttrOrOID)
} ASN1_CHOICE_END(CsrAttrs);
IMPLEMENT_ASN1_FUNCTIONS(CsrAttrs);
static void add_csrattrs_oid(struct hs20_osu_client *ctx, ASN1_OBJECT *oid,
STACK_OF(X509_EXTENSION) *exts)
{
char txt[100];
int res;
if (!oid)
return;
res = OBJ_obj2txt(txt, sizeof(txt), oid, 1);
if (res < 0 || res >= (int) sizeof(txt))
return;
if (os_strcmp(txt, "1.2.840.113549.1.9.7") == 0) {
wpa_printf(MSG_INFO, "TODO: csrattr challengePassword");
} else if (os_strcmp(txt, "1.2.840.113549.1.1.11") == 0) {
wpa_printf(MSG_INFO, "csrattr sha256WithRSAEncryption");
} else {
wpa_printf(MSG_INFO, "Ignore unsupported csrattr oid %s", txt);
}
}
static void add_csrattrs_ext_req(struct hs20_osu_client *ctx,
STACK_OF(ASN1_OBJECT) *values,
STACK_OF(X509_EXTENSION) *exts)
{
char txt[100];
int i, num, res;
num = sk_ASN1_OBJECT_num(values);
for (i = 0; i < num; i++) {
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(values, i);
res = OBJ_obj2txt(txt, sizeof(txt), oid, 1);
if (res < 0 || res >= (int) sizeof(txt))
continue;
if (os_strcmp(txt, "1.3.6.1.1.1.1.22") == 0) {
wpa_printf(MSG_INFO, "TODO: extReq macAddress");
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.3") == 0) {
wpa_printf(MSG_INFO, "TODO: extReq imei");
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.4") == 0) {
wpa_printf(MSG_INFO, "TODO: extReq meid");
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.5") == 0) {
wpa_printf(MSG_INFO, "TODO: extReq DevId");
} else {
wpa_printf(MSG_INFO, "Ignore unsupported cstattr extensionsRequest %s",
txt);
}
}
}
static void add_csrattrs_attr(struct hs20_osu_client *ctx, Attribute *attr,
STACK_OF(X509_EXTENSION) *exts)
{
char txt[100], txt2[100];
int i, num, res;
if (!attr || !attr->type || !attr->values)
return;
res = OBJ_obj2txt(txt, sizeof(txt), attr->type, 1);
if (res < 0 || res >= (int) sizeof(txt))
return;
if (os_strcmp(txt, "1.2.840.113549.1.9.14") == 0) {
add_csrattrs_ext_req(ctx, attr->values, exts);
return;
}
num = sk_ASN1_OBJECT_num(attr->values);
for (i = 0; i < num; i++) {
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(attr->values, i);
res = OBJ_obj2txt(txt2, sizeof(txt2), oid, 1);
if (res < 0 || res >= (int) sizeof(txt2))
continue;
wpa_printf(MSG_INFO, "Ignore unsupported cstattr::attr %s oid %s",
txt, txt2);
}
}
static void add_csrattrs(struct hs20_osu_client *ctx, CsrAttrs *csrattrs,
STACK_OF(X509_EXTENSION) *exts)
{
int i, num;
if (!csrattrs || ! csrattrs->attrs)
return;
#ifdef OPENSSL_IS_BORINGSSL
num = sk_num(CHECKED_CAST(_STACK *, STACK_OF(AttrOrOID) *,
csrattrs->attrs));
for (i = 0; i < num; i++) {
AttrOrOID *ao = sk_value(
CHECKED_CAST(_STACK *, const STACK_OF(AttrOrOID) *,
csrattrs->attrs), i);
switch (ao->type) {
case 0:
add_csrattrs_oid(ctx, ao->d.oid, exts);
break;
case 1:
add_csrattrs_attr(ctx, ao->d.attribute, exts);
break;
}
}
#else /* OPENSSL_IS_BORINGSSL */
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
num = sk_AttrOrOID_num(csrattrs->attrs);
#else
num = SKM_sk_num(AttrOrOID, csrattrs->attrs);
#endif
for (i = 0; i < num; i++) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
AttrOrOID *ao = sk_AttrOrOID_value(csrattrs->attrs, i);
#else
AttrOrOID *ao = SKM_sk_value(AttrOrOID, csrattrs->attrs, i);
#endif
switch (ao->type) {
case 0:
add_csrattrs_oid(ctx, ao->d.oid, exts);
break;
case 1:
add_csrattrs_attr(ctx, ao->d.attribute, exts);
break;
}
}
#endif /* OPENSSL_IS_BORINGSSL */
}
static int generate_csr(struct hs20_osu_client *ctx, char *key_pem,
char *csr_pem, char *est_req, char *old_cert,
CsrAttrs *csrattrs)
{
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
RSA *rsa;
X509_REQ *req = NULL;
int ret = -1;
unsigned int val;
X509_NAME *subj = NULL;
char name[100];
STACK_OF(X509_EXTENSION) *exts = NULL;
X509_EXTENSION *ex;
BIO *out;
CONF *ctmp = NULL;
wpa_printf(MSG_INFO, "Generate RSA private key");
write_summary(ctx, "Generate RSA private key");
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (!pctx)
return -1;
if (EVP_PKEY_keygen_init(pctx) <= 0)
goto fail;
if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048) <= 0)
goto fail;
if (EVP_PKEY_keygen(pctx, &pkey) <= 0)
goto fail;
EVP_PKEY_CTX_free(pctx);
pctx = NULL;
rsa = EVP_PKEY_get1_RSA(pkey);
if (rsa == NULL)
goto fail;
if (key_pem) {
FILE *f = fopen(key_pem, "wb");
if (f == NULL)
goto fail;
if (!PEM_write_RSAPrivateKey(f, rsa, NULL, NULL, 0, NULL,
NULL)) {
wpa_printf(MSG_INFO, "Could not write private key: %s",
ERR_error_string(ERR_get_error(), NULL));
fclose(f);
goto fail;
}
fclose(f);
}
wpa_printf(MSG_INFO, "Generate CSR");
write_summary(ctx, "Generate CSR");
req = X509_REQ_new();
if (req == NULL)
goto fail;
if (old_cert) {
FILE *f;
X509 *cert;
int res;
f = fopen(old_cert, "r");
if (f == NULL)
goto fail;
cert = PEM_read_X509(f, NULL, NULL, NULL);
fclose(f);
if (cert == NULL)
goto fail;
res = X509_REQ_set_subject_name(req,
X509_get_subject_name(cert));
X509_free(cert);
if (!res)
goto fail;
} else {
os_get_random((u8 *) &val, sizeof(val));
os_snprintf(name, sizeof(name), "cert-user-%u", val);
subj = X509_NAME_new();
if (subj == NULL ||
!X509_NAME_add_entry_by_txt(subj, "CN", MBSTRING_ASC,
(unsigned char *) name,
-1, -1, 0) ||
!X509_REQ_set_subject_name(req, subj))
goto fail;
X509_NAME_free(subj);
subj = NULL;
}
if (!X509_REQ_set_pubkey(req, pkey))
goto fail;
exts = sk_X509_EXTENSION_new_null();
if (!exts)
goto fail;
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_basic_constraints,
"CA:FALSE");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_key_usage,
"nonRepudiation,digitalSignature,keyEncipherment");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_ext_key_usage,
"1.3.6.1.4.1.40808.1.1.2");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
add_csrattrs(ctx, csrattrs, exts);
if (!X509_REQ_add_extensions(req, exts))
goto fail;
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
exts = NULL;
if (!X509_REQ_sign(req, pkey, EVP_sha256()))
goto fail;
out = BIO_new(BIO_s_mem());
if (out) {
char *txt;
size_t rlen;
#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
X509_REQ_print(out, req);
#endif
rlen = BIO_ctrl_pending(out);
txt = os_malloc(rlen + 1);
if (txt) {
int res = BIO_read(out, txt, rlen);
if (res > 0) {
txt[res] = '\0';
wpa_printf(MSG_MSGDUMP, "OpenSSL: Certificate request:\n%s",
txt);
}
os_free(txt);
}
BIO_free(out);
}
if (csr_pem) {
FILE *f = fopen(csr_pem, "w");
if (f == NULL)
goto fail;
#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
X509_REQ_print_fp(f, req);
#endif
if (!PEM_write_X509_REQ(f, req)) {
fclose(f);
goto fail;
}
fclose(f);
}
if (est_req) {
BIO *mem = BIO_new(BIO_s_mem());
BUF_MEM *ptr;
char *pos, *end, *buf_end;
FILE *f;
if (mem == NULL)
goto fail;
if (!PEM_write_bio_X509_REQ(mem, req)) {
BIO_free(mem);
goto fail;
}
BIO_get_mem_ptr(mem, &ptr);
pos = ptr->data;
buf_end = pos + ptr->length;
/* Remove START/END lines */
while (pos < buf_end && *pos != '\n')
pos++;
if (pos == buf_end) {
BIO_free(mem);
goto fail;
}
pos++;
end = pos;
while (end < buf_end && *end != '-')
end++;
f = fopen(est_req, "w");
if (f == NULL) {
BIO_free(mem);
goto fail;
}
fwrite(pos, end - pos, 1, f);
fclose(f);
BIO_free(mem);
}
ret = 0;
fail:
if (exts)
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
if (subj)
X509_NAME_free(subj);
if (req)
X509_REQ_free(req);
if (pkey)
EVP_PKEY_free(pkey);
if (pctx)
EVP_PKEY_CTX_free(pctx);
return ret;
}
int est_build_csr(struct hs20_osu_client *ctx, const char *url)
{
char *buf;
size_t buflen;
int res;
char old_cert_buf[200];
char *old_cert = NULL;
CsrAttrs *csrattrs = NULL;
buflen = os_strlen(url) + 100;
buf = os_malloc(buflen);
if (buf == NULL)
return -1;
os_snprintf(buf, buflen, "%s/csrattrs", url);
wpa_printf(MSG_INFO, "Download csrattrs from %s", buf);
write_summary(ctx, "Download EST csrattrs from %s", buf);
ctx->no_osu_cert_validation = 1;
http_ocsp_set(ctx->http, 1);
res = http_download_file(ctx->http, buf, "Cert/est-csrattrs.txt",
ctx->ca_fname);
http_ocsp_set(ctx->http,
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
ctx->no_osu_cert_validation = 0;
os_free(buf);
if (res < 0) {
wpa_printf(MSG_INFO, "Failed to download EST csrattrs - assume no extra attributes are needed");
} else {
size_t resp_len;
char *resp;
unsigned char *attrs;
const unsigned char *pos;
size_t attrs_len;
resp = os_readfile("Cert/est-csrattrs.txt", &resp_len);
if (resp == NULL) {
wpa_printf(MSG_INFO, "Could not read csrattrs");
return -1;
}
attrs = base64_decode(resp, resp_len, &attrs_len);
os_free(resp);
if (attrs == NULL) {
wpa_printf(MSG_INFO, "Could not base64 decode csrattrs");
return -1;
}
unlink("Cert/est-csrattrs.txt");
pos = attrs;
csrattrs = d2i_CsrAttrs(NULL, &pos, attrs_len);
os_free(attrs);
if (csrattrs == NULL) {
wpa_printf(MSG_INFO, "Failed to parse csrattrs ASN.1");
/* Continue assuming no additional requirements */
}
}
if (ctx->client_cert_present) {
os_snprintf(old_cert_buf, sizeof(old_cert_buf),
"SP/%s/client-cert.pem", ctx->fqdn);
old_cert = old_cert_buf;
}
res = generate_csr(ctx, "Cert/privkey-plain.pem", "Cert/est-req.pem",
"Cert/est-req.b64", old_cert, csrattrs);
if (csrattrs)
CsrAttrs_free(csrattrs);
return res;
}
int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
const char *user, const char *pw)
{
char *buf, *resp, *req, *req2;
size_t buflen, resp_len, len, pkcs7_len;
unsigned char *pkcs7;
char client_cert_buf[200];
char client_key_buf[200];
const char *client_cert = NULL, *client_key = NULL;
int res;
req = os_readfile("Cert/est-req.b64", &len);
if (req == NULL) {
wpa_printf(MSG_INFO, "Could not read Cert/req.b64");
return -1;
}
req2 = os_realloc(req, len + 1);
if (req2 == NULL) {
os_free(req);
return -1;
}
req2[len] = '\0';
req = req2;
wpa_printf(MSG_DEBUG, "EST simpleenroll request: %s", req);
buflen = os_strlen(url) + 100;
buf = os_malloc(buflen);
if (buf == NULL) {
os_free(req);
return -1;
}
if (ctx->client_cert_present) {
os_snprintf(buf, buflen, "%s/simplereenroll", url);
os_snprintf(client_cert_buf, sizeof(client_cert_buf),
"SP/%s/client-cert.pem", ctx->fqdn);
client_cert = client_cert_buf;
os_snprintf(client_key_buf, sizeof(client_key_buf),
"SP/%s/client-key.pem", ctx->fqdn);
client_key = client_key_buf;
} else
os_snprintf(buf, buflen, "%s/simpleenroll", url);
wpa_printf(MSG_INFO, "EST simpleenroll URL: %s", buf);
write_summary(ctx, "EST simpleenroll URL: %s", buf);
ctx->no_osu_cert_validation = 1;
http_ocsp_set(ctx->http, 1);
resp = http_post(ctx->http, buf, req, "application/pkcs10",
"Content-Transfer-Encoding: base64",
ctx->ca_fname, user, pw, client_cert, client_key,
&resp_len);
http_ocsp_set(ctx->http,
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
ctx->no_osu_cert_validation = 0;
os_free(buf);
if (resp == NULL) {
wpa_printf(MSG_INFO, "EST certificate enrollment failed");
write_result(ctx, "EST certificate enrollment failed");
return -1;
}
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
pkcs7 = os_malloc(resp_len);
if (pkcs7) {
os_memcpy(pkcs7, resp, resp_len);
pkcs7_len = resp_len;
}
}
os_free(resp);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "Failed to parse simpleenroll base64 response");
write_result(ctx, "Failed to parse EST simpleenroll base64 response");
return -1;
}
res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est_cert.pem",
"Cert/est_cert.der");
os_free(pkcs7);
if (res < 0) {
wpa_printf(MSG_INFO, "EST: Failed to extract certificate from PKCS7 file");
write_result(ctx, "EST: Failed to extract certificate from EST PKCS7 file");
return -1;
}
wpa_printf(MSG_INFO, "EST simple%senroll completed successfully",
ctx->client_cert_present ? "re" : "");
write_summary(ctx, "EST simple%senroll completed successfully",
ctx->client_cert_present ? "re" : "");
return 0;
}

1398
hs20/client/oma_dm_client.c Normal file

File diff suppressed because it is too large Load Diff

3431
hs20/client/osu_client.c Normal file

File diff suppressed because it is too large Load Diff

121
hs20/client/osu_client.h Normal file
View File

@ -0,0 +1,121 @@
/*
* Hotspot 2.0 - OSU client
* Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef OSU_CLIENT_H
#define OSU_CLIENT_H
#define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp"
#define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0"
#define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0"
#define URN_HS20_DEVDETAIL_EXT "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0"
#define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0"
#define MAX_OSU_VALS 10
struct osu_lang_text {
char lang[4];
char text[253];
};
struct hs20_osu_client {
struct xml_node_ctx *xml;
struct http_ctx *http;
int no_reconnect;
char pps_fname[300];
char *devid;
const char *result_file;
const char *summary_file;
const char *ifname;
const char *ca_fname;
int no_osu_cert_validation; /* for EST operations */
char *fqdn;
char *server_url;
struct osu_lang_text friendly_name[MAX_OSU_VALS];
size_t friendly_name_count;
size_t icon_count;
char icon_filename[MAX_OSU_VALS][256];
u8 icon_hash[MAX_OSU_VALS][32];
int pps_cred_set;
int pps_updated;
int client_cert_present;
char **server_dnsname;
size_t server_dnsname_count;
const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */
#define WORKAROUND_OCSP_OPTIONAL 0x00000001
unsigned long int workarounds;
int ignore_tls; /* whether to ignore TLS validation issues with HTTPS
* server certificate */
};
/* osu_client.c */
void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
void debug_dump_node(struct hs20_osu_client *ctx, const char *title,
xml_node_t *node);
int osu_get_certificate(struct hs20_osu_client *ctx, xml_node_t *getcert);
int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri,
xml_node_t *add_mo, char *fname, size_t fname_len);
void get_user_pw(struct hs20_osu_client *ctx, xml_node_t *pps,
const char *alt_loc, char **user, char **pw);
int update_pps_file(struct hs20_osu_client *ctx, const char *pps_fname,
xml_node_t *pps);
void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname);
/* spp_client.c */
void spp_sub_rem(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname,
const char *client_cert, const char *client_key,
const char *cred_username, const char *cred_password,
xml_node_t *pps);
void spp_pol_upd(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname,
const char *client_cert, const char *client_key,
const char *cred_username, const char *cred_password,
xml_node_t *pps);
int cmd_prov(struct hs20_osu_client *ctx, const char *url);
int cmd_sim_prov(struct hs20_osu_client *ctx, const char *url);
/* oma_dm_client.c */
int cmd_oma_dm_prov(struct hs20_osu_client *ctx, const char *url);
int cmd_oma_dm_sim_prov(struct hs20_osu_client *ctx, const char *url);
void oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname,
const char *client_cert, const char *client_key,
const char *cred_username, const char *cred_password,
xml_node_t *pps);
void oma_dm_pol_upd(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname,
const char *client_cert, const char *client_key,
const char *cred_username, const char *cred_password,
xml_node_t *pps);
void cmd_oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
const char *pps_fname);
void cmd_oma_dm_add(struct hs20_osu_client *ctx, const char *pps_fname,
const char *add_fname);
void cmd_oma_dm_replace(struct hs20_osu_client *ctx, const char *pps_fname,
const char *replace_fname);
/* est.c */
int est_load_cacerts(struct hs20_osu_client *ctx, const char *url);
int est_build_csr(struct hs20_osu_client *ctx, const char *url);
int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
const char *user, const char *pw);
#endif /* OSU_CLIENT_H */

1004
hs20/client/spp_client.c Normal file

File diff suppressed because it is too large Load Diff

1827
wpa_supplicant/Android.mk Normal file

File diff suppressed because it is too large Load Diff

2500
wpa_supplicant/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

2074
wpa_supplicant/Makefile Normal file

File diff suppressed because it is too large Load Diff

1163
wpa_supplicant/README Normal file

File diff suppressed because it is too large Load Diff

204
wpa_supplicant/README-DPP Normal file
View File

@ -0,0 +1,204 @@
Device Provisioning Protocol (DPP)
==================================
This document describes how the Device Provisioning Protocol (DPP)
implementation in wpa_supplicant and hostapd can be configured and how
the STA device and AP can be configured to connect each other using DPP
Connector mechanism.
Introduction to DPP
-------------------
Device Provisioning Protocol (also known as Wi-Fi Easy Connect) allows
enrolling of interface-less devices in a secure Wi-Fi network using many
methods like QR code based authentication (detailed below), PKEX based
authentication (password with in-band provisioning), etc. In DPP a
Configurator is used to provide network credentials to the devices. The
three phases of DPP connection are authentication, configuration and
network introduction.
More information about Wi-Fi Easy Connect is available from this Wi-Fi
Alliance web page:
https://www.wi-fi.org/discover-wi-fi/wi-fi-easy-connect
Build config setup
------------------
The following parameters must be included in the config file used to
compile hostapd and wpa_supplicant.
wpa_supplicant build config
---------------------------
Enable DPP in wpa_supplicant build config file
CONFIG_DPP=y
hostapd build config
--------------------
Enable DPP in hostapd build config file
CONFIG_DPP=y
Configurator build config
-------------------------
Any STA or AP device can act as a Configurator. Enable DPP in build
config. For an AP to act as a Configurator, Interworking needs to be
enabled for GAS. For wpa_supplicant it is not required.
CONFIG_INTERWORKING=y
Sample supplicant config file before provisioning
-------------------------------------------------
ctrl_interface=DIR=/var/run/wpa_supplicant
ctrl_interface_group=0
update_config=1
pmf=2
dpp_config_processing=2
Sample hostapd config file before provisioning
----------------------------------------------
interface=wlan0
driver=nl80211
ctrl_interface=/var/run/hostapd
ssid=test
channel=1
wpa=2
wpa_key_mgmt=DPP
ieee80211w=1
wpa_pairwise=CCMP
rsn_pairwise=CCMP
Pre-requisites
--------------
It is assumed that an AP and client station are up by running hostapd
and wpa_supplicant using respective config files.
Creating Configurator
---------------------
Add a Configurator over the control interface (wpa_cli/hostapd_cli)
> dpp_configurator_add
(returns id)
To get key of Configurator
> dpp_configurator_get_key <id>
How to configure an Enrollee using Configurator
-----------------------------------------------
On Enrollee side:
Generate QR code for the device. Store the QR code id returned by the
command.
> dpp_bootstrap_gen type=qrcode mac=<mac-address-of-device> chan=<operating-class/channel> key=<key of the device>
(Returns bootstrapping info id. If the key parameter is not included, a new key
is generated automatically. The MAC address is specified without octet
separating colons. The channel list includes the possible channels on which the
device is waiting. This uses global operating classes; e.g., 81/1 is the 2.4
GHz channel 1 on 2412 MHz.)
Get URI for the QR Code of device using the bootstrap info id.
> dpp_bootstrap_get_uri <bootstrap-id>
Make device listen to DPP request. The central frequency of the 2.4 GHz
band channel 1 is 2412 MHz) in case the Enrollee is a client device. An
AP as an Enrollee is listening on its operating channel.
> dpp_listen <frequency>
On Configurator side:
Enter the QR Code in the Configurator.
> dpp_qr_code "<URI-from-QR-Code-read-from-enrollee>"
On successfully adding QR Code, a bootstrapping info id is returned.
Send provisioning request to Enrollee. (conf is ap-dpp if Enrollee is an
AP. conf is sta-dpp if Enrollee is a client)
> dpp_auth_init peer=<qr-code-id> conf=<ap-dpp|sta-dpp> ssid=<SSID hexdump> configurator=<configurator-id>
or for legacy (PSK/SAE) provisioning for a station Enrollee:
> dpp_auth_init peer=<qr-code-id> conf=sta-psk ssid=<SSID hexdump> pass=<passphrase hexdump>
The DPP values will be printed in the console. Save these values into the
config file. If the Enrollee is an AP, we need to manually write these
values to the hostapd config file. If the Enrollee is a client device,
these details can be automatically saved to config file using the
following command.
> save_config
To set values in runtime for AP enrollees
> set dpp_connector <Connector-value-printed-on-console>
> set dpp_csign <csign-value-on-console>
> set dpp_netaccesskey <netaccess-value-on-console>
To set values in runtime for client enrollees, set dpp_config_processing
to 2 in wpa_supplicant conf file.
Once the values are set in run-time (if not set in run-time, but saved
in config files, they are taken up in next restart), the client device
will automatically connect to the already provisioned AP and connection
will be established.
Self-configuring a device
-------------------------
It is possible for a device to configure itself if it is the
Configurator for the network.
Create a Configurator in the device and use the dpp_configurator_sign
command to get DPP credentials.
> dpp_configurator_add
(returns configurator id)
> dpp_configurator_sign conf=<ap-dpp|sta-dpp> configurator=<configurator-id> ssid=<SSID hexdump>
Sample AP configuration files after provisioning
------------------------------------------------
interface=wlan0
driver=nl80211
ctrl_interface=/var/run/hostapd
ssid=test
channel=1
wpa=2
wpa_key_mgmt=DPP
ieee80211w=1
wpa_pairwise=CCMP
rsn_pairwise=CCMP
dpp_connector=<Connector value provided by Configurator>
dpp_csign=<C-Sign-Key value provided by Configurator>
dpp_netaccesskey=<Net access key provided by Configurator>
Sample station configuration file after provisioning
----------------------------------------------------
ctrl_interface=DIR=/var/run/wpa_supplicant
ctrl_interface_group=0
update_config=1
pmf=2
dpp_config_processing=2
network={
ssid="test"
key_mgmt=DPP
ieee80211w=2
dpp_connector="<Connector value provided by Configurator>"
dpp_netaccesskey=<Net access key provided by Configurator>
dpp_csign=<C-sign-key value provided by Configurator>
}

654
wpa_supplicant/README-HS20 Normal file
View File

@ -0,0 +1,654 @@
wpa_supplicant and Hotspot 2.0
==============================
This document describe how the IEEE 802.11u Interworking and Wi-Fi
Hotspot 2.0 (Release 1) implementation in wpa_supplicant can be
configured and how an external component on the client e.g., management
GUI or Wi-Fi framework) is used to manage this functionality.
Introduction to Wi-Fi Hotspot 2.0
---------------------------------
Hotspot 2.0 is the name of the Wi-Fi Alliance specification that is used
in the Wi-Fi CERTIFIED Passpoint<TM> program. More information about
this is available in this white paper:
http://www.wi-fi.org/knowledge-center/white-papers/wi-fi-certified-passpoint%E2%84%A2-new-program-wi-fi-alliance%C2%AE-enable-seamless
The Hotspot 2.0 specification is also available from WFA:
https://www.wi-fi.org/knowledge-center/published-specifications
The core Interworking functionality (network selection, GAS/ANQP) were
standardized in IEEE Std 802.11u-2011 which is now part of the IEEE Std
802.11-2012.
wpa_supplicant network selection
--------------------------------
Interworking support added option for configuring credentials that can
work with multiple networks as an alternative to configuration of
network blocks (e.g., per-SSID parameters). When requested to perform
network selection, wpa_supplicant picks the highest priority enabled
network block or credential. If a credential is picked (based on ANQP
information from APs), a temporary network block is created
automatically for the matching network. This temporary network block is
used similarly to the network blocks that can be configured by the user,
but it is not stored into the configuration file and is meant to be used
only for temporary period of time since a new one can be created
whenever needed based on ANQP information and the credential.
By default, wpa_supplicant is not using automatic network selection
unless requested explicitly with the interworking_select command. This
can be changed with the auto_interworking=1 parameter to perform network
selection automatically whenever trying to find a network for connection
and none of the enabled network blocks match with the scan results. This
case works similarly to "interworking_select auto", i.e., wpa_supplicant
will internally determine which network or credential is going to be
used based on configured priorities, scan results, and ANQP information.
wpa_supplicant configuration
----------------------------
Interworking and Hotspot 2.0 functionality are optional components that
need to be enabled in the wpa_supplicant build configuration
(.config). This is done by adding following parameters into that file:
CONFIG_INTERWORKING=y
CONFIG_HS20=y
It should be noted that this functionality requires a driver that
supports GAS/ANQP operations. This uses the same design as P2P, i.e.,
Action frame processing and building in user space within
wpa_supplicant. The Linux nl80211 driver interface provides the needed
functionality for this.
There are number of run-time configuration parameters (e.g., in
wpa_supplicant.conf when using the configuration file) that can be used
to control Hotspot 2.0 operations.
# Enable Interworking
interworking=1
# Enable Hotspot 2.0
hs20=1
# Parameters for controlling scanning
# Homogeneous ESS identifier
# If this is set, scans will be used to request response only from BSSes
# belonging to the specified Homogeneous ESS. This is used only if interworking
# is enabled.
#hessid=00:11:22:33:44:55
# Access Network Type
# When Interworking is enabled, scans can be limited to APs that advertise the
# specified Access Network Type (0..15; with 15 indicating wildcard match).
# This value controls the Access Network Type value in Probe Request frames.
#access_network_type=15
# Automatic network selection behavior
# 0 = do not automatically go through Interworking network selection
# (i.e., require explicit interworking_select command for this; default)
# 1 = perform Interworking network selection if one or more
# credentials have been configured and scan did not find a
# matching network block
#auto_interworking=0
Credentials can be pre-configured for automatic network selection:
# credential block
#
# Each credential used for automatic network selection is configured as a set
# of parameters that are compared to the information advertised by the APs when
# interworking_select and interworking_connect commands are used.
#
# credential fields:
#
# temporary: Whether this credential is temporary and not to be saved
#
# priority: Priority group
# By default, all networks and credentials get the same priority group
# (0). This field can be used to give higher priority for credentials
# (and similarly in struct wpa_ssid for network blocks) to change the
# Interworking automatic networking selection behavior. The matching
# network (based on either an enabled network block or a credential)
# with the highest priority value will be selected.
#
# pcsc: Use PC/SC and SIM/USIM card
#
# realm: Home Realm for Interworking
#
# username: Username for Interworking network selection
#
# password: Password for Interworking network selection
#
# ca_cert: CA certificate for Interworking network selection
#
# client_cert: File path to client certificate file (PEM/DER)
# This field is used with Interworking networking selection for a case
# where client certificate/private key is used for authentication
# (EAP-TLS). Full path to the file should be used since working
# directory may change when wpa_supplicant is run in the background.
#
# Alternatively, a named configuration blob can be used by setting
# this to blob://blob_name.
#
# private_key: File path to client private key file (PEM/DER/PFX)
# When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be
# commented out. Both the private key and certificate will be read
# from the PKCS#12 file in this case. Full path to the file should be
# used since working directory may change when wpa_supplicant is run
# in the background.
#
# Windows certificate store can be used by leaving client_cert out and
# configuring private_key in one of the following formats:
#
# cert://substring_to_match
#
# hash://certificate_thumbprint_in_hex
#
# For example: private_key="hash://63093aa9c47f56ae88334c7b65a4"
#
# Note that when running wpa_supplicant as an application, the user
# certificate store (My user account) is used, whereas computer store
# (Computer account) is used when running wpasvc as a service.
#
# Alternatively, a named configuration blob can be used by setting
# this to blob://blob_name.
#
# private_key_passwd: Password for private key file
#
# imsi: IMSI in <MCC> | <MNC> | '-' | <MSIN> format
#
# milenage: Milenage parameters for SIM/USIM simulator in <Ki>:<OPc>:<SQN>
# format
#
# domain_suffix_match: Constraint for server domain name
# If set, this FQDN is used as a suffix match requirement for the AAA
# server certificate in SubjectAltName dNSName element(s). If a
# matching dNSName is found, this constraint is met. If no dNSName
# values are present, this constraint is matched against SubjectName CN
# using same suffix match comparison. Suffix match here means that the
# host/domain name is compared one label at a time starting from the
# top-level domain and all the labels in @domain_suffix_match shall be
# included in the certificate. The certificate may include additional
# sub-level labels in addition to the required labels.
#
# For example, domain_suffix_match=example.com would match
# test.example.com but would not match test-example.com.
#
# domain: Home service provider FQDN(s)
# This is used to compare against the Domain Name List to figure out
# whether the AP is operated by the Home SP. Multiple domain entries can
# be used to configure alternative FQDNs that will be considered home
# networks.
#
# roaming_consortium: Roaming Consortium OI
# If roaming_consortium_len is non-zero, this field contains the
# Roaming Consortium OI that can be used to determine which access
# points support authentication with this credential. This is an
# alternative to the use of the realm parameter. When using Roaming
# Consortium to match the network, the EAP parameters need to be
# pre-configured with the credential since the NAI Realm information
# may not be available or fetched.
#
# required_roaming_consortium: Required Roaming Consortium OI
# If required_roaming_consortium_len is non-zero, this field contains the
# Roaming Consortium OI that is required to be advertised by the AP for
# the credential to be considered matching.
#
# roaming_consortiums: Roaming Consortium OI(s) memberships
# This string field contains one or more comma delimited OIs (hexdump)
# identifying the roaming consortiums of which the provider is a member.
# The list is sorted from the most preferred one to the least preferred
# one. A match between the Roaming Consortium OIs advertised by an AP and
# the OIs in this list indicates that successful authentication is
# possible.
# (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/RoamingConsortiumOI)
#
# eap: Pre-configured EAP method
# This optional field can be used to specify which EAP method will be
# used with this credential. If not set, the EAP method is selected
# automatically based on ANQP information (e.g., NAI Realm).
#
# phase1: Pre-configure Phase 1 (outer authentication) parameters
# This optional field is used with like the 'eap' parameter.
#
# phase2: Pre-configure Phase 2 (inner authentication) parameters
# This optional field is used with like the 'eap' parameter.
#
# excluded_ssid: Excluded SSID
# This optional field can be used to excluded specific SSID(s) from
# matching with the network. Multiple entries can be used to specify more
# than one SSID.
#
# roaming_partner: Roaming partner information
# This optional field can be used to configure preferences between roaming
# partners. The field is a string in following format:
# <FQDN>,<0/1 exact match>,<priority>,<* or country code>
# (non-exact match means any subdomain matches the entry; priority is in
# 0..255 range with 0 being the highest priority)
#
# update_identifier: PPS MO ID
# (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier)
#
# provisioning_sp: FQDN of the SP that provisioned the credential
# This optional field can be used to keep track of the SP that provisioned
# the credential to find the PPS MO (./Wi-Fi/<provisioning_sp>).
#
# sp_priority: Credential priority within a provisioning SP
# This is the priority of the credential among all credentials
# provisioned by the same SP (i.e., for entries that have identical
# provisioning_sp value). The range of this priority is 0-255 with 0
# being the highest and 255 the lower priority.
#
# Minimum backhaul threshold (PPS/<X+>/Policy/MinBackhauldThreshold/*)
# These fields can be used to specify minimum download/upload backhaul
# bandwidth that is preferred for the credential. This constraint is
# ignored if the AP does not advertise WAN Metrics information or if the
# limit would prevent any connection. Values are in kilobits per second.
# min_dl_bandwidth_home
# min_ul_bandwidth_home
# min_dl_bandwidth_roaming
# min_ul_bandwidth_roaming
#
# max_bss_load: Maximum BSS Load Channel Utilization (1..255)
# (PPS/<X+>/Policy/MaximumBSSLoadValue)
# This value is used as the maximum channel utilization for network
# selection purposes for home networks. If the AP does not advertise
# BSS Load or if the limit would prevent any connection, this constraint
# will be ignored.
#
# req_conn_capab: Required connection capability
# (PPS/<X+>/Policy/RequiredProtoPortTuple)
# This value is used to configure set of required protocol/port pairs that
# a roaming network shall support (include explicitly in Connection
# Capability ANQP element). This constraint is ignored if the AP does not
# advertise Connection Capability or if this constraint would prevent any
# network connection. This policy is not used in home networks.
# Format: <protocol>[:<comma-separated list of ports]
# Multiple entries can be used to list multiple requirements.
# For example, number of common TCP protocols:
# req_conn_capab=6:22,80,443
# For example, IPSec/IKE:
# req_conn_capab=17:500
# req_conn_capab=50
#
# ocsp: Whether to use/require OCSP to check server certificate
# 0 = do not use OCSP stapling (TLS certificate status extension)
# 1 = try to use OCSP stapling, but not require response
# 2 = require valid OCSP stapling response
#
# sim_num: Identifier for which SIM to use in multi-SIM devices
#
# engine: Whether to use an engine for private key operations (0/1)
# engine_id: String identifying the engine to use
# ca_cert_id: The CA certificate identifier when using an engine
# cert_id: The certificate identifier when using an engine
# key_id: The private key identifier when using an engine
#
# for example:
#
#cred={
# realm="example.com"
# username="user@example.com"
# password="password"
# ca_cert="/etc/wpa_supplicant/ca.pem"
# domain="example.com"
# domain_suffix_match="example.com"
#}
#
#cred={
# imsi="310026-000000000"
# milenage="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82"
#}
#
#cred={
# realm="example.com"
# username="user"
# password="password"
# ca_cert="/etc/wpa_supplicant/ca.pem"
# domain="example.com"
# roaming_consortium=223344
# roaming_consortiums="112233,4455667788,aabbcc"
# eap=TTLS
# phase2="auth=MSCHAPV2"
#}
Control interface
-----------------
wpa_supplicant provides a control interface that can be used from
external programs to manage various operations. The included command
line tool, wpa_cli, can be used for manual testing with this interface.
Following wpa_cli interactive mode commands show some examples of manual
operations related to Hotspot 2.0:
Remove configured networks and credentials:
> remove_network all
OK
> remove_cred all
OK
Add a username/password credential:
> add_cred
0
> set_cred 0 realm "mail.example.com"
OK
> set_cred 0 username "username"
OK
> set_cred 0 password "password"
OK
> set_cred 0 priority 1
OK
> set_cred 0 temporary 1
OK
Add a SIM credential using a simulated SIM/USIM card for testing:
> add_cred
1
> set_cred 1 imsi "23456-0000000000"
OK
> set_cred 1 milenage "90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123"
OK
> set_cred 1 priority 1
OK
Note: the return value of add_cred is used as the first argument to
the following set_cred commands.
Add a SIM credential using a external SIM/USIM processing:
> set external_sim 1
OK
> add_cred
1
> set_cred 1 imsi "23456-0000000000"
OK
> set_cred 1 eap SIM
OK
Add a WPA2-Enterprise network:
> add_network
0
> set_network 0 key_mgmt WPA-EAP
OK
> set_network 0 ssid "enterprise"
OK
> set_network 0 eap TTLS
OK
> set_network 0 anonymous_identity "anonymous"
OK
> set_network 0 identity "user"
OK
> set_network 0 password "password"
OK
> set_network 0 priority 0
OK
> enable_network 0 no-connect
OK
Add an open network:
> add_network
3
> set_network 3 key_mgmt NONE
OK
> set_network 3 ssid "coffee-shop"
OK
> select_network 3
OK
Note: the return value of add_network is used as the first argument to
the following set_network commands.
The preferred credentials/networks can be indicated with the priority
parameter (1 is higher priority than 0).
Interworking network selection can be started with interworking_select
command. This instructs wpa_supplicant to run a network scan and iterate
through the discovered APs to request ANQP information from the APs that
advertise support for Interworking/Hotspot 2.0:
> interworking_select
OK
<3>Starting ANQP fetch for 02:00:00:00:01:00
<3>RX-ANQP 02:00:00:00:01:00 ANQP Capability list
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
<3>ANQP fetch completed
<3>INTERWORKING-AP 02:00:00:00:01:00 type=unknown
INTERWORKING-AP event messages indicate the APs that support network
selection and for which there is a matching
credential. interworking_connect command can be used to select a network
to connect with:
> interworking_connect 02:00:00:00:01:00
OK
<3>CTRL-EVENT-SCAN-RESULTS
<3>SME: Trying to authenticate with 02:00:00:00:01:00 (SSID='Example Network' freq=2412 MHz)
<3>Trying to associate with 02:00:00:00:01:00 (SSID='Example Network' freq=2412 MHz)
<3>Associated with 02:00:00:00:01:00
<3>CTRL-EVENT-EAP-STARTED EAP authentication started
<3>CTRL-EVENT-EAP-PROPOSED-METHOD vendor=0 method=21
<3>CTRL-EVENT-EAP-METHOD EAP vendor 0 method 21 (TTLS) selected
<3>CTRL-EVENT-EAP-SUCCESS EAP authentication completed successfully
<3>WPA: Key negotiation completed with 02:00:00:00:01:00 [PTK=CCMP GTK=CCMP]
<3>CTRL-EVENT-CONNECTED - Connection to 02:00:00:00:01:00 completed (auth) [id=0 id_str=]
wpa_supplicant creates a temporary network block for the selected
network based on the configured credential and ANQP information from the
AP:
> list_networks
network id / ssid / bssid / flags
0 Example Network any [CURRENT]
> get_network 0 key_mgmt
WPA-EAP
> get_network 0 eap
TTLS
Alternatively to using an external program to select the network,
"interworking_select auto" command can be used to request wpa_supplicant
to select which network to use based on configured priorities:
> remove_network all
OK
<3>CTRL-EVENT-DISCONNECTED bssid=02:00:00:00:01:00 reason=1 locally_generated=1
> interworking_select auto
OK
<3>Starting ANQP fetch for 02:00:00:00:01:00
<3>RX-ANQP 02:00:00:00:01:00 ANQP Capability list
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
<3>ANQP fetch completed
<3>INTERWORKING-AP 02:00:00:00:01:00 type=unknown
<3>CTRL-EVENT-SCAN-RESULTS
<3>SME: Trying to authenticate with 02:00:00:00:01:00 (SSID='Example Network' freq=2412 MHz)
<3>Trying to associate with 02:00:00:00:01:00 (SSID='Example Network' freq=2412 MHz)
<3>Associated with 02:00:00:00:01:00
<3>CTRL-EVENT-EAP-STARTED EAP authentication started
<3>CTRL-EVENT-EAP-PROPOSED-METHOD vendor=0 method=21
<3>CTRL-EVENT-EAP-METHOD EAP vendor 0 method 21 (TTLS) selected
<3>CTRL-EVENT-EAP-SUCCESS EAP authentication completed successfully
<3>WPA: Key negotiation completed with 02:00:00:00:01:00 [PTK=CCMP GTK=CCMP]
<3>CTRL-EVENT-CONNECTED - Connection to 02:00:00:00:01:00 completed (reauth) [id=0 id_str=]
The connection status can be shown with the status command:
> status
bssid=02:00:00:00:01:00
ssid=Example Network
id=0
mode=station
pairwise_cipher=CCMP <--- link layer security indication
group_cipher=CCMP
key_mgmt=WPA2/IEEE 802.1X/EAP
wpa_state=COMPLETED
p2p_device_address=02:00:00:00:00:00
address=02:00:00:00:00:00
hs20=1 <--- HS 2.0 indication
Supplicant PAE state=AUTHENTICATED
suppPortStatus=Authorized
EAP state=SUCCESS
selectedMethod=21 (EAP-TTLS)
EAP TLS cipher=AES-128-SHA
EAP-TTLSv0 Phase2 method=PAP
> status
bssid=02:00:00:00:02:00
ssid=coffee-shop
id=3
mode=station
pairwise_cipher=NONE
group_cipher=NONE
key_mgmt=NONE
wpa_state=COMPLETED
p2p_device_address=02:00:00:00:00:00
address=02:00:00:00:00:00
Note: The Hotspot 2.0 indication is shown as "hs20=1" in the status
command output. Link layer security is indicated with the
pairwise_cipher (CCMP = secure, NONE = no encryption used).
Also the scan results include the Hotspot 2.0 indication:
> scan_results
bssid / frequency / signal level / flags / ssid
02:00:00:00:01:00 2412 -30 [WPA2-EAP-CCMP][ESS][HS20] Example Network
ANQP information for the BSS can be fetched using the BSS command:
> bss 02:00:00:00:01:00
id=1
bssid=02:00:00:00:01:00
freq=2412
beacon_int=100
capabilities=0x0411
qual=0
noise=-92
level=-30
tsf=1345573286517276
age=105
ie=000f4578616d706c65204e6574776f726b010882848b960c1218240301012a010432043048606c30140100000fac040100000fac040100000fac0100007f04000000806b091e07010203040506076c027f006f1001531122331020304050010203040506dd05506f9a1000
flags=[WPA2-EAP-CCMP][ESS][HS20]
ssid=Example Network
anqp_roaming_consortium=031122330510203040500601020304050603fedcba
ANQP queries can also be requested with the anqp_get and hs20_anqp_get
commands:
> anqp_get 02:00:00:00:01:00 261
OK
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
> hs20_anqp_get 02:00:00:00:01:00 2
OK
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
In addition, fetch_anqp command can be used to request similar set of
ANQP queries to be done as is run as part of interworking_select:
> scan
OK
<3>CTRL-EVENT-SCAN-RESULTS
> fetch_anqp
OK
<3>Starting ANQP fetch for 02:00:00:00:01:00
<3>RX-ANQP 02:00:00:00:01:00 ANQP Capability list
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
<3>ANQP fetch completed
Hotspot 2.0 Rel 2 online signup and OSEN
----------------------------------------
Following parameters can be used to create a network profile for
link-layer protected Hotspot 2.0 online signup connection with
OSEN. Note that ssid and identify (NAI) values need to be set based on
the information for the selected provider in the OSU Providers list
ANQP-element.
network={
ssid="HS 2.0 OSU"
proto=OSEN
key_mgmt=OSEN
pairwise=CCMP
group=GTK_NOT_USED
eap=WFA-UNAUTH-TLS
identity="anonymous@example.com"
ca_cert="osu-ca.pem"
ocsp=2
}
Hotspot 2.0 connection with external network selection
------------------------------------------------------
When a component controlling wpa_supplicant takes care of Interworking
network selection, following configuration and network profile
parameters can be used to configure a temporary network profile for a
Hotspot 2.0 connection (e.g., with SET, ADD_NETWORK, SET_NETWORK, and
SELECT_NETWORK control interface commands):
interworking=1
hs20=1
auto_interworking=0
network={
ssid="test-hs20"
proto=RSN
key_mgmt=WPA-EAP
pairwise=CCMP
anonymous_identity="anonymous@example.com"
identity="hs20-test@example.com"
password="password"
ca_cert="ca.pem"
eap=TTLS
phase2="auth=MSCHAPV2"
update_identifier=54321
roaming_consortium_selection=112233
#ocsp=2
}
These parameters are set based on the PPS MO credential and/or NAI Realm
list ANQP-element:
anonymous_identity: Credential/UsernamePassword/Username with username part
replaced with "anonymous"
identity: Credential/UsernamePassword/Username
password: Credential/UsernamePassword/Password
update_identifier: PPS/UpdateIdentifier
ca_cert: from the downloaded trust root based on PPS information
eap: Credential/UsernamePassword/EAPMethod or NAI Realm list
phase2: Credential/UsernamePassword/EAPMethod or NAI Realm list
roaming_consortium_selection: Matching OI from HomeSP/RoamingConsortiumOI
ocsp: Credential/CheckAAAServerCertStatus

856
wpa_supplicant/README-P2P Normal file
View File

@ -0,0 +1,856 @@
wpa_supplicant and Wi-Fi P2P
============================
This document describes how the Wi-Fi P2P implementation in
wpa_supplicant can be configured and how an external component on the
client (e.g., management GUI) is used to enable WPS enrollment and
registrar registration.
Introduction to Wi-Fi P2P
-------------------------
TODO
More information about Wi-Fi P2P is available from Wi-Fi Alliance:
http://www.wi-fi.org/Wi-Fi_Direct.php
wpa_supplicant implementation
-----------------------------
TODO
wpa_supplicant configuration
----------------------------
Wi-Fi P2P is an optional component that needs to be enabled in the
wpa_supplicant build configuration (.config). Here is an example
configuration that includes Wi-Fi P2P support and Linux nl80211
-based driver interface:
CONFIG_DRIVER_NL80211=y
CONFIG_CTRL_IFACE=y
CONFIG_P2P=y
CONFIG_AP=y
CONFIG_WPS=y
In run-time configuration file (wpa_supplicant.conf), some parameters
for P2P may be set. In order to make the devices easier to recognize,
device_name and device_type should be specified. For example,
something like this should be included:
ctrl_interface=/var/run/wpa_supplicant
device_name=My P2P Device
device_type=1-0050F204-1
wpa_cli
-------
Actual Wi-Fi P2P operations are requested during runtime. These can be
done for example using wpa_cli (which is described below) or a GUI
like wpa_gui-qt4.
wpa_cli starts in interactive mode if no command string is included on
the command line. By default, it will select the first network interface
that it can find (and that wpa_supplicant controls). If more than one
interface is in use, it may be necessary to select one of the explicitly
by adding -i argument on the command line (e.g., 'wpa_cli -i wlan1').
Most of the P2P operations are done on the main interface (e.g., the
interface that is automatically added when the driver is loaded, e.g.,
wlan0). When using a separate virtual interface for group operations
(e.g., wlan1), the control interface for that group interface may need
to be used for some operations (mainly WPS activation in GO). This may
change in the future so that all the needed operations could be done
over the main control interface.
Device Discovery
p2p_find [timeout in seconds] [type=<social|progressive>] \
[dev_id=<addr>] [dev_type=<device type>] \
[delay=<search delay in ms>] [seek=<service name>] [freq=<MHz>]
The default behavior is to run a single full scan in the beginning and
then scan only social channels. type=social will scan only social
channels, i.e., it skips the initial full scan. type=progressive is
like the default behavior, but it will scan through all the channels
progressively one channel at the time in the Search state rounds. This
will help in finding new groups or groups missed during the initial
full scan. When the type parameter is not included (i.e., full scan), the
optional freq parameter can be used to override the first scan to use only
the specified channel after which only social channels are scanned.
The optional dev_id option can be used to specify a single P2P peer to
search for. The optional delay parameter can be used to request an extra
delay to be used between search iterations (e.g., to free up radio
resources for concurrent operations).
The optional dev_type option can be used to specify a single device type
(primary or secondary) to search for, e.g.,
"p2p_find dev_type=1-0050F204-1".
With one or more seek arguments, the command sends Probe Request frames
for a P2PS service. For example,
p2p_find 5 dev_id=11:22:33:44:55:66 seek=alt.example.chat seek=alt.example.video
Parameters description:
Timeout - Optional ASCII base-10-encoded u16. If missing, request will not
time out and must be canceled manually
dev_id - Optional to request responses from a single known remote device
Service Name - Mandatory UTF-8 string for ASP seeks
Service name must match the remote service being advertised exactly
(no prefix matching).
Service name may be empty, in which case all ASP services will be
returned, and may be filtered with p2p_serv_disc_req settings, and
p2p_serv_asp_resp results.
Multiple service names may be requested, but if it exceeds internal
limit, it will automatically revert to requesting all ASP services.
p2p_listen [timeout in seconds]
Start Listen-only state (become discoverable without searching for
other devices). Optional parameter can be used to specify the duration
for the Listen operation in seconds. This command may not be of that
much use during normal operations and is mainly designed for
testing. It can also be used to keep the device discoverable without
having to maintain a group.
p2p_stop_find
Stop ongoing P2P device discovery or other operation (connect, listen
mode).
p2p_flush
Flush P2P peer table and state.
Group Formation
p2p_prov_disc <peer device address> <display|keypad|pbc> [join|auto]
Send P2P provision discovery request to the specified peer. The
parameters for this command are the P2P device address of the peer and
the desired configuration method. For example, "p2p_prov_disc
02:01:02:03:04:05 display" would request the peer to display a PIN for
us and "p2p_prov_disc 02:01:02:03:04:05 keypad" would request the peer
to enter a PIN that we display.
The optional "join" parameter can be used to indicate that this command
is requesting an already running GO to prepare for a new client. This is
mainly used with "display" to request it to display a PIN. The "auto"
parameter can be used to request wpa_supplicant to automatically figure
out whether the peer device is operating as a GO and if so, use
join-a-group style PD instead of GO Negotiation style PD.
p2p_connect <peer device address> <pbc|pin|PIN#|p2ps> [display|keypad|p2ps]
[persistent|persistent=<network id>] [join|auth]
[go_intent=<0..15>] [freq=<in MHz>] [ht40] [vht] [he] [provdisc] [auto]
[ssid=<hexdump>]
Start P2P group formation with a discovered P2P peer. This includes
optional group owner negotiation, group interface setup, provisioning,
and establishing data connection.
The <pbc|pin|PIN#> parameter specifies the WPS provisioning
method. "pbc" string starts pushbutton method, "pin" string start PIN
method using an automatically generated PIN (which will be returned as
the command return code), PIN# means that a pre-selected PIN can be
used (e.g., 12345670). [display|keypad] is used with PIN method
to specify which PIN is used (display=dynamically generated random PIN
from local display, keypad=PIN entered from peer display). "persistent"
parameter can be used to request a persistent group to be formed. The
"persistent=<network id>" alternative can be used to pre-populate
SSID/passphrase configuration based on a previously used persistent
group where this device was the GO. The previously used parameters will
then be used if the local end becomes the GO in GO Negotiation (which
can be forced with go_intent=15).
"join" indicates that this is a command to join an existing group as a
client. It skips the GO Negotiation part. This will send a Provision
Discovery Request message to the target GO before associating for WPS
provisioning.
"auth" indicates that the WPS parameters are authorized for the peer
device without actually starting GO Negotiation (i.e., the peer is
expected to initiate GO Negotiation). This is mainly for testing
purposes.
"go_intent" can be used to override the default GO Intent for this GO
Negotiation.
"freq" can be used to set a forced operating channel (e.g., freq=2412
to select 2.4 GHz channel 1).
"provdisc" can be used to request a Provision Discovery exchange to be
used prior to starting GO Negotiation as a workaround with some deployed
P2P implementations that require this to allow the user to accept the
connection.
"auto" can be used to request wpa_supplicant to automatically figure
out whether the peer device is operating as a GO and if so, use
join-a-group operation rather than GO Negotiation.
"ssid=<hexdump>" can be used to specify the Group SSID for join
operations. This allows the P2P Client interface to filter scan results
based on SSID to avoid selecting an incorrect BSS entry in case the same
P2P Device or Interface address have been used in multiple groups
recently.
P2PS attribute changes to p2p_connect command:
P2PS supports two WPS provisioning methods namely PIN method and P2PS default.
The remaining parameters hold same role as in legacy P2P. In case of P2PS
default config method "p2ps" keyword is added in p2p_connect command.
For example:
p2p_connect 02:0a:f5:85:11:00 12345670 p2ps persistent join
(WPS Method = P2PS default)
p2p_connect 02:0a:f5:85:11:00 45629034 keypad persistent
(WPS Method = PIN)
p2p_asp_provision <peer MAC address> <adv_id=peer adv id>
<adv_mac=peer MAC address> [role=2|4|1] <session=session id>
<session_mac=initiator mac address>
[info='service info'] <method=Default|keypad|Display>
This command starts provision discovery with the P2PS enabled peer device.
For example,
p2p_asp_provision 00:11:22:33:44:55 adv_id=4d6fc7 adv_mac=00:55:44:33:22:11 role=1 session=12ab34 session_mac=00:11:22:33:44:55 info='name=john' method=1000
Parameter description:
MAC address - Mandatory
adv_id - Mandatory remote Advertising ID of service connection is being
established for
adv_mac - Mandatory MAC address that owns/registered the service
role - Optional
2 (group client only) or 4 (group owner only)
if not present (or 1) role is negotiated by the two peers.
session - Mandatory Session ID of the first session to be established
session_mac - Mandatory MAC address that owns/initiated the session
method - Optional method to request for provisioning (1000 - P2PS Default,
100 - Keypad(PIN), 8 - Display(PIN))
info - Optional UTF-8 string. Hint for service to indicate possible usage
parameters - Escape single quote & backslash:
with a backslash 0x27 == ' == \', and 0x5c == \ == \\
p2p_asp_provision_resp <peer mac address> <adv_id= local adv id>
<adv_mac=local MAC address> <role=1|2|4> <status=0>
<session=session id> <session_mac=peer MAC address>
This command sends a provision discovery response from responder side.
For example,
p2p_asp_provision_resp 00:55:44:33:22:11 adv_id=4d6fc7 adv_mac=00:55:44:33:22:11 role=1 status=0 session=12ab34 session_mac=00:11:22:33:44:55
Parameters definition:
MAC address - Mandatory
adv_id - Mandatory local Advertising ID of service connection is being
established for
adv_mac - Mandatory MAC address that owns/registered the service
role - Optional 2 (group client only) or 4 (group owner only)
if not present (or 1) role is negotiated by the two peers.
status - Mandatory Acceptance/Rejection code of Provisioning
session - Mandatory Session ID of the first session to be established
session_mac - Mandatory MAC address that owns/initiated the session
p2p_group_add [persistent|persistent=<network id>] [freq=<freq in MHz>]
[ht40] [vht] [he]
Set up a P2P group owner manually (i.e., without group owner
negotiation with a specific peer). This is also known as autonomous
GO. Optional persistent=<network id> can be used to specify restart of
a persistent group. Optional freq=<freq in MHz> can be used to force
the GO to be started on a specific frequency. Special freq=2 or freq=5
options can be used to request the best 2.4 GHz or 5 GHz band channel
to be selected automatically.
p2p_reject <peer device address>
Reject connection attempt from a peer (specified with a device
address). This is a mechanism to reject a pending GO Negotiation with
a peer and request to automatically block any further connection or
discovery of the peer.
p2p_group_remove <group interface>
Terminate a P2P group. If a new virtual network interface was used for
the group, it will also be removed. The network interface name of the
group interface is used as a parameter for this command.
p2p_cancel
Cancel an ongoing P2P group formation and joining-a-group related
operation. This operation unauthorizes the specific peer device (if any
had been authorized to start group formation), stops P2P find (if in
progress), stops pending operations for join-a-group, and removes the
P2P group interface (if one was used) that is in the WPS provisioning
step. If the WPS provisioning step has been completed, the group is not
terminated.
p2p_remove_client <peer's P2P Device Address|iface=<interface address>>
This command can be used to remove the specified client from all groups
(operating and persistent) from the local GO. Note that the peer device
can rejoin the group if it is in possession of a valid key. See p2p_set
per_sta_psk command below for more details on how the peer can be
removed securely.
Service Discovery
p2p_service_add asp <auto accept> <adv id> <status 0/1> <Config Methods>
<Service name> [Service Information] [Response Info]
This command can be used to search for a P2PS service which includes
Play, Send, Display, and Print service. The parameters for this command
are "asp" to identify the command as P2PS one, auto accept value,
advertisement id which uniquely identifies the service requests, state
of the service whether the service is available or not, config methods
which can be either P2PS method or PIN method, service name followed by
two optional parameters service information, and response info.
For example,
p2p_service_add asp 1 4d6fc7 0 1108 alt.example.chat svc_info='name=john' rsp_info='enter PIN 1234'
Parameters definition:
asp - Mandatory for ASP service registration
auto accept - Mandatory ASCII hex-encoded boolean (0 == no auto-accept,
1 == auto-accept ANY role, 2 == auto-accept CLIENT role,
4 == auto-accept GO role)
Advertisement ID - Mandatory non-zero ASCII hex-encoded u32
(Must be unique/not yet exist in svc db)
State - Mandatory ASCII hex-encoded u8 (0 -- Svc not available,
1 -- Svc available, 2-0xff Application defined)
Config Methods - Mandatory ASCII hex-encoded u16 (bitmask of WSC config
methods)
Service Name - Mandatory UTF-8 string
Service Information - Optional UTF-8 string
Escape single quote & backslash with a backslash:
0x27 == ' == \', and 0x5c == \ == \\
Session response information - Optional (used only if auto accept is TRUE)
UTF-8 string
Escape single quote & backslash with a backslash:
0x27 == ' == \', and 0x5c == \ == \\
p2p_service_rep asp <auto accept> <adv id> <status 0/1> <Config Methods>
<Service name> [Service Information] [Response Info]
This command can be used to replace the existing service request
attributes from the initiator side. The replacement is only allowed if
the advertisement id issued in the command matches with any one entry in
the list of existing SD queries. If advertisement id doesn't match the
command returns a failure.
For example,
p2p_service_rep asp 1 4d6fc7 1 1108 alt.example.chat svc_info='name=john' rsp_info='enter PIN 1234'
Parameters definition:
asp - Mandatory for ASP service registration
auto accept - Mandatory ASCII hex-encoded boolean (1 == true, 0 == false)
Advertisement ID - Mandatory non-zero ASCII hex-encoded u32
(Must already exist in svc db)
State - Mandatory ASCII hex-encoded u8 (can be used to indicate svc
available or not available for instance)
Config Methods - Mandatory ASCII hex-encoded u16 (bitmask of WSC config
methods)
Service Name - Mandatory UTF-8 string (Must match existing string in svc db)
Service Information - Optional UTF-8 string
Escape single quote & backslash with a backslash:
0x27 == ' == \', and 0x5c == \ == \\
Session response information - Optional (used only if auto accept is TRUE)
UTF-8 string
Escape single quote & backslash with a backslash:
0x27 == ' == \', and 0x5c == \ == \\
p2p_serv_disc_req
Schedule a P2P service discovery request. The parameters for this
command are the device address of the peer device (or 00:00:00:00:00:00
for wildcard query that is sent to every discovered P2P peer that
supports service discovery) and P2P Service Query TLV(s) as hexdump. For
example,
p2p_serv_disc_req 00:00:00:00:00:00 02000001
schedules a request for listing all available services of all service
discovery protocols and requests this to be sent to all discovered
peers (note: this can result in long response frames). The pending
requests are sent during device discovery (see p2p_find).
There can be multiple pending peer device specific queries (each will be
sent in sequence whenever the peer is found).
This command returns an identifier for the pending query (e.g.,
"1f77628") that can be used to cancel the request. Directed requests
will be automatically removed when the specified peer has replied to
it.
Service Query TLV has following format:
Length (2 octets, little endian) - length of following data
Service Protocol Type (1 octet) - see the table below
Service Transaction ID (1 octet) - nonzero identifier for the TLV
Query Data (Length - 2 octets of data) - service protocol specific data
Service Protocol Types:
0 = All service protocols
1 = Bonjour
2 = UPnP
3 = WS-Discovery
4 = Wi-Fi Display
For UPnP, an alternative command format can be used to specify a
single query TLV (i.e., a service discovery for a specific UPnP
service):
p2p_serv_disc_req 00:00:00:00:00:00 upnp <version hex> <ST: from M-SEARCH>
For example:
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 urn:schemas-upnp-org:device:InternetGatewayDevice:1
Additional examples for queries:
# list of all Bonjour services
p2p_serv_disc_req 00:00:00:00:00:00 02000101
# list of all UPnP services
p2p_serv_disc_req 00:00:00:00:00:00 02000201
# list of all WS-Discovery services
p2p_serv_disc_req 00:00:00:00:00:00 02000301
# list of all Bonjour and UPnP services
p2p_serv_disc_req 00:00:00:00:00:00 0200010102000202
# Apple File Sharing over TCP
p2p_serv_disc_req 00:00:00:00:00:00 130001010b5f6166706f766572746370c00c000c01
# Bonjour SSTH (supported service type hash)
p2p_serv_disc_req 00:00:00:00:00:00 05000101000000
# UPnP examples
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 ssdp:all
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 upnp:rootdevice
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 urn:schemas-upnp-org:service:ContentDirectory:2
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 uuid:6859dede-8574-59ab-9332-123456789012
p2p_serv_disc_req 00:00:00:00:00:00 upnp 10 urn:schemas-upnp-org:device:InternetGatewayDevice:1
# Wi-Fi Display examples
# format: wifi-display <list of roles> <list of subelements>
p2p_serv_disc_req 00:00:00:00:00:00 wifi-display [source] 2,3,4,5
p2p_serv_disc_req 02:01:02:03:04:05 wifi-display [pri-sink] 3
p2p_serv_disc_req 00:00:00:00:00:00 wifi-display [sec-source] 2
p2p_serv_disc_req 00:00:00:00:00:00 wifi-display [source+sink] 2,3,4,5
p2p_serv_disc_req 00:00:00:00:00:00 wifi-display [source][pri-sink] 2,3,4,5
p2p_serv_disc_req <Unicast|Broadcast mac address> asp <Transaction ID>
<Service Name> [Service Information]
The command can be used for service discovery for P2PS enabled devices.
For example: p2p_serv_disc_req 00:00:00:00:00:00 asp a1 alt.example 'john'
Parameters definition:
MAC address - Mandatory Existing
asp - Mandatory for ASP queries
Transaction ID - Mandatory non-zero ASCII hex-encoded u8 for GAS
Service Name Prefix - Mandatory UTF-8 string.
Will match from beginning of remote Service Name
Service Information Substring - Optional UTF-8 string
If Service Information Substring is not included, all services matching
Service Name Prefix will be returned.
If Service Information Substring is included, both the Substring and the
Service Name Prefix must match for service to be returned.
If remote service has no Service Information, all Substring searches
will fail.
p2p_serv_disc_cancel_req <query identifier>
Cancel a pending P2P service discovery request. This command takes a
single parameter: identifier for the pending query (the value returned
by p2p_serv_disc_req, e.g., "p2p_serv_disc_cancel_req 1f77628".
p2p_serv_disc_resp
Reply to a service discovery query. This command takes following
parameters: frequency in MHz, destination address, dialog token,
response TLV(s). The first three parameters are copied from the
request event. For example, "p2p_serv_disc_resp 2437 02:40:61:c2:f3:b7
1 0300000101". This command is used only if external program is used
to process the request (see p2p_serv_disc_external).
p2p_service_update
Indicate that local services have changed. This is used to increment
the P2P service indicator value so that peers know when previously
cached information may have changed. This is only needed when external
service discovery processing is enabled since the commands to
pre-configure services for internal processing will increment the
indicator automatically.
p2p_serv_disc_external <0|1>
Configure external processing of P2P service requests: 0 (default) =
no external processing of requests (i.e., internal code will process
each request based on pre-configured services), 1 = external
processing of requests (external program is responsible for replying
to service discovery requests with p2p_serv_disc_resp). Please note
that there is quite strict limit on how quickly the response needs to
be transmitted, so use of the internal processing is strongly
recommended.
p2p_service_add bonjour <query hexdump> <RDATA hexdump>
Add a local Bonjour service for internal SD query processing.
Examples:
# AFP Over TCP (PTR)
p2p_service_add bonjour 0b5f6166706f766572746370c00c000c01 074578616d706c65c027
# AFP Over TCP (TXT) (RDATA=null)
p2p_service_add bonjour 076578616d706c650b5f6166706f766572746370c00c001001 00
# IP Printing over TCP (PTR) (RDATA=MyPrinter._ipp._tcp.local.)
p2p_service_add bonjour 045f697070c00c000c01 094d795072696e746572c027
# IP Printing over TCP (TXT) (RDATA=txtvers=1,pdl=application/postscript)
p2p_service_add bonjour 096d797072696e746572045f697070c00c001001 09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074
# Supported Service Type Hash (SSTH)
p2p_service_add bonjour 000000 <32-byte bitfield as hexdump>
(note: see P2P spec Annex E.4 for information on how to construct the bitfield)
p2p_service_del bonjour <query hexdump>
Remove a local Bonjour service from internal SD query processing.
p2p_service_add upnp <version hex> <service>
Add a local UPnP service for internal SD query processing.
Examples:
p2p_service_add upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice
p2p_service_add upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::upnp:rootdevice
p2p_service_add upnp 10 uuid:1122de4e-8574-59ab-9322-333456789044::urn:schemas-upnp-org:service:ContentDirectory:2
p2p_service_add upnp 10 uuid:5566d33e-9774-09ab-4822-333456785632::urn:schemas-upnp-org:service:ContentDirectory:2
p2p_service_add upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp-org:device:InternetGatewayDevice:1
p2p_service_del upnp <version hex> <service>
Remove a local UPnP service from internal SD query processing.
p2p_service_del asp <adv id>
Removes the local asp service from internal SD query list.
For example: p2p_service_del asp 4d6fc7
p2p_service_flush
Remove all local services from internal SD query processing.
Invitation
p2p_invite [persistent=<network id>|group=<group ifname>] [peer=address]
[go_dev_addr=address] [freq=<freq in MHz>] [ht40] [vht] [he]
[pref=<MHz>]
Invite a peer to join a group (e.g., group=wlan1) or to reinvoke a
persistent group (e.g., persistent=4). If the peer device is the GO of
the persistent group, the peer parameter is not needed. Otherwise it is
used to specify which device to invite. go_dev_addr parameter can be
used to override the GO device address for Invitation Request should
it be not known for some reason (this should not be needed in most
cases). When reinvoking a persistent group, the GO device can specify
the frequency for the group with the freq parameter. When reinvoking a
persistent group, the P2P client device can use freq parameter to force
a specific operating channel (or invitation failure if GO rejects that)
or pref parameter to request a specific channel (while allowing GO to
select to use another channel, if needed).
Group Operations
(These are used on the group interface.)
wps_pin <any|address> <PIN>
Start WPS PIN method. This allows a single WPS Enrollee to connect to
the AP/GO. This is used on the GO when a P2P client joins an existing
group. The second parameter is the address of the Enrollee or a string
"any" to allow any station to use the entered PIN (which will restrict
the PIN for one-time-use). PIN is the Enrollee PIN read either from a
label or display on the P2P Client/WPS Enrollee.
wps_pbc
Start WPS PBC method (i.e., push the button). This allows a single WPS
Enrollee to connect to the AP/GO. This is used on the GO when a P2P
client joins an existing group.
p2p_get_passphrase
Get the passphrase for a group (only available when acting as a GO).
p2p_presence_req [<duration> <interval>] [<duration> <interval>]
Send a P2P Presence Request to the GO (this is only available when
acting as a P2P client). If no duration/interval pairs are given, the
request indicates that this client has no special needs for GO
presence. The first parameter pair gives the preferred duration and
interval values in microseconds. If the second pair is included, that
indicates which value would be acceptable. This command returns OK
immediately and the response from the GO is indicated in a
P2P-PRESENCE-RESPONSE event message.
Parameters
p2p_ext_listen [<period> <interval>]
Configure Extended Listen Timing. If the parameters are omitted, this
feature is disabled. If the parameters are included, Listen State will
be entered every interval msec for at least period msec. Both values
have acceptable range of 1-65535 (with interval obviously having to be
larger than or equal to duration). If the P2P module is not idle at
the time the Extended Listen Timing timeout occurs, the Listen State
operation will be skipped.
The configured values will also be advertised to other P2P Devices. The
received values are available in the p2p_peer command output:
ext_listen_period=100 ext_listen_interval=5000
p2p_set <field> <value>
Change dynamic P2P parameters
p2p_set discoverability <0/1>
Disable/enable advertisement of client discoverability. This is
enabled by default and this parameter is mainly used to allow testing
of device discoverability.
p2p_set managed <0/1>
Disable/enable managed P2P Device operations. This is disabled by
default.
p2p_set listen_channel <channel> [<op_class>]
Set P2P Listen channel. This is mainly meant for testing purposes and
changing the Listen channel during normal operations can result in
protocol failures.
When specifying a social channel on the 2.4 GHz band (1/6/11) there is
no need to specify the operating class since it defaults to 81. When
specifying a social channel on the 60 GHz band (2), specify the 60 GHz
operating class (180).
p2p_set ssid_postfix <postfix>
Set postfix string to be added to the automatically generated P2P SSID
(DIRECT-<two random characters>). For example, postfix of "-testing"
could result in the SSID becoming DIRECT-ab-testing.
p2p_set per_sta_psk <0/1>
Disabled(default)/enables use of per-client PSK in the P2P groups. This
can be used to request GO to assign a unique PSK for each client during
WPS provisioning. When enabled, this allow clients to be removed from
the group securely with p2p_remove_client command since that client's
PSK is removed at the same time to prevent it from connecting back using
the old PSK. When per-client PSK is not used, the client can still be
disconnected, but it will be able to re-join the group since the PSK it
learned previously is still valid. It should be noted that the default
passphrase on the GO that is normally used to allow legacy stations to
connect through manual configuration does not change here, so if that is
shared, devices with knowledge of that passphrase can still connect.
set <field> <value>
Set global configuration parameters which may also affect P2P
operations. The format on these parameters is same as is used in
wpa_supplicant.conf. Only the parameters listen here should be
changed. Modifying other parameters may result in incorrect behavior
since not all existing users of the parameters are updated.
set uuid <UUID>
Set WPS UUID (by default, this is generated based on the MAC address).
set device_name <device name>
Set WPS Device Name (also included in some P2P messages).
set manufacturer <manufacturer>
Set WPS Manufacturer.
set model_name <model name>
Set WPS Model Name.
set model_number <model number>
Set WPS Model Number.
set serial_number <serial number>
Set WPS Serial Number.
set device_type <device type>
Set WPS Device Type.
set os_version <OS version>
Set WPS OS Version.
set config_methods <config methods>
Set WPS Configuration Methods.
set sec_device_type <device type>
Add a new Secondary Device Type.
set p2p_go_intent <GO intent>
Set the default P2P GO Intent. Note: This value can be overridden in
p2p_connect command and as such, there should be no need to change the
default value here during normal operations.
set p2p_ssid_postfix <P2P SSID postfix>
Set P2P SSID postfix.
set persistent_reconnect <0/1>
Disable/enabled persistent reconnect for reinvocation of persistent
groups. If enabled, invitations to reinvoke a persistent group will be
accepted without separate authorization (e.g., user interaction).
set country <two character country code>
Set country code (this is included in some P2P messages).
set p2p_search_delay <delay>
Set p2p_search_delay which adds extra delay in milliseconds between
concurrent search iterations to make p2p_find friendlier to concurrent
operations by avoiding it from taking 100% of radio resources. The
default value is 500 ms.
Status
p2p_peers [discovered]
List P2P Device Addresses of all the P2P peers we know. The optional
"discovered" parameter filters out the peers that we have not fully
discovered, i.e., which we have only seen in a received Probe Request
frame.
p2p_peer <P2P Device Address>
Fetch information about a known P2P peer.
Group Status
(These are used on the group interface.)
status
Show status information (connection state, role, use encryption
parameters, IP address, etc.).
sta
Show information about an associated station (when acting in AP/GO role).
all_sta
Lists the currently associated stations.
Configuration data
list_networks
Lists the configured networks, including stored information for
persistent groups. The identifier in this list is used with
p2p_group_add and p2p_invite to indicate which persistent group is to
be reinvoked.
remove_network <network id>
Remove a network entry from configuration.
P2PS Events/Responses:
P2PS-PROV-START: This events gets triggered when provisioning is issued for
either seeker or advertiser.
For example,
P2PS-PROV-START 00:55:44:33:22:11 adv_id=111 adv_mac=00:55:44:33:22:11 conncap=1 session=1234567 session_mac=00:11:22:33:44:55 info='xxxx'
Parameters definition:
MAC address - always
adv_id - always ASCII hex-encoded u32
adv_mac - always MAC address that owns/registered the service
conncap - always mask of 0x01 (new), 0x02 (group client), 0x04 (group owner)
bits
session - always Session ID of the first session to be established
session_mac - always MAC address that owns/initiated the session
info - if available, UTF-8 string
Escaped single quote & backslash with a backslash:
\' == 0x27 == ', and \\ == 0x5c == \
P2PS-PROV-DONE: When provisioning is completed then this event gets triggered.
For example,
P2PS-PROV-DONE 00:11:22:33:44:55 status=0 adv_id=111 adv_mac=00:55:44:33:22:11 conncap=1 session=1234567 session_mac=00:11:22:33:44:55 [dev_passwd_id=8 | go=p2p-wlan0-0 | join=11:22:33:44:55:66 | persist=0]
Parameters definition:
MAC address - always main device address of peer. May be different from MAC
ultimately connected to.
status - always ascii hex-encoded u8 (0 == success, 12 == deferred success)
adv_id - always ascii hex-encoded u32
adv_mac - always MAC address that owns/registered the service
conncap - always One of: 1 (new), 2 (group client), 4 (group owner) bits
session - always Session ID of the first session to be established
session_mac - always MAC address that owns/initiated the session
dev_passwd_id - only if conncap value == 1 (New GO negotiation)
8 - "p2ps" password must be passed in p2p_connect command
1 - "display" password must be passed in p2p_connect command
5 - "keypad" password must be passed in p2p_connect command
join only - if conncap value == 2 (Client Only). Display password and "join"
must be passed in p2p_connect and address must be the MAC specified
go only - if conncap value == 4 (GO Only). Interface name must be set with a
password
persist - only if previous persistent group existed between peers and shall
be re-used. Group is restarted by sending "p2p_group_add persistent=0"
where value is taken from P2P-PROV-DONE
Extended Events/Response
P2P-DEVICE-FOUND 00:11:22:33:44:55 p2p_dev_addr=00:11:22:33:44:55 pri_dev_type=0-00000000-0 name='' config_methods=0x108 dev_capab=0x21 group_capab=0x0 adv_id=111 asp_svc=alt.example.chat
Parameters definition:
adv_id - if ASP ASCII hex-encoded u32. If it is reporting the
"wildcard service", this value will be 0
asp_svc - if ASP this is the service string. If it is reporting the
"wildcard service", this value will be org.wi-fi.wfds
wpa_cli action script
---------------------
See examples/p2p-action.sh
TODO: describe DHCP/DNS setup
TODO: cross-connection

399
wpa_supplicant/README-WPS Normal file
View File

@ -0,0 +1,399 @@
wpa_supplicant and Wi-Fi Protected Setup (WPS)
==============================================
This document describes how the WPS implementation in wpa_supplicant
can be configured and how an external component on the client (e.g.,
management GUI) is used to enable WPS enrollment and registrar
registration.
Introduction to WPS
-------------------
Wi-Fi Protected Setup (WPS) is a mechanism for easy configuration of a
wireless network. It allows automated generation of random keys (WPA
passphrase/PSK) and configuration of an access point and client
devices. WPS includes number of methods for setting up connections
with PIN method and push-button configuration (PBC) being the most
commonly deployed options.
While WPS can enable more home networks to use encryption in the
wireless network, it should be noted that the use of the PIN and
especially PBC mechanisms for authenticating the initial key setup is
not very secure. As such, use of WPS may not be suitable for
environments that require secure network access without chance for
allowing outsiders to gain access during the setup phase.
WPS uses following terms to describe the entities participating in the
network setup:
- access point: the WLAN access point
- Registrar: a device that control a network and can authorize
addition of new devices); this may be either in the AP ("internal
Registrar") or in an external device, e.g., a laptop, ("external
Registrar")
- Enrollee: a device that is being authorized to use the network
It should also be noted that the AP and a client device may change
roles (i.e., AP acts as an Enrollee and client device as a Registrar)
when WPS is used to configure the access point.
More information about WPS is available from Wi-Fi Alliance:
http://www.wi-fi.org/wifi-protected-setup
wpa_supplicant implementation
-----------------------------
wpa_supplicant includes an optional WPS component that can be used as
an Enrollee to enroll new network credential or as a Registrar to
configure an AP.
wpa_supplicant configuration
----------------------------
WPS is an optional component that needs to be enabled in
wpa_supplicant build configuration (.config). Here is an example
configuration that includes WPS support and Linux nl80211 -based
driver interface:
CONFIG_DRIVER_NL80211=y
CONFIG_WPS=y
If you want to enable WPS external registrar (ER) functionality, you
will also need to add following line:
CONFIG_WPS_ER=y
Following parameter can be used to enable support for NFC config method:
CONFIG_WPS_NFC=y
WPS needs the Universally Unique IDentifier (UUID; see RFC 4122) for
the device. This is configured in the runtime configuration for
wpa_supplicant (if not set, UUID will be generated based on local MAC
address):
# example UUID for WPS
uuid=12345678-9abc-def0-1234-56789abcdef0
The network configuration blocks needed for WPS are added
automatically based on control interface commands, so they do not need
to be added explicitly in the configuration file.
WPS registration will generate new network blocks for the acquired
credentials. If these are to be stored for future use (after
restarting wpa_supplicant), wpa_supplicant will need to be configured
to allow configuration file updates:
update_config=1
External operations
-------------------
WPS requires either a device PIN code (usually, 8-digit number) or a
pushbutton event (for PBC) to allow a new WPS Enrollee to join the
network. wpa_supplicant uses the control interface as an input channel
for these events.
The PIN value used in the commands must be processed by an UI to
remove non-digit characters and potentially, to verify the checksum
digit. "wpa_cli wps_check_pin <PIN>" can be used to do such processing.
It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if the checksum
digit is incorrect, or the processed PIN (non-digit characters removed)
if the PIN is valid.
If the client device has a display, a random PIN has to be generated
for each WPS registration session. wpa_supplicant can do this with a
control interface request, e.g., by calling wpa_cli:
wpa_cli wps_pin any
This will return the generated 8-digit PIN which will then need to be
entered at the Registrar to complete WPS registration. At that point,
the client will be enrolled with credentials needed to connect to the
AP to access the network.
If the client device does not have a display that could show the
random PIN, a hardcoded PIN that is printed on a label can be
used. wpa_supplicant is notified this with a control interface
request, e.g., by calling wpa_cli:
wpa_cli wps_pin any 12345670
This starts the WPS negotiation in the same way as above with the
generated PIN.
When the wps_pin command is issued for an AP (including P2P GO) mode
interface, an optional timeout parameter can be used to specify
expiration timeout for the PIN in seconds. For example:
wpa_cli wps_pin any 12345670 300
If a random PIN is needed for a user interface, "wpa_cli wps_pin get"
can be used to generate a new PIN without starting WPS negotiation.
This random PIN can then be passed as an argument to another wps_pin
call when the actual operation should be started.
If the client design wants to support optional WPS PBC mode, this can
be enabled by either a physical button in the client device or a
virtual button in the user interface. The PBC operation requires that
a button is also pressed at the AP/Registrar at about the same time (2
minute window). wpa_supplicant is notified of the local button event
over the control interface, e.g., by calling wpa_cli:
wpa_cli wps_pbc
At this point, the AP/Registrar has two minutes to complete WPS
negotiation which will generate a new WPA PSK in the same way as the
PIN method described above.
If the client wants to operate in the Registrar role to learn the
current AP configuration and optionally, to configure an AP,
wpa_supplicant is notified over the control interface, e.g., with
wpa_cli:
wpa_cli wps_reg <AP BSSID> <AP PIN>
(example: wpa_cli wps_reg 02:34:56:78:9a:bc 12345670)
This is used to fetch the current AP settings instead of actually
changing them. The main difference with the wps_pin command is that
wps_reg uses the AP PIN (e.g., from a label on the AP) instead of a
PIN generated at the client.
In order to change the AP configuration, the new configuration
parameters are given to the wps_reg command:
wpa_cli wps_reg <AP BSSID> <AP PIN> <new SSID> <auth> <encr> <new key>
examples:
wpa_cli wps_reg 02:34:56:78:9a:bc 12345670 testing WPA2PSK CCMP 12345678
wpa_cli wps_reg 02:34:56:78:9a:bc 12345670 clear OPEN NONE ""
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
<encr> must be one of the following: NONE WEP TKIP CCMP
Scanning
--------
Scan results ('wpa_cli scan_results' or 'wpa_cli bss <idx>') include a
flags field that is used to indicate whether the BSS support WPS. If
the AP support WPS, but has not recently activated a Registrar, [WPS]
flag will be included. If PIN method has been recently selected,
[WPS-PIN] is shown instead. Similarly, [WPS-PBC] is shown if PBC mode
is in progress. GUI programs can use these as triggers for suggesting
a guided WPS configuration to the user. In addition, control interface
monitor events WPS-AP-AVAILABLE{,-PBC,-PIN} can be used to find out if
there are WPS enabled APs in scan results without having to go through
all the details in the GUI. These notification could be used, e.g., to
suggest possible WPS connection to the user.
wpa_gui
-------
wpa_gui-qt4 directory contains a sample GUI that shows an example of
how WPS support can be integrated into the GUI. Its main window has a
WPS tab that guides user through WPS registration with automatic AP
selection. In addition, it shows how WPS can be started manually by
selecting an AP from scan results.
Credential processing
---------------------
By default, wpa_supplicant processes received credentials and updates
its configuration internally. However, it is possible to
control these operations from external programs, if desired.
This internal processing can be disabled with wps_cred_processing=1
option. When this is used, an external program is responsible for
processing the credential attributes and updating wpa_supplicant
configuration based on them.
Following control interface messages are sent out for external programs:
WPS-CRED-RECEIVED <hexdump of Credential attribute(s)>
For example:
<2>WPS-CRED-RECEIVED 100e006f10260001011045000c6a6b6d2d7770732d74657374100300020020100f000200081027004030653462303435366332363666653064333961643135353461316634626637313234333761636664623766333939653534663166316230323061643434386235102000060266a0ee1727
wpa_supplicant as WPS External Registrar (ER)
---------------------------------------------
wpa_supplicant can be used as a WPS ER to configure an AP or enroll
new Enrollee to join the network. This functionality uses UPnP and
requires that a working IP connectivity is available with the AP (this
can be either over a wired or wireless connection).
Separate wpa_supplicant process can be started for WPS ER
operations. A special "none" driver can be used in such a case to
indicate that no local network interface is actually controlled. For
example, following command could be used to start the ER:
wpa_supplicant -Dnone -c er.conf -ieth0
Sample er.conf:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=admin
device_name=WPS External Registrar
wpa_cli commands for ER functionality:
wps_er_start [IP address]
- start WPS ER functionality
- the optional IP address parameter can be used to filter operations only
to include a single AP
- if run again while ER is active, the stored information (discovered APs
and Enrollees) are shown again
wps_er_stop
- stop WPS ER functionality
wps_er_learn <UUID|BSSID> <AP PIN>
- learn AP configuration
wps_er_set_config <UUID|BSSID> <network id>
- use AP configuration from a locally configured network (e.g., from
wps_reg command); this does not change the AP's configuration, but
only prepares a configuration to be used when enrolling a new device
to the AP
wps_er_config <UUID|BSSID> <AP PIN> <new SSID> <auth> <encr> <new key>
- examples:
wps_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 testing WPA2PSK CCMP 12345678
wpa_er_config 87654321-9abc-def0-1234-56789abc0002 12345670 clear OPEN NONE ""
<auth> must be one of the following: OPEN WPAPSK WPA2PSK
<encr> must be one of the following: NONE WEP TKIP CCMP
wps_er_pbc <Enrollee UUID|MAC address>
- accept an Enrollee PBC using External Registrar
wps_er_pin <Enrollee UUID|"any"|MAC address> <PIN> [Enrollee MAC address]
- add an Enrollee PIN to External Registrar
- if Enrollee UUID is not known, "any" can be used to add a wildcard PIN
- if the MAC address of the enrollee is known, it should be configured
to allow the AP to advertise list of authorized enrollees
WPS ER events:
WPS_EVENT_ER_AP_ADD
- WPS ER discovered an AP
WPS-ER-AP-ADD 87654321-9abc-def0-1234-56789abc0002 02:11:22:33:44:55 pri_dev_type=6-0050F204-1 wps_state=1 |Very friendly name|Company|Long description of the model|WAP|http://w1.fi/|http://w1.fi/hostapd/
WPS_EVENT_ER_AP_REMOVE
- WPS ER removed an AP entry
WPS-ER-AP-REMOVE 87654321-9abc-def0-1234-56789abc0002
WPS_EVENT_ER_ENROLLEE_ADD
- WPS ER discovered a new Enrollee
WPS-ER-ENROLLEE-ADD 2b7093f1-d6fb-5108-adbb-bea66bb87333 02:66:a0:ee:17:27 M1=1 config_methods=0x14d dev_passwd_id=0 pri_dev_type=1-0050F204-1 |Wireless Client|Company|cmodel|123|12345|
WPS_EVENT_ER_ENROLLEE_REMOVE
- WPS ER removed an Enrollee entry
WPS-ER-ENROLLEE-REMOVE 2b7093f1-d6fb-5108-adbb-bea66bb87333 02:66:a0:ee:17:27
WPS-ER-AP-SETTINGS
- WPS ER learned AP settings
WPS-ER-AP-SETTINGS uuid=fd91b4ec-e3fa-5891-a57d-8c59efeed1d2 ssid=test-wps auth_type=0x0020 encr_type=0x0008 key=12345678
WPS with NFC
------------
WPS can be used with NFC-based configuration method. An NFC tag
containing a password token from the Enrollee can be used to
authenticate the connection instead of the PIN. In addition, an NFC tag
with a configuration token can be used to transfer AP settings without
going through the WPS protocol.
When the station acts as an Enrollee, a local NFC tag with a password
token can be used by touching the NFC interface of a Registrar.
"wps_nfc [BSSID]" command starts WPS protocol run with the local end as
the Enrollee using the NFC password token that is either pre-configured
in the configuration file (wps_nfc_dev_pw_id, wps_nfc_dh_pubkey,
wps_nfc_dh_privkey, wps_nfc_dev_pw) or generated dynamically with
"wps_nfc_token <WPS|NDEF>" command. The included nfc_pw_token tool
(build with "make nfc_pw_token") can be used to generate NFC password
tokens during manufacturing (each station needs to have its own random
keys).
The "wps_nfc_config_token <WPS/NDEF>" command can be used to build an
NFC configuration token when wpa_supplicant is controlling an AP
interface (AP or P2P GO). The output value from this command is a
hexdump of the current AP configuration (WPS parameter requests this to
include only the WPS attributes; NDEF parameter requests additional NDEF
encapsulation to be included). This data needs to be written to an NFC
tag with an external program. Once written, the NFC configuration token
can be used to touch an NFC interface on a station to provision the
credentials needed to access the network.
The "wps_nfc_config_token <WPS/NDEF> <network id>" command can be used
to build an NFC configuration token based on a locally configured
network.
If the station includes NFC interface and reads an NFC tag with a MIME
media type "application/vnd.wfa.wsc", the NDEF message payload (with or
without NDEF encapsulation) can be delivered to wpa_supplicant using the
following wpa_cli command:
wps_nfc_tag_read <hexdump of payload>
If the NFC tag contains a configuration token, the network is added to
wpa_supplicant configuration. If the NFC tag contains a password token,
the token is added to the WPS Registrar component. This information can
then be used with wps_reg command (when the NFC password token was from
an AP) using a special value "nfc-pw" in place of the PIN parameter. If
the ER functionality has been started (wps_er_start), the NFC password
token is used to enable enrollment of a new station (that was the source
of the NFC password token).
"nfc_get_handover_req <NDEF> <WPS-CR>" command can be used to build the
WPS carrier record for a Handover Request Message for connection
handover. The first argument selects the format of the output data and
the second argument selects which type of connection handover is
requested (WPS-CR = Wi-Fi handover as specified in WSC 2.0).
"nfc_get_handover_sel <NDEF> <WPS> [UUID|BSSID]" command can be used to
build the contents of a Handover Select Message for connection handover
when this does not depend on the contents of the Handover Request
Message. The first argument selects the format of the output data and
the second argument selects which type of connection handover is
requested (WPS = Wi-Fi handover as specified in WSC 2.0). If the options
UUID|BSSID argument is included, this is a request to build the handover
message for the specified AP when wpa_supplicant is operating as a WPS
ER.
"nfc_report_handover <INIT/RESP> WPS <carrier from handover request>
<carrier from handover select>" can be used as an alternative way for
reporting completed NFC connection handover. The first parameter
indicates whether the local device initiated or responded to the
connection handover and the carrier records are the selected carrier
from the handover request and select messages as a hexdump.
The "wps_er_nfc_config_token <WPS/NDEF> <UUID|BSSID>" command can be
used to build an NFC configuration token for the specified AP when
wpa_supplicant is operating as a WPS ER. The output value from this
command is a hexdump of the selected AP configuration (WPS parameter
requests this to include only the WPS attributes; NDEF parameter
requests additional NDEF encapsulation to be included). This data needs
to be written to an NFC tag with an external program. Once written, the
NFC configuration token can be used to touch an NFC interface on a
station to provision the credentials needed to access the network.

View File

@ -0,0 +1,299 @@
wpa_supplicant for Windows
==========================
Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
advertisement clause removed).
wpa_supplicant has support for being used as a WPA/WPA2/IEEE 802.1X
Supplicant on Windows. The current port requires that WinPcap
(http://winpcap.polito.it/) is installed for accessing packets and the
driver interface. Both release versions 3.0 and 3.1 are supported.
The current port is still somewhat experimental. It has been tested
mainly on Windows XP (SP2) with limited set of NDIS drivers. In
addition, the current version has been reported to work with Windows
2000.
All security modes have been verified to work (at least complete
authentication and successfully ping a wired host):
- plaintext
- static WEP / open system authentication
- static WEP / shared key authentication
- IEEE 802.1X with dynamic WEP keys
- WPA-PSK, TKIP, CCMP, TKIP+CCMP
- WPA-EAP, TKIP, CCMP, TKIP+CCMP
- WPA2-PSK, TKIP, CCMP, TKIP+CCMP
- WPA2-EAP, TKIP, CCMP, TKIP+CCMP
Building wpa_supplicant with mingw
----------------------------------
The default build setup for wpa_supplicant is to use MinGW and
cross-compiling from Linux to MinGW/Windows. It should also be
possible to build this under Windows using the MinGW tools, but that
is not tested nor supported and is likely to require some changes to
the Makefile unless cygwin is used.
Building wpa_supplicant with MSVC
---------------------------------
wpa_supplicant can be built with Microsoft Visual C++ compiler. This
has been tested with Microsoft Visual C++ Toolkit 2003 and Visual
Studio 2005 using the included nmake.mak as a Makefile for nmake. IDE
can also be used by creating a project that includes the files and
defines mentioned in nmake.mak. Example VS2005 solution and project
files are included in vs2005 subdirectory. This can be used as a
starting point for building the programs with VS2005 IDE. Visual Studio
2008 Express Edition is also able to use these project files.
WinPcap development package is needed for the build and this can be
downloaded from http://www.winpcap.org/install/bin/WpdPack_4_0_2.zip. The
default nmake.mak expects this to be unpacked into C:\dev\WpdPack so
that Include and Lib directories are in this directory. The files can be
stored elsewhere as long as the WINPCAPDIR in nmake.mak is updated to
match with the selected directory. In case a project file in the IDE is
used, these Include and Lib directories need to be added to project
properties as additional include/library directories.
OpenSSL source package can be downloaded from
http://www.openssl.org/source/openssl-0.9.8i.tar.gz and built and
installed following instructions in INSTALL.W32. Note that if EAP-FAST
support will be included in the wpa_supplicant, OpenSSL needs to be
patched to# support it openssl-0.9.8i-tls-extensions.patch. The example
nmake.mak file expects OpenSSL to be installed into C:\dev\openssl, but
this directory can be modified by changing OPENSSLDIR variable in
nmake.mak.
If you do not need EAP-FAST support, you may also be able to use Win32
binary installation package of OpenSSL from
http://www.slproweb.com/products/Win32OpenSSL.html instead of building
the library yourself. In this case, you will need to copy Include and
Lib directories in suitable directory, e.g., C:\dev\openssl for the
default nmake.mak. Copy {Win32OpenSSLRoot}\include into
C:\dev\openssl\include and make C:\dev\openssl\lib subdirectory with
files from {Win32OpenSSLRoot}\VC (i.e., libeay*.lib and ssleay*.lib).
This will end up using dynamically linked OpenSSL (i.e., .dll files are
needed) for it. Alternative, you can copy files from
{Win32OpenSSLRoot}\VC\static to create a static build (no OpenSSL .dll
files needed).
Building wpa_supplicant for cygwin
----------------------------------
wpa_supplicant can be built for cygwin by installing the needed
development packages for cygwin. This includes things like compiler,
make, openssl development package, etc. In addition, developer's pack
for WinPcap (WPdpack.zip) from
http://winpcap.polito.it/install/default.htm is needed.
.config file should enable only one driver interface,
CONFIG_DRIVER_NDIS. In addition, include directories may need to be
added to match the system. An example configuration is available in
defconfig. The library and include files for WinPcap will either need
to be installed in compiler/linker default directories or their
location will need to be adding to .config when building
wpa_supplicant.
Othen than this, the build should be more or less identical to Linux
version, i.e., just run make after having created .config file. An
additional tool, win_if_list.exe, can be built by running "make
win_if_list".
Building wpa_gui
----------------
wpa_gui uses Qt application framework from Trolltech. It can be built
with the open source version of Qt4 and MinGW. Following commands can
be used to build the binary in the Qt 4 Command Prompt:
# go to the root directory of wpa_supplicant source code
cd wpa_gui-qt4
qmake -o Makefile wpa_gui.pro
make
# the wpa_gui.exe binary is created into 'release' subdirectory
Using wpa_supplicant for Windows
--------------------------------
wpa_supplicant, wpa_cli, and wpa_gui behave more or less identically to
Linux version, so instructions in README and example wpa_supplicant.conf
should be applicable for most parts. In addition, there is another
version of wpa_supplicant, wpasvc.exe, which can be used as a Windows
service and which reads its configuration from registry instead of
text file.
When using access points in "hidden SSID" mode, ap_scan=2 mode need to
be used (see wpa_supplicant.conf for more information).
Windows NDIS/WinPcap uses quite long interface names, so some care
will be needed when starting wpa_supplicant. Alternatively, the
adapter description can be used as the interface name which may be
easier since it is usually in more human-readable
format. win_if_list.exe can be used to find out the proper interface
name.
Example steps in starting up wpa_supplicant:
# win_if_list.exe
ifname: \Device\NPF_GenericNdisWanAdapter
description: Generic NdisWan adapter
ifname: \Device\NPF_{769E012B-FD17-4935-A5E3-8090C38E25D2}
description: Atheros Wireless Network Adapter (Microsoft's Packet Scheduler)
ifname: \Device\NPF_{732546E7-E26C-48E3-9871-7537B020A211}
description: Intel 8255x-based Integrated Fast Ethernet (Microsoft's Packet Scheduler)
Since the example configuration used Atheros WLAN card, the middle one
is the correct interface in this case. The interface name for -i
command line option is the full string following "ifname:" (the
"\Device\NPF_" prefix can be removed). In other words, wpa_supplicant
would be started with the following command:
# wpa_supplicant.exe -i'{769E012B-FD17-4935-A5E3-8090C38E25D2}' -c wpa_supplicant.conf -d
-d optional enables some more debugging (use -dd for even more, if
needed). It can be left out if debugging information is not needed.
With the alternative mechanism for selecting the interface, this
command has identical results in this case:
# wpa_supplicant.exe -iAtheros -c wpa_supplicant.conf -d
Simple configuration example for WPA-PSK:
#ap_scan=2
ctrl_interface=
network={
ssid="test"
key_mgmt=WPA-PSK
proto=WPA
pairwise=TKIP
psk="secret passphrase"
}
(remove '#' from the comment out ap_scan line to enable mode in which
wpa_supplicant tries to associate with the SSID without doing
scanning; this allows APs with hidden SSIDs to be used)
wpa_cli.exe and wpa_gui.exe can be used to interact with the
wpa_supplicant.exe program in the same way as with Linux. Note that
ctrl_interface is using UNIX domain sockets when built for cygwin, but
the native build for Windows uses named pipes and the contents of the
ctrl_interface configuration item is used to control access to the
interface. Anyway, this variable has to be included in the configuration
to enable the control interface.
Example SDDL string formats:
(local admins group has permission, but nobody else):
ctrl_interface=SDDL=D:(A;;GA;;;BA)
("A" == "access allowed", "GA" == GENERIC_ALL == all permissions, and
"BA" == "builtin administrators" == the local admins. The empty fields
are for flags and object GUIDs, none of which should be required in this
case.)
(local admins and the local "power users" group have permissions,
but nobody else):
ctrl_interface=SDDL=D:(A;;GA;;;BA)(A;;GA;;;PU)
(One ACCESS_ALLOWED ACE for GENERIC_ALL for builtin administrators, and
one ACCESS_ALLOWED ACE for GENERIC_ALL for power users.)
(close to wide open, but you have to be a valid user on
the machine):
ctrl_interface=SDDL=D:(A;;GA;;;AU)
(One ACCESS_ALLOWED ACE for GENERIC_ALL for the "authenticated users"
group.)
This one would allow absolutely everyone (including anonymous
users) -- this is *not* recommended, since named pipes can be attached
to from anywhere on the network (i.e. there's no "this machine only"
like there is with 127.0.0.1 sockets):
ctrl_interface=SDDL=D:(A;;GA;;;BU)(A;;GA;;;AN)
(BU == "builtin users", "AN" == "anonymous")
See also [1] for the format of ACEs, and [2] for the possible strings
that can be used for principal names.
[1]
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/ace_strings.asp
[2]
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/sid_strings.asp
Starting wpa_supplicant as a Windows service (wpasvc.exe)
---------------------------------------------------------
wpa_supplicant can be started as a Windows service by using wpasvc.exe
program that is alternative build of wpa_supplicant.exe. Most of the
core functionality of wpasvc.exe is identical to wpa_supplicant.exe,
but it is using Windows registry for configuration information instead
of a text file and command line parameters. In addition, it can be
registered as a service that can be started automatically or manually
like any other Windows service.
The root of wpa_supplicant configuration in registry is
HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant. This level includes global
parameters and a 'interfaces' subkey with all the interface configuration
(adapter to confname mapping). Each such mapping is a subkey that has
'adapter', 'config', and 'ctrl_interface' values.
This program can be run either as a normal command line application,
e.g., for debugging, with 'wpasvc.exe app' or as a Windows service.
Service need to be registered with 'wpasvc.exe reg <full path to
wpasvc.exe>'. Alternatively, 'wpasvc.exe reg' can be used to register
the service with the current location of wpasvc.exe. After this, wpasvc
can be started like any other Windows service (e.g., 'net start wpasvc')
or it can be configured to start automatically through the Services tool
in administrative tasks. The service can be unregistered with
'wpasvc.exe unreg'.
If the service is set to start during system bootup to make the
network connection available before any user has logged in, there may
be a long (half a minute or so) delay in starting up wpa_supplicant
due to WinPcap needing a driver called "Network Monitor Driver" which
is started by default on demand.
To speed up wpa_supplicant start during system bootup, "Network
Monitor Driver" can be configured to be started sooner by setting its
startup type to System instead of the default Demand. To do this, open
up Device Manager, select Show Hidden Devices, expand the "Non
Plug-and-Play devices" branch, double click "Network Monitor Driver",
go to the Driver tab, and change the Demand setting to System instead.
Configuration data is in HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs
key. Each configuration profile has its own key under this. In terms of text
files, each profile would map to a separate text file with possibly multiple
networks. Under each profile, there is a networks key that lists all
networks as a subkey. Each network has set of values in the same way as
network block in the configuration file. In addition, blobs subkey has
possible blobs as values.
HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs\test\networks\0000
ssid="example"
key_mgmt=WPA-PSK
See win_example.reg for an example on how to setup wpasvc.exe
parameters in registry. It can also be imported to registry as a
starting point for the configuration.

View File

@ -0,0 +1,545 @@
# Example wpa_supplicant build time configuration
#
# This file lists the configuration options that are used when building the
# wpa_supplicant binary. All lines starting with # are ignored. Configuration
# option lines must be commented out complete, if they are not to be included,
# i.e., just setting VARIABLE=n is not disabling that variable.
#
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
# be modified from here. In most cases, these lines should use += in order not
# to override previous values of the variables.
# Uncomment following two lines and fix the paths if you have installed OpenSSL
# or GnuTLS in non-default location
#CFLAGS += -I/usr/local/openssl/include
#LIBS += -L/usr/local/openssl/lib
# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
# the kerberos files are not in the default include path. Following line can be
# used to fix build issues on such systems (krb5.h not found).
#CFLAGS += -I/usr/include/kerberos
# Driver interface for generic Linux wireless extensions
# Note: WEXT is deprecated in the current Linux kernel version and no new
# functionality is added to it. nl80211-based interface is the new
# replacement for WEXT and its use allows wpa_supplicant to properly control
# the driver to improve existing functionality like roaming and to support new
# functionality.
#CONFIG_DRIVER_WEXT=y
# Driver interface for Linux drivers using the nl80211 kernel interface
#CONFIG_DRIVER_NL80211=y
CONFIG_LIBNL20=y
# QCA vendor extensions to nl80211
CONFIG_DRIVER_NL80211_QCA=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
#LIBS += -L/usr/local/lib
#LIBS_p += -L/usr/local/lib
#LIBS_c += -L/usr/local/lib
# Driver interface for Windows NDIS
#CONFIG_DRIVER_NDIS=y
#CFLAGS += -I/usr/include/w32api/ddk
#LIBS += -L/usr/local/lib
# For native build using mingw
#CONFIG_NATIVE_WINDOWS=y
# Additional directories for cross-compilation on Linux host for mingw target
#CFLAGS += -I/opt/mingw/mingw32/include/ddk
#LIBS += -L/opt/mingw/mingw32/lib
#CC=mingw32-gcc
# By default, driver_ndis uses WinPcap for low-level operations. This can be
# replaced with the following option which replaces WinPcap calls with NDISUIO.
# However, this requires that WZC is disabled (net stop wzcsvc) before starting
# wpa_supplicant.
# CONFIG_USE_NDISUIO=y
# Driver interface for wired Ethernet drivers
#CONFIG_DRIVER_WIRED=y
# Driver interface for the Broadcom RoboSwitch family
#CONFIG_DRIVER_ROBOSWITCH=y
# Driver interface for no driver (e.g., WPS ER only)
#CONFIG_DRIVER_NONE=y
# Solaris libraries
#LIBS += -lsocket -ldlpi -lnsl
#LIBS_c += -lsocket
# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is
# included)
CONFIG_IEEE8021X_EAPOL=y
# EAP-MD5
CONFIG_EAP_MD5=y
# EAP-MSCHAPv2
CONFIG_EAP_MSCHAPV2=y
# EAP-TLS
CONFIG_EAP_TLS=y
# EAL-PEAP
CONFIG_EAP_PEAP=y
# EAP-TTLS
CONFIG_EAP_TTLS=y
# EAP-FAST
#CONFIG_EAP_FAST=y
# EAP-GTC
CONFIG_EAP_GTC=y
# EAP-OTP
CONFIG_EAP_OTP=y
# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
CONFIG_EAP_SIM=y
# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
#CONFIG_EAP_PSK=y
# EAP-pwd (secure authentication using only a password)
CONFIG_EAP_PWD=y
# EAP-PAX
#CONFIG_EAP_PAX=y
# LEAP
CONFIG_EAP_LEAP=y
# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
CONFIG_EAP_AKA=y
# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
# This requires CONFIG_EAP_AKA to be enabled, too.
CONFIG_EAP_AKA_PRIME=y
# Enable USIM simulator (Milenage) for EAP-AKA
#CONFIG_USIM_SIMULATOR=y
# EAP-SAKE
#CONFIG_EAP_SAKE=y
# EAP-GPSK
#CONFIG_EAP_GPSK=y
# Include support for optional SHA256 cipher suite in EAP-GPSK
#CONFIG_EAP_GPSK_SHA256=y
# EAP-TNC and related Trusted Network Connect support (experimental)
#CONFIG_EAP_TNC=y
# Wi-Fi Protected Setup (WPS)
CONFIG_WPS=y
# Enable WPS external registrar functionality
CONFIG_WPS_ER=y
# Disable credentials for an open network by default when acting as a WPS
# registrar.
#CONFIG_WPS_REG_DISABLE_OPEN=y
# Enable WPS support with NFC config method
CONFIG_WPS_NFC=y
# EAP-IKEv2
#CONFIG_EAP_IKEV2=y
# EAP-EKE
#CONFIG_EAP_EKE=y
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
# engine.
CONFIG_SMARTCARD=y
# PC/SC interface for smartcards (USIM, GSM SIM)
# Enable this if EAP-SIM or EAP-AKA is included
#CONFIG_PCSC=y
# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
#CONFIG_HT_OVERRIDES=y
# Support VHT overrides (disable VHT, mask MCS rates, etc.)
#CONFIG_VHT_OVERRIDES=y
# Development testing
#CONFIG_EAPOL_TEST=y
# Select control interface backend for external programs, e.g, wpa_cli:
# unix = UNIX domain sockets (default for Linux/*BSD)
# udp = UDP sockets using localhost (127.0.0.1)
# udp6 = UDP IPv6 sockets using localhost (::1)
# named_pipe = Windows Named Pipe (default for Windows)
# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
# y = use default (backwards compatibility)
# If this option is commented out, control interface is not included in the
# build.
CONFIG_CTRL_IFACE=y
# Include support for GNU Readline and History Libraries in wpa_cli.
# When building a wpa_cli binary for distribution, please note that these
# libraries are licensed under GPL and as such, BSD license may not apply for
# the resulting binary.
#CONFIG_READLINE=y
# Include internal line edit mode in wpa_cli. This can be used as a replacement
# for GNU Readline to provide limited command line editing and history support.
CONFIG_WPA_CLI_EDIT=y
# Remove debugging code that is printing out debug message to stdout.
# This can be used to reduce the size of the wpa_supplicant considerably
# if debugging code is not needed. The size reduction can be around 35%
# (e.g., 90 kB).
#CONFIG_NO_STDOUT_DEBUG=y
# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
# 35-50 kB in code size.
#CONFIG_NO_WPA=y
# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
# This option can be used to reduce code size by removing support for
# converting ASCII passphrases into PSK. If this functionality is removed, the
# PSK can only be configured as the 64-octet hexstring (e.g., from
# wpa_passphrase). This saves about 0.5 kB in code size.
#CONFIG_NO_WPA_PASSPHRASE=y
# Disable scan result processing (ap_mode=1) to save code size by about 1 kB.
# This can be used if ap_scan=1 mode is never enabled.
#CONFIG_NO_SCAN_PROCESSING=y
# Select configuration backend:
# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
# path is given on command line, not here; this option is just used to
# select the backend that allows configuration files to be used)
# winreg = Windows registry (see win_example.reg for an example)
CONFIG_BACKEND=file
# Remove configuration write functionality (i.e., to allow the configuration
# file to be updated based on runtime configuration changes). The runtime
# configuration can still be changed, the changes are just not going to be
# persistent over restarts. This option can be used to reduce code size by
# about 3.5 kB.
#CONFIG_NO_CONFIG_WRITE=y
# Remove support for configuration blobs to reduce code size by about 1.5 kB.
#CONFIG_NO_CONFIG_BLOBS=y
# Select program entry point implementation:
# main = UNIX/POSIX like main() function (default)
# main_winsvc = Windows service (read parameters from registry)
# main_none = Very basic example (development use only)
#CONFIG_MAIN=main
# Select wrapper for operating system and C library specific functions
# unix = UNIX/POSIX like systems (default)
# win32 = Windows systems
# none = Empty template
CONFIG_OS=unix
# Select event loop implementation
# eloop = select() loop (default)
# eloop_win = Windows events and WaitForMultipleObject() loop
CONFIG_ELOOP=eloop
# Should we use poll instead of select? Select is used by default.
#CONFIG_ELOOP_POLL=y
# Should we use epoll instead of select? Select is used by default.
#CONFIG_ELOOP_EPOLL=y
# Should we use kqueue instead of select? Select is used by default.
#CONFIG_ELOOP_KQUEUE=y
# Select layer 2 packet implementation
# linux = Linux packet socket (default)
# pcap = libpcap/libdnet/WinPcap
# freebsd = FreeBSD libpcap
# winpcap = WinPcap with receive thread
# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
# none = Empty template
CONFIG_L2_PACKET=linux
# Disable Linux packet socket workaround applicable for station interface
# in a bridge for EAPOL frames. This should be uncommented only if the kernel
# is known to not have the regression issue in packet socket behavior with
# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
#CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
# Support Operating Channel Validation
#CONFIG_OCV=y
# Select TLS implementation
# openssl = OpenSSL (default)
# gnutls = GnuTLS
# internal = Internal TLSv1 implementation (experimental)
# none = Empty template
#CONFIG_TLS=openssl
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
# can be enabled to get a stronger construction of messages when block ciphers
# are used. It should be noted that some existing TLS v1.0 -based
# implementation may not be compatible with TLS v1.1 message (ClientHello is
# sent prior to negotiating which version will be used)
#CONFIG_TLSV11=y
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
# can be enabled to enable use of stronger crypto algorithms. It should be
# noted that some existing TLS v1.0 -based implementation may not be compatible
# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
# will be used)
#CONFIG_TLSV12=y
# Select which ciphers to use by default with OpenSSL if the user does not
# specify them.
#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
# If CONFIG_TLS=internal is used, additional library and include paths are
# needed for LibTomMath. Alternatively, an integrated, minimal version of
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
# and drawbacks of this option.
#CONFIG_INTERNAL_LIBTOMMATH=y
#ifndef CONFIG_INTERNAL_LIBTOMMATH
#LTM_PATH=/usr/src/libtommath-0.39
#CFLAGS += -I$(LTM_PATH)
#LIBS += -L$(LTM_PATH)
#LIBS_p += -L$(LTM_PATH)
#endif
# At the cost of about 4 kB of additional binary size, the internal LibTomMath
# can be configured to include faster routines for exptmod, sqr, and div to
# speed up DH and RSA calculation considerably
#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
# This is only for Windows builds and requires WMI-related header files and
# WbemUuid.Lib from Platform SDK even when building with MinGW.
#CONFIG_NDIS_EVENTS_INTEGRATED=y
#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
# Add support for new DBus control interface
# (fi.w1.hostap.wpa_supplicant1)
#CONFIG_CTRL_IFACE_DBUS_NEW=y
# Add introspection support for new DBus control interface
#CONFIG_CTRL_IFACE_DBUS_INTRO=y
# Add support for Binder control interface
# Only applicable for Android platforms.
#CONFIG_CTRL_IFACE_BINDER=y
# Add support for loading EAP methods dynamically as shared libraries.
# When this option is enabled, each EAP method can be either included
# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
# be loaded in the beginning of the wpa_supplicant configuration file
# (see load_dynamic_eap parameter in the example file) before being used in
# the network blocks.
#
# Note that some shared parts of EAP methods are included in the main program
# and in order to be able to use dynamic EAP methods using these parts, the
# main program must have been build with the EAP method enabled (=y or =dyn).
# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
# unless at least one of them was included in the main build to force inclusion
# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
# in the main build to be able to load these methods dynamically.
#
# Please also note that using dynamic libraries will increase the total binary
# size. Thus, it may not be the best option for targets that have limited
# amount of memory/flash.
#CONFIG_DYNAMIC_EAP_METHODS=y
# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
CONFIG_IEEE80211R=y
# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
#CONFIG_DEBUG_FILE=y
# Send debug messages to syslog instead of stdout
#CONFIG_DEBUG_SYSLOG=y
# Set syslog facility for debug messages
#CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
# Add support for sending all debug messages (regardless of debug verbosity)
# to the Linux kernel tracing facility. This helps debug the entire stack by
# making it easy to record everything happening from the driver up into the
# same file, e.g., using trace-cmd.
#CONFIG_DEBUG_LINUX_TRACING=y
# Add support for writing debug log to Android logcat instead of standard
# output
CONFIG_ANDROID_LOG=y
# Enable privilege separation (see README 'Privilege separation' for details)
#CONFIG_PRIVSEP=y
# Enable mitigation against certain attacks against TKIP by delaying Michael
# MIC error reports by a random amount of time between 0 and 60 seconds
#CONFIG_DELAYED_MIC_ERROR_REPORT=y
# Enable tracing code for developer debugging
# This tracks use of memory allocations and other registrations and reports
# incorrect use with a backtrace of call (or allocation) location.
#CONFIG_WPA_TRACE=y
# For BSD, uncomment these.
#LIBS += -lexecinfo
#LIBS_p += -lexecinfo
#LIBS_c += -lexecinfo
# Use libbfd to get more details for developer debugging
# This enables use of libbfd to get more detailed symbols for the backtraces
# generated by CONFIG_WPA_TRACE=y.
#CONFIG_WPA_TRACE_BFD=y
# For BSD, uncomment these.
#LIBS += -lbfd -liberty -lz
#LIBS_p += -lbfd -liberty -lz
#LIBS_c += -lbfd -liberty -lz
# wpa_supplicant depends on strong random number generation being available
# from the operating system. os_get_random() function is used to fetch random
# data when needed, e.g., for key generation. On Linux and BSD systems, this
# works by reading /dev/urandom. It should be noted that the OS entropy pool
# needs to be properly initialized before wpa_supplicant is started. This is
# important especially on embedded devices that do not have a hardware random
# number generator and may by default start up with minimal entropy available
# for random number generation.
#
# As a safety net, wpa_supplicant is by default trying to internally collect
# additional entropy for generating random data to mix in with the data fetched
# from the OS. This by itself is not considered to be very strong, but it may
# help in cases where the system pool is not initialized properly. However, it
# is very strongly recommended that the system pool is initialized with enough
# entropy either by using hardware assisted random number generator or by
# storing state over device reboots.
#
# wpa_supplicant can be configured to maintain its own entropy store over
# restarts to enhance random number generation. This is not perfect, but it is
# much more secure than using the same sequence of random numbers after every
# reboot. This can be enabled with -e<entropy file> command line option. The
# specified file needs to be readable and writable by wpa_supplicant.
#
# If the os_get_random() is known to provide strong random data (e.g., on
# Linux/BSD, the board in question is known to have reliable source of random
# data from /dev/urandom), the internal wpa_supplicant random pool can be
# disabled. This will save some in binary size and CPU use. However, this
# should only be considered for builds that are known to be used on devices
# that meet the requirements described above.
# Wpa_supplicant's random pool is not necessary on Android. Randomness is
# already provided by the entropymixer service which ensures sufficient
# entropy is maintained across reboots. Commit b410eb1913 'Initialize
# /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
# either wpa_supplicant or hostapd are run.
CONFIG_NO_RANDOM_POOL=y
# IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
#CONFIG_IEEE80211AC=y
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
CONFIG_WNM=y
# Interworking (IEEE 802.11u)
# This can be used to enable functionality to improve interworking with
# external networks (GAS/ANQP to learn more about the networks and network
# selection based on available credentials).
CONFIG_INTERWORKING=y
# Hotspot 2.0
CONFIG_HS20=y
# Enable interface matching in wpa_supplicant
#CONFIG_MATCH_IFACE=y
# Disable roaming in wpa_supplicant
CONFIG_NO_ROAMING=y
# AP mode operations with wpa_supplicant
# This can be used for controlling AP mode operations with wpa_supplicant. It
# should be noted that this is mainly aimed at simple cases like
# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
# external RADIUS server can be supported with hostapd.
CONFIG_AP=y
# P2P (Wi-Fi Direct)
# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
# more information on P2P operations.
CONFIG_P2P=y
# Enable TDLS support
CONFIG_TDLS=y
# Wi-Fi Display
# This can be used to enable Wi-Fi Display extensions for P2P using an external
# program to control the additional information exchanges in the messages.
CONFIG_WIFI_DISPLAY=y
# Autoscan
# This can be used to enable automatic scan support in wpa_supplicant.
# See wpa_supplicant.conf for more information on autoscan usage.
#
# Enabling directly a module will enable autoscan support.
# For exponential module:
#CONFIG_AUTOSCAN_EXPONENTIAL=y
# For periodic module:
#CONFIG_AUTOSCAN_PERIODIC=y
# Password (and passphrase, etc.) backend for external storage
# These optional mechanisms can be used to add support for storing passwords
# and other secrets in external (to wpa_supplicant) location. This allows, for
# example, operating system specific key storage to be used
#
# External password backend for testing purposes (developer use)
#CONFIG_EXT_PASSWORD_TEST=y
# Enable Fast Session Transfer (FST)
#CONFIG_FST=y
# Support Multi Band Operation
#CONFIG_MBO=y
# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
#CONFIG_FILS=y
# Support RSN on IBSS networks
# This is needed to be able to use mode=1 network profile with proto=RSN and
# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
#CONFIG_IBSS_RSN=y
# External PMKSA cache control
# This can be used to enable control interface commands that allow the current
# PMKSA cache entries to be fetched and new entries to be added.
#CONFIG_PMKSA_CACHE_EXTERNAL=y
# Mesh Networking (IEEE 802.11s)
#CONFIG_MESH=y
# Background scanning modules
# These can be used to request wpa_supplicant to perform background scanning
# operations for roaming within an ESS (same SSID). See the bgscan parameter in
# the wpa_supplicant.conf file for more details.
# Periodic background scans based on signal strength
#CONFIG_BGSCAN_SIMPLE=y
# Learn channels used by the network and try to avoid bgscans on other
# channels (experimental)
#CONFIG_BGSCAN_LEARN=y
# Opportunistic Wireless Encryption (OWE)
# Experimental implementation of draft-harkins-owe-07.txt
#CONFIG_OWE=y
# Wired equivalent privacy (WEP)
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
# considered secure. It should not be used for anything anymore. The
# functionality needed to use WEP is available in the current wpa_supplicant
# release under this optional build parameter. This functionality is subject to
# be completely removed in a future release.
CONFIG_WEP=y
include $(wildcard $(LOCAL_PATH)/android_config_*.inc)

1945
wpa_supplicant/ap.c Normal file

File diff suppressed because it is too large Load Diff

106
wpa_supplicant/ap.h Normal file
View File

@ -0,0 +1,106 @@
/*
* WPA Supplicant - Basic AP mode support routines
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2009, Atheros Communications
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef AP_H
#define AP_H
int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpa_supplicant_ap_deinit(struct wpa_supplicant *wpa_s);
void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s,
const u8 *src_addr, const u8 *buf, size_t len);
int wpa_supplicant_ap_wps_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
const u8 *p2p_dev_addr);
int wpa_supplicant_ap_wps_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
const char *pin, char *buf, size_t buflen,
int timeout);
int wpa_supplicant_ap_wps_cancel(struct wpa_supplicant *wpa_s);
void wpas_wps_ap_pin_disable(struct wpa_supplicant *wpa_s);
const char * wpas_wps_ap_pin_random(struct wpa_supplicant *wpa_s, int timeout);
const char * wpas_wps_ap_pin_get(struct wpa_supplicant *wpa_s);
int wpas_wps_ap_pin_set(struct wpa_supplicant *wpa_s, const char *pin,
int timeout);
int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
char *buf, size_t buflen);
int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
char *buf, size_t buflen);
int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
char *buf, size_t buflen);
int ap_ctrl_iface_sta_deauthenticate(struct wpa_supplicant *wpa_s,
const char *txtaddr);
int ap_ctrl_iface_sta_disassociate(struct wpa_supplicant *wpa_s,
const char *txtaddr);
int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
size_t buflen, int verbose);
void ap_tx_status(void *ctx, const u8 *addr,
const u8 *buf, size_t len, int ack);
void ap_eapol_tx_status(void *ctx, const u8 *dst,
const u8 *data, size_t len, int ack);
void ap_client_poll_ok(void *ctx, const u8 *addr);
void ap_rx_from_unknown_sta(void *ctx, const u8 *addr, int wds);
void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt);
void ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok);
int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s);
int wpa_supplicant_ap_mac_addr_filter(struct wpa_supplicant *wpa_s,
const u8 *addr);
void wpa_supplicant_ap_pwd_auth_fail(struct wpa_supplicant *wpa_s);
int ap_switch_channel(struct wpa_supplicant *wpa_s,
struct csa_settings *settings);
int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *txtaddr);
void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
int offset, int width, int cf1, int cf2, int finished);
struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
int ndef);
#ifdef CONFIG_AP
struct wpabuf * wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
int ndef);
#else /* CONFIG_AP */
static inline struct wpabuf *
wpas_ap_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
int ndef)
{
return NULL;
}
#endif /* CONFIG_AP */
int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
const struct wpabuf *req,
const struct wpabuf *sel);
int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
const struct wpabuf *pw, const u8 *pubkey_hash);
struct hostapd_config;
int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct hostapd_config *conf);
int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s);
int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
size_t len);
void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
char *buf, size_t len);
int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd);
int wpas_ap_update_beacon(struct wpa_supplicant *wpa_s);
void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
void wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
void wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
void wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
void ap_periodic(struct wpa_supplicant *wpa_s);
#endif /* AP_H */

162
wpa_supplicant/autoscan.c Normal file
View File

@ -0,0 +1,162 @@
/*
* WPA Supplicant - auto scan
* Copyright (c) 2012, Intel Corporation. All rights reserved.
* Copyright 2015 Intel Deutschland GmbH
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "config.h"
#include "wpa_supplicant_i.h"
#include "bss.h"
#include "scan.h"
#include "autoscan.h"
static const struct autoscan_ops * autoscan_modules[] = {
#ifdef CONFIG_AUTOSCAN_EXPONENTIAL
&autoscan_exponential_ops,
#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */
#ifdef CONFIG_AUTOSCAN_PERIODIC
&autoscan_periodic_ops,
#endif /* CONFIG_AUTOSCAN_PERIODIC */
NULL
};
static void request_scan(struct wpa_supplicant *wpa_s)
{
wpa_s->scan_req = MANUAL_SCAN_REQ;
if (wpa_supplicant_req_sched_scan(wpa_s))
wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval, 0);
}
int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan)
{
const char *name = wpa_s->conf->autoscan;
const char *params;
size_t nlen;
int i;
const struct autoscan_ops *ops = NULL;
struct sched_scan_plan *scan_plans;
/* Give preference to scheduled scan plans if supported/configured */
if (wpa_s->sched_scan_plans) {
wpa_printf(MSG_DEBUG,
"autoscan: sched_scan_plans set - use it instead");
return 0;
}
if (wpa_s->autoscan && wpa_s->autoscan_priv) {
wpa_printf(MSG_DEBUG, "autoscan: Already initialized");
return 0;
}
if (name == NULL)
return 0;
params = os_strchr(name, ':');
if (params == NULL) {
params = "";
nlen = os_strlen(name);
} else {
nlen = params - name;
params++;
}
for (i = 0; autoscan_modules[i]; i++) {
if (os_strncmp(name, autoscan_modules[i]->name, nlen) == 0) {
ops = autoscan_modules[i];
break;
}
}
if (ops == NULL) {
wpa_printf(MSG_ERROR, "autoscan: Could not find module "
"matching the parameter '%s'", name);
return -1;
}
scan_plans = os_malloc(sizeof(*wpa_s->sched_scan_plans));
if (!scan_plans)
return -1;
wpa_s->autoscan_params = NULL;
wpa_s->autoscan_priv = ops->init(wpa_s, params);
if (!wpa_s->autoscan_priv) {
os_free(scan_plans);
return -1;
}
scan_plans[0].interval = 5;
scan_plans[0].iterations = 0;
os_free(wpa_s->sched_scan_plans);
wpa_s->sched_scan_plans = scan_plans;
wpa_s->sched_scan_plans_num = 1;
wpa_s->autoscan = ops;
wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with "
"parameters '%s'", ops->name, params);
if (!req_scan)
return 0;
/*
* Cancelling existing scan requests, if any.
*/
wpa_supplicant_cancel_sched_scan(wpa_s);
wpa_supplicant_cancel_scan(wpa_s);
/*
* Firing first scan, which will lead to call autoscan_notify_scan.
*/
request_scan(wpa_s);
return 0;
}
void autoscan_deinit(struct wpa_supplicant *wpa_s)
{
if (wpa_s->autoscan && wpa_s->autoscan_priv) {
wpa_printf(MSG_DEBUG, "autoscan: Deinitializing module '%s'",
wpa_s->autoscan->name);
wpa_s->autoscan->deinit(wpa_s->autoscan_priv);
wpa_s->autoscan = NULL;
wpa_s->autoscan_priv = NULL;
wpa_s->scan_interval = 5;
os_free(wpa_s->sched_scan_plans);
wpa_s->sched_scan_plans = NULL;
wpa_s->sched_scan_plans_num = 0;
}
}
int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
{
int interval;
if (wpa_s->autoscan && wpa_s->autoscan_priv) {
interval = wpa_s->autoscan->notify_scan(wpa_s->autoscan_priv,
scan_res);
if (interval <= 0)
return -1;
wpa_s->scan_interval = interval;
wpa_s->sched_scan_plans[0].interval = interval;
request_scan(wpa_s);
}
return 0;
}

59
wpa_supplicant/autoscan.h Normal file
View File

@ -0,0 +1,59 @@
/*
* WPA Supplicant - auto scan
* Copyright (c) 2012, Intel Corporation. All rights reserved.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef AUTOSCAN_H
#define AUTOSCAN_H
struct wpa_supplicant;
struct autoscan_ops {
const char *name;
void * (*init)(struct wpa_supplicant *wpa_s, const char *params);
void (*deinit)(void *priv);
int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res);
};
#ifdef CONFIG_AUTOSCAN
int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan);
void autoscan_deinit(struct wpa_supplicant *wpa_s);
int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
/* Available autoscan modules */
#ifdef CONFIG_AUTOSCAN_EXPONENTIAL
extern const struct autoscan_ops autoscan_exponential_ops;
#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */
#ifdef CONFIG_AUTOSCAN_PERIODIC
extern const struct autoscan_ops autoscan_periodic_ops;
#endif /* CONFIG_AUTOSCAN_PERIODIC */
#else /* CONFIG_AUTOSCAN */
static inline int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan)
{
return 0;
}
static inline void autoscan_deinit(struct wpa_supplicant *wpa_s)
{
}
static inline int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
{
return 0;
}
#endif /* CONFIG_AUTOSCAN */
#endif /* AUTOSCAN_H */

View File

@ -0,0 +1,104 @@
/*
* WPA Supplicant - auto scan exponential module
* Copyright (c) 2012, Intel Corporation. All rights reserved.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "wpa_supplicant_i.h"
#include "autoscan.h"
struct autoscan_exponential_data {
struct wpa_supplicant *wpa_s;
int base;
int limit;
int interval;
};
static int
autoscan_exponential_get_params(struct autoscan_exponential_data *data,
const char *params)
{
const char *pos;
if (params == NULL)
return -1;
data->base = atoi(params);
pos = os_strchr(params, ':');
if (pos == NULL)
return -1;
pos++;
data->limit = atoi(pos);
return 0;
}
static void * autoscan_exponential_init(struct wpa_supplicant *wpa_s,
const char *params)
{
struct autoscan_exponential_data *data;
data = os_zalloc(sizeof(struct autoscan_exponential_data));
if (data == NULL)
return NULL;
if (autoscan_exponential_get_params(data, params) < 0) {
os_free(data);
return NULL;
}
wpa_printf(MSG_DEBUG, "autoscan exponential: base exponential is %d "
"and limit is %d", data->base, data->limit);
data->wpa_s = wpa_s;
return data;
}
static void autoscan_exponential_deinit(void *priv)
{
struct autoscan_exponential_data *data = priv;
os_free(data);
}
static int autoscan_exponential_notify_scan(void *priv,
struct wpa_scan_results *scan_res)
{
struct autoscan_exponential_data *data = priv;
wpa_printf(MSG_DEBUG, "autoscan exponential: scan result "
"notification");
if (data->interval >= data->limit)
return data->limit;
if (data->interval <= 0)
data->interval = data->base;
else {
data->interval = data->interval * data->base;
if (data->interval > data->limit)
return data->limit;
}
return data->interval;
}
const struct autoscan_ops autoscan_exponential_ops = {
.name = "exponential",
.init = autoscan_exponential_init,
.deinit = autoscan_exponential_deinit,
.notify_scan = autoscan_exponential_notify_scan,
};

View File

@ -0,0 +1,85 @@
/*
* WPA Supplicant - auto scan periodic module
* Copyright (c) 2012, Intel Corporation. All rights reserved.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "wpa_supplicant_i.h"
#include "autoscan.h"
struct autoscan_periodic_data {
int periodic_interval;
};
static int autoscan_periodic_get_params(struct autoscan_periodic_data *data,
const char *params)
{
int interval;
if (params == NULL)
return -1;
interval = atoi(params);
if (interval < 0)
return -1;
data->periodic_interval = interval;
return 0;
}
static void * autoscan_periodic_init(struct wpa_supplicant *wpa_s,
const char *params)
{
struct autoscan_periodic_data *data;
data = os_zalloc(sizeof(struct autoscan_periodic_data));
if (data == NULL)
return NULL;
if (autoscan_periodic_get_params(data, params) < 0) {
os_free(data);
return NULL;
}
wpa_printf(MSG_DEBUG, "autoscan periodic: interval is %d",
data->periodic_interval);
return data;
}
static void autoscan_periodic_deinit(void *priv)
{
struct autoscan_periodic_data *data = priv;
os_free(data);
}
static int autoscan_periodic_notify_scan(void *priv,
struct wpa_scan_results *scan_res)
{
struct autoscan_periodic_data *data = priv;
wpa_printf(MSG_DEBUG, "autoscan periodic: scan result notification");
return data->periodic_interval;
}
const struct autoscan_ops autoscan_periodic_ops = {
.name = "periodic",
.init = autoscan_periodic_init,
.deinit = autoscan_periodic_deinit,
.notify_scan = autoscan_periodic_notify_scan,
};

109
wpa_supplicant/bgscan.c Normal file
View File

@ -0,0 +1,109 @@
/*
* WPA Supplicant - background scan and roaming interface
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "wpa_supplicant_i.h"
#include "config_ssid.h"
#include "bgscan.h"
static const struct bgscan_ops * bgscan_modules[] = {
#ifdef CONFIG_BGSCAN_SIMPLE
&bgscan_simple_ops,
#endif /* CONFIG_BGSCAN_SIMPLE */
#ifdef CONFIG_BGSCAN_LEARN
&bgscan_learn_ops,
#endif /* CONFIG_BGSCAN_LEARN */
NULL
};
int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
const char *name)
{
const char *params;
size_t nlen;
int i;
const struct bgscan_ops *ops = NULL;
bgscan_deinit(wpa_s);
params = os_strchr(name, ':');
if (params == NULL) {
params = "";
nlen = os_strlen(name);
} else {
nlen = params - name;
params++;
}
for (i = 0; bgscan_modules[i]; i++) {
if (os_strncmp(name, bgscan_modules[i]->name, nlen) == 0) {
ops = bgscan_modules[i];
break;
}
}
if (ops == NULL) {
wpa_printf(MSG_ERROR, "bgscan: Could not find module "
"matching the parameter '%s'", name);
return -1;
}
wpa_s->bgscan_priv = ops->init(wpa_s, params, ssid);
if (wpa_s->bgscan_priv == NULL)
return -1;
wpa_s->bgscan = ops;
wpa_printf(MSG_DEBUG, "bgscan: Initialized module '%s' with "
"parameters '%s'", ops->name, params);
return 0;
}
void bgscan_deinit(struct wpa_supplicant *wpa_s)
{
if (wpa_s->bgscan && wpa_s->bgscan_priv) {
wpa_printf(MSG_DEBUG, "bgscan: Deinitializing module '%s'",
wpa_s->bgscan->name);
wpa_s->bgscan->deinit(wpa_s->bgscan_priv);
wpa_s->bgscan = NULL;
wpa_s->bgscan_priv = NULL;
}
}
int bgscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
{
if (wpa_s->bgscan && wpa_s->bgscan_priv)
return wpa_s->bgscan->notify_scan(wpa_s->bgscan_priv,
scan_res);
return 0;
}
void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s)
{
if (wpa_s->bgscan && wpa_s->bgscan_priv)
wpa_s->bgscan->notify_beacon_loss(wpa_s->bgscan_priv);
}
void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above,
int current_signal, int current_noise,
int current_txrate)
{
if (wpa_s->bgscan && wpa_s->bgscan_priv)
wpa_s->bgscan->notify_signal_change(wpa_s->bgscan_priv, above,
current_signal,
current_noise,
current_txrate);
}

82
wpa_supplicant/bgscan.h Normal file
View File

@ -0,0 +1,82 @@
/*
* WPA Supplicant - background scan and roaming interface
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef BGSCAN_H
#define BGSCAN_H
struct wpa_supplicant;
struct wpa_ssid;
struct bgscan_ops {
const char *name;
void * (*init)(struct wpa_supplicant *wpa_s, const char *params,
const struct wpa_ssid *ssid);
void (*deinit)(void *priv);
int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res);
void (*notify_beacon_loss)(void *priv);
void (*notify_signal_change)(void *priv, int above,
int current_signal,
int current_noise,
int current_txrate);
};
#ifdef CONFIG_BGSCAN
int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
const char *name);
void bgscan_deinit(struct wpa_supplicant *wpa_s);
int bgscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s);
void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above,
int current_signal, int current_noise,
int current_txrate);
/* Available bgscan modules */
#ifdef CONFIG_BGSCAN_SIMPLE
extern const struct bgscan_ops bgscan_simple_ops;
#endif /* CONFIG_BGSCAN_SIMPLE */
#ifdef CONFIG_BGSCAN_LEARN
extern const struct bgscan_ops bgscan_learn_ops;
#endif /* CONFIG_BGSCAN_LEARN */
#else /* CONFIG_BGSCAN */
static inline int bgscan_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, const char name)
{
return 0;
}
static inline void bgscan_deinit(struct wpa_supplicant *wpa_s)
{
}
static inline int bgscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
{
return 0;
}
static inline void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s)
{
}
static inline void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s,
int above, int current_signal,
int current_noise,
int current_txrate)
{
}
#endif /* CONFIG_BGSCAN */
#endif /* BGSCAN_H */

View File

@ -0,0 +1,614 @@
/*
* WPA Supplicant - background scan and roaming module: learn
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "eloop.h"
#include "list.h"
#include "common/ieee802_11_defs.h"
#include "drivers/driver.h"
#include "config_ssid.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "scan.h"
#include "bgscan.h"
struct bgscan_learn_bss {
struct dl_list list;
u8 bssid[ETH_ALEN];
int freq;
u8 *neigh; /* num_neigh * ETH_ALEN buffer */
size_t num_neigh;
};
struct bgscan_learn_data {
struct wpa_supplicant *wpa_s;
const struct wpa_ssid *ssid;
int scan_interval;
int signal_threshold;
int short_interval; /* use if signal < threshold */
int long_interval; /* use if signal > threshold */
struct os_reltime last_bgscan;
char *fname;
struct dl_list bss;
int *supp_freqs;
int probe_idx;
};
static void bss_free(struct bgscan_learn_bss *bss)
{
os_free(bss->neigh);
os_free(bss);
}
static int bssid_in_array(u8 *array, size_t array_len, const u8 *bssid)
{
size_t i;
if (array == NULL || array_len == 0)
return 0;
for (i = 0; i < array_len; i++) {
if (os_memcmp(array + i * ETH_ALEN, bssid, ETH_ALEN) == 0)
return 1;
}
return 0;
}
static void bgscan_learn_add_neighbor(struct bgscan_learn_bss *bss,
const u8 *bssid)
{
u8 *n;
if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
return;
if (bssid_in_array(bss->neigh, bss->num_neigh, bssid))
return;
n = os_realloc_array(bss->neigh, bss->num_neigh + 1, ETH_ALEN);
if (n == NULL)
return;
os_memcpy(n + bss->num_neigh * ETH_ALEN, bssid, ETH_ALEN);
bss->neigh = n;
bss->num_neigh++;
}
static struct bgscan_learn_bss * bgscan_learn_get_bss(
struct bgscan_learn_data *data, const u8 *bssid)
{
struct bgscan_learn_bss *bss;
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
return bss;
}
return NULL;
}
static int bgscan_learn_load(struct bgscan_learn_data *data)
{
FILE *f;
char buf[128];
struct bgscan_learn_bss *bss;
if (data->fname == NULL)
return 0;
f = fopen(data->fname, "r");
if (f == NULL)
return 0;
wpa_printf(MSG_DEBUG, "bgscan learn: Loading data from %s",
data->fname);
if (fgets(buf, sizeof(buf), f) == NULL ||
os_strncmp(buf, "wpa_supplicant-bgscan-learn\n", 28) != 0) {
wpa_printf(MSG_INFO, "bgscan learn: Invalid data file %s",
data->fname);
fclose(f);
return -1;
}
while (fgets(buf, sizeof(buf), f)) {
if (os_strncmp(buf, "BSS ", 4) == 0) {
bss = os_zalloc(sizeof(*bss));
if (!bss)
continue;
if (hwaddr_aton(buf + 4, bss->bssid) < 0) {
bss_free(bss);
continue;
}
bss->freq = atoi(buf + 4 + 18);
dl_list_add(&data->bss, &bss->list);
wpa_printf(MSG_DEBUG, "bgscan learn: Loaded BSS "
"entry: " MACSTR " freq=%d",
MAC2STR(bss->bssid), bss->freq);
}
if (os_strncmp(buf, "NEIGHBOR ", 9) == 0) {
u8 addr[ETH_ALEN];
if (hwaddr_aton(buf + 9, addr) < 0)
continue;
bss = bgscan_learn_get_bss(data, addr);
if (bss == NULL)
continue;
if (hwaddr_aton(buf + 9 + 18, addr) < 0)
continue;
bgscan_learn_add_neighbor(bss, addr);
}
}
fclose(f);
return 0;
}
static void bgscan_learn_save(struct bgscan_learn_data *data)
{
FILE *f;
struct bgscan_learn_bss *bss;
if (data->fname == NULL)
return;
wpa_printf(MSG_DEBUG, "bgscan learn: Saving data to %s",
data->fname);
f = fopen(data->fname, "w");
if (f == NULL)
return;
fprintf(f, "wpa_supplicant-bgscan-learn\n");
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
fprintf(f, "BSS " MACSTR " %d\n",
MAC2STR(bss->bssid), bss->freq);
}
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
size_t i;
for (i = 0; i < bss->num_neigh; i++) {
fprintf(f, "NEIGHBOR " MACSTR " " MACSTR "\n",
MAC2STR(bss->bssid),
MAC2STR(bss->neigh + i * ETH_ALEN));
}
}
fclose(f);
}
static int in_array(int *array, int val)
{
int i;
if (array == NULL)
return 0;
for (i = 0; array[i]; i++) {
if (array[i] == val)
return 1;
}
return 0;
}
static int * bgscan_learn_get_freqs(struct bgscan_learn_data *data,
size_t *count)
{
struct bgscan_learn_bss *bss;
int *freqs = NULL, *n;
*count = 0;
dl_list_for_each(bss, &data->bss, struct bgscan_learn_bss, list) {
if (in_array(freqs, bss->freq))
continue;
n = os_realloc_array(freqs, *count + 2, sizeof(int));
if (n == NULL)
return freqs;
freqs = n;
freqs[*count] = bss->freq;
(*count)++;
freqs[*count] = 0;
}
return freqs;
}
static int * bgscan_learn_get_probe_freq(struct bgscan_learn_data *data,
int *freqs, size_t count)
{
int idx, *n;
if (data->supp_freqs == NULL)
return freqs;
idx = data->probe_idx;
do {
if (!in_array(freqs, data->supp_freqs[idx])) {
wpa_printf(MSG_DEBUG, "bgscan learn: Probe new freq "
"%u", data->supp_freqs[idx]);
data->probe_idx = idx + 1;
if (data->supp_freqs[data->probe_idx] == 0)
data->probe_idx = 0;
n = os_realloc_array(freqs, count + 2, sizeof(int));
if (n == NULL)
return freqs;
freqs = n;
freqs[count] = data->supp_freqs[idx];
count++;
freqs[count] = 0;
break;
}
idx++;
if (data->supp_freqs[idx] == 0)
idx = 0;
} while (idx != data->probe_idx);
return freqs;
}
static void bgscan_learn_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct bgscan_learn_data *data = eloop_ctx;
struct wpa_supplicant *wpa_s = data->wpa_s;
struct wpa_driver_scan_params params;
int *freqs = NULL;
size_t count, i;
char msg[100], *pos;
os_memset(&params, 0, sizeof(params));
params.num_ssids = 1;
params.ssids[0].ssid = data->ssid->ssid;
params.ssids[0].ssid_len = data->ssid->ssid_len;
if (data->ssid->scan_freq)
params.freqs = data->ssid->scan_freq;
else {
freqs = bgscan_learn_get_freqs(data, &count);
wpa_printf(MSG_DEBUG, "bgscan learn: BSSes in this ESS have "
"been seen on %u channels", (unsigned int) count);
freqs = bgscan_learn_get_probe_freq(data, freqs, count);
msg[0] = '\0';
pos = msg;
for (i = 0; freqs && freqs[i]; i++) {
int ret;
ret = os_snprintf(pos, msg + sizeof(msg) - pos, " %d",
freqs[i]);
if (os_snprintf_error(msg + sizeof(msg) - pos, ret))
break;
pos += ret;
}
pos[0] = '\0';
wpa_printf(MSG_DEBUG, "bgscan learn: Scanning frequencies:%s",
msg);
params.freqs = freqs;
}
wpa_printf(MSG_DEBUG, "bgscan learn: Request a background scan");
if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
wpa_printf(MSG_DEBUG, "bgscan learn: Failed to trigger scan");
eloop_register_timeout(data->scan_interval, 0,
bgscan_learn_timeout, data, NULL);
} else
os_get_reltime(&data->last_bgscan);
os_free(freqs);
}
static int bgscan_learn_get_params(struct bgscan_learn_data *data,
const char *params)
{
const char *pos;
data->short_interval = atoi(params);
pos = os_strchr(params, ':');
if (pos == NULL)
return 0;
pos++;
data->signal_threshold = atoi(pos);
pos = os_strchr(pos, ':');
if (pos == NULL) {
wpa_printf(MSG_ERROR, "bgscan learn: Missing scan interval "
"for high signal");
return -1;
}
pos++;
data->long_interval = atoi(pos);
pos = os_strchr(pos, ':');
if (pos) {
pos++;
data->fname = os_strdup(pos);
}
return 0;
}
static int * bgscan_learn_get_supp_freqs(struct wpa_supplicant *wpa_s)
{
struct hostapd_hw_modes *modes;
int i, j, *freqs = NULL, *n;
size_t count = 0;
modes = wpa_s->hw.modes;
if (modes == NULL)
return NULL;
for (i = 0; i < wpa_s->hw.num_modes; i++) {
for (j = 0; j < modes[i].num_channels; j++) {
if (modes[i].channels[j].flag & HOSTAPD_CHAN_DISABLED)
continue;
/* some hw modes (e.g. 11b & 11g) contain same freqs */
if (in_array(freqs, modes[i].channels[j].freq))
continue;
n = os_realloc_array(freqs, count + 2, sizeof(int));
if (n == NULL)
continue;
freqs = n;
freqs[count] = modes[i].channels[j].freq;
count++;
freqs[count] = 0;
}
}
return freqs;
}
static void * bgscan_learn_init(struct wpa_supplicant *wpa_s,
const char *params,
const struct wpa_ssid *ssid)
{
struct bgscan_learn_data *data;
data = os_zalloc(sizeof(*data));
if (data == NULL)
return NULL;
dl_list_init(&data->bss);
data->wpa_s = wpa_s;
data->ssid = ssid;
if (bgscan_learn_get_params(data, params) < 0) {
os_free(data->fname);
os_free(data);
return NULL;
}
if (data->short_interval <= 0)
data->short_interval = 30;
if (data->long_interval <= 0)
data->long_interval = 30;
if (bgscan_learn_load(data) < 0) {
os_free(data->fname);
os_free(data);
return NULL;
}
wpa_printf(MSG_DEBUG, "bgscan learn: Signal strength threshold %d "
"Short bgscan interval %d Long bgscan interval %d",
data->signal_threshold, data->short_interval,
data->long_interval);
if (data->signal_threshold &&
wpa_drv_signal_monitor(wpa_s, data->signal_threshold, 4) < 0) {
wpa_printf(MSG_ERROR, "bgscan learn: Failed to enable "
"signal strength monitoring");
}
data->supp_freqs = bgscan_learn_get_supp_freqs(wpa_s);
data->scan_interval = data->short_interval;
if (data->signal_threshold) {
/* Poll for signal info to set initial scan interval */
struct wpa_signal_info siginfo;
if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
siginfo.current_signal >= data->signal_threshold)
data->scan_interval = data->long_interval;
}
eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout,
data, NULL);
/*
* This function is called immediately after an association, so it is
* reasonable to assume that a scan was completed recently. This makes
* us skip an immediate new scan in cases where the current signal
* level is below the bgscan threshold.
*/
os_get_reltime(&data->last_bgscan);
return data;
}
static void bgscan_learn_deinit(void *priv)
{
struct bgscan_learn_data *data = priv;
struct bgscan_learn_bss *bss, *n;
bgscan_learn_save(data);
eloop_cancel_timeout(bgscan_learn_timeout, data, NULL);
if (data->signal_threshold)
wpa_drv_signal_monitor(data->wpa_s, 0, 0);
os_free(data->fname);
dl_list_for_each_safe(bss, n, &data->bss, struct bgscan_learn_bss,
list) {
dl_list_del(&bss->list);
bss_free(bss);
}
os_free(data->supp_freqs);
os_free(data);
}
static int bgscan_learn_bss_match(struct bgscan_learn_data *data,
struct wpa_scan_res *bss)
{
const u8 *ie;
ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
if (ie == NULL)
return 0;
if (data->ssid->ssid_len != ie[1] ||
os_memcmp(data->ssid->ssid, ie + 2, ie[1]) != 0)
return 0; /* SSID mismatch */
return 1;
}
static int bgscan_learn_notify_scan(void *priv,
struct wpa_scan_results *scan_res)
{
struct bgscan_learn_data *data = priv;
size_t i, j;
#define MAX_BSS 50
u8 bssid[MAX_BSS * ETH_ALEN];
size_t num_bssid = 0;
wpa_printf(MSG_DEBUG, "bgscan learn: scan result notification");
eloop_cancel_timeout(bgscan_learn_timeout, data, NULL);
eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout,
data, NULL);
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *res = scan_res->res[i];
if (!bgscan_learn_bss_match(data, res))
continue;
if (num_bssid < MAX_BSS) {
os_memcpy(bssid + num_bssid * ETH_ALEN, res->bssid,
ETH_ALEN);
num_bssid++;
}
}
wpa_printf(MSG_DEBUG, "bgscan learn: %u matching BSSes in scan "
"results", (unsigned int) num_bssid);
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *res = scan_res->res[i];
struct bgscan_learn_bss *bss;
if (!bgscan_learn_bss_match(data, res))
continue;
bss = bgscan_learn_get_bss(data, res->bssid);
if (bss && bss->freq != res->freq) {
wpa_printf(MSG_DEBUG, "bgscan learn: Update BSS "
MACSTR " freq %d -> %d",
MAC2STR(res->bssid), bss->freq, res->freq);
bss->freq = res->freq;
} else if (!bss) {
wpa_printf(MSG_DEBUG, "bgscan learn: Add BSS " MACSTR
" freq=%d", MAC2STR(res->bssid), res->freq);
bss = os_zalloc(sizeof(*bss));
if (!bss)
continue;
os_memcpy(bss->bssid, res->bssid, ETH_ALEN);
bss->freq = res->freq;
dl_list_add(&data->bss, &bss->list);
}
for (j = 0; j < num_bssid; j++) {
u8 *addr = bssid + j * ETH_ALEN;
bgscan_learn_add_neighbor(bss, addr);
}
}
/*
* A more advanced bgscan could process scan results internally, select
* the BSS and request roam if needed. This sample uses the existing
* BSS/ESS selection routine. Change this to return 1 if selection is
* done inside the bgscan module.
*/
return 0;
}
static void bgscan_learn_notify_beacon_loss(void *priv)
{
wpa_printf(MSG_DEBUG, "bgscan learn: beacon loss");
/* TODO: speed up background scanning */
}
static void bgscan_learn_notify_signal_change(void *priv, int above,
int current_signal,
int current_noise,
int current_txrate)
{
struct bgscan_learn_data *data = priv;
int scan = 0;
struct os_reltime now;
if (data->short_interval == data->long_interval ||
data->signal_threshold == 0)
return;
wpa_printf(MSG_DEBUG, "bgscan learn: signal level changed "
"(above=%d current_signal=%d current_noise=%d "
"current_txrate=%d)", above, current_signal,
current_noise, current_txrate);
if (data->scan_interval == data->long_interval && !above) {
wpa_printf(MSG_DEBUG, "bgscan learn: Start using short bgscan "
"interval");
data->scan_interval = data->short_interval;
os_get_reltime(&now);
if (now.sec > data->last_bgscan.sec + 1)
scan = 1;
} else if (data->scan_interval == data->short_interval && above) {
wpa_printf(MSG_DEBUG, "bgscan learn: Start using long bgscan "
"interval");
data->scan_interval = data->long_interval;
eloop_cancel_timeout(bgscan_learn_timeout, data, NULL);
eloop_register_timeout(data->scan_interval, 0,
bgscan_learn_timeout, data, NULL);
} else if (!above) {
/*
* Signal dropped further 4 dB. Request a new scan if we have
* not yet scanned in a while.
*/
os_get_reltime(&now);
if (now.sec > data->last_bgscan.sec + 10)
scan = 1;
}
if (scan) {
wpa_printf(MSG_DEBUG, "bgscan learn: Trigger immediate scan");
eloop_cancel_timeout(bgscan_learn_timeout, data, NULL);
eloop_register_timeout(0, 0, bgscan_learn_timeout, data, NULL);
}
}
const struct bgscan_ops bgscan_learn_ops = {
.name = "learn",
.init = bgscan_learn_init,
.deinit = bgscan_learn_deinit,
.notify_scan = bgscan_learn_notify_scan,
.notify_beacon_loss = bgscan_learn_notify_beacon_loss,
.notify_signal_change = bgscan_learn_notify_signal_change,
};

View File

@ -0,0 +1,275 @@
/*
* WPA Supplicant - background scan and roaming module: simple
* Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "eloop.h"
#include "drivers/driver.h"
#include "config_ssid.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "scan.h"
#include "bgscan.h"
struct bgscan_simple_data {
struct wpa_supplicant *wpa_s;
const struct wpa_ssid *ssid;
int scan_interval;
int signal_threshold;
int short_scan_count; /* counter for scans using short scan interval */
int max_short_scans; /* maximum times we short-scan before back-off */
int short_interval; /* use if signal < threshold */
int long_interval; /* use if signal > threshold */
struct os_reltime last_bgscan;
};
static void bgscan_simple_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct bgscan_simple_data *data = eloop_ctx;
struct wpa_supplicant *wpa_s = data->wpa_s;
struct wpa_driver_scan_params params;
os_memset(&params, 0, sizeof(params));
params.num_ssids = 1;
params.ssids[0].ssid = data->ssid->ssid;
params.ssids[0].ssid_len = data->ssid->ssid_len;
params.freqs = data->ssid->scan_freq;
/*
* A more advanced bgscan module would learn about most like channels
* over time and request scans only for some channels (probing others
* every now and then) to reduce effect on the data connection.
*/
wpa_printf(MSG_DEBUG, "bgscan simple: Request a background scan");
if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
wpa_printf(MSG_DEBUG, "bgscan simple: Failed to trigger scan");
eloop_register_timeout(data->scan_interval, 0,
bgscan_simple_timeout, data, NULL);
} else {
if (data->scan_interval == data->short_interval) {
data->short_scan_count++;
if (data->short_scan_count >= data->max_short_scans) {
data->scan_interval = data->long_interval;
wpa_printf(MSG_DEBUG, "bgscan simple: Backing "
"off to long scan interval");
}
} else if (data->short_scan_count > 0) {
/*
* If we lasted a long scan interval without any
* CQM triggers, decrease the short-scan count,
* which allows 1 more short-scan interval to
* occur in the future when CQM triggers.
*/
data->short_scan_count--;
}
os_get_reltime(&data->last_bgscan);
}
}
static int bgscan_simple_get_params(struct bgscan_simple_data *data,
const char *params)
{
const char *pos;
data->short_interval = atoi(params);
pos = os_strchr(params, ':');
if (pos == NULL)
return 0;
pos++;
data->signal_threshold = atoi(pos);
pos = os_strchr(pos, ':');
if (pos == NULL) {
wpa_printf(MSG_ERROR, "bgscan simple: Missing scan interval "
"for high signal");
return -1;
}
pos++;
data->long_interval = atoi(pos);
return 0;
}
static void * bgscan_simple_init(struct wpa_supplicant *wpa_s,
const char *params,
const struct wpa_ssid *ssid)
{
struct bgscan_simple_data *data;
data = os_zalloc(sizeof(*data));
if (data == NULL)
return NULL;
data->wpa_s = wpa_s;
data->ssid = ssid;
if (bgscan_simple_get_params(data, params) < 0) {
os_free(data);
return NULL;
}
if (data->short_interval <= 0)
data->short_interval = 30;
if (data->long_interval <= 0)
data->long_interval = 30;
wpa_printf(MSG_DEBUG, "bgscan simple: Signal strength threshold %d "
"Short bgscan interval %d Long bgscan interval %d",
data->signal_threshold, data->short_interval,
data->long_interval);
if (data->signal_threshold &&
wpa_drv_signal_monitor(wpa_s, data->signal_threshold, 4) < 0) {
wpa_printf(MSG_ERROR, "bgscan simple: Failed to enable "
"signal strength monitoring");
}
data->scan_interval = data->short_interval;
data->max_short_scans = data->long_interval / data->short_interval + 1;
if (data->signal_threshold) {
/* Poll for signal info to set initial scan interval */
struct wpa_signal_info siginfo;
if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
siginfo.current_signal >= data->signal_threshold)
data->scan_interval = data->long_interval;
}
wpa_printf(MSG_DEBUG, "bgscan simple: Init scan interval: %d",
data->scan_interval);
eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
data, NULL);
/*
* This function is called immediately after an association, so it is
* reasonable to assume that a scan was completed recently. This makes
* us skip an immediate new scan in cases where the current signal
* level is below the bgscan threshold.
*/
os_get_reltime(&data->last_bgscan);
return data;
}
static void bgscan_simple_deinit(void *priv)
{
struct bgscan_simple_data *data = priv;
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
if (data->signal_threshold)
wpa_drv_signal_monitor(data->wpa_s, 0, 0);
os_free(data);
}
static int bgscan_simple_notify_scan(void *priv,
struct wpa_scan_results *scan_res)
{
struct bgscan_simple_data *data = priv;
wpa_printf(MSG_DEBUG, "bgscan simple: scan result notification");
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
eloop_register_timeout(data->scan_interval, 0, bgscan_simple_timeout,
data, NULL);
/*
* A more advanced bgscan could process scan results internally, select
* the BSS and request roam if needed. This sample uses the existing
* BSS/ESS selection routine. Change this to return 1 if selection is
* done inside the bgscan module.
*/
return 0;
}
static void bgscan_simple_notify_beacon_loss(void *priv)
{
wpa_printf(MSG_DEBUG, "bgscan simple: beacon loss");
/* TODO: speed up background scanning */
}
static void bgscan_simple_notify_signal_change(void *priv, int above,
int current_signal,
int current_noise,
int current_txrate)
{
struct bgscan_simple_data *data = priv;
int scan = 0;
struct os_reltime now;
if (data->short_interval == data->long_interval ||
data->signal_threshold == 0)
return;
wpa_printf(MSG_DEBUG, "bgscan simple: signal level changed "
"(above=%d current_signal=%d current_noise=%d "
"current_txrate=%d))", above, current_signal,
current_noise, current_txrate);
if (data->scan_interval == data->long_interval && !above) {
wpa_printf(MSG_DEBUG, "bgscan simple: Start using short "
"bgscan interval");
data->scan_interval = data->short_interval;
os_get_reltime(&now);
if (now.sec > data->last_bgscan.sec + 1 &&
data->short_scan_count <= data->max_short_scans)
/*
* If we haven't just previously (<1 second ago)
* performed a scan, and we haven't depleted our
* budget for short-scans, perform a scan
* immediately.
*/
scan = 1;
else if (data->last_bgscan.sec + data->long_interval >
now.sec + data->scan_interval) {
/*
* Restart scan interval timer if currently scheduled
* scan is too far in the future.
*/
eloop_cancel_timeout(bgscan_simple_timeout, data,
NULL);
eloop_register_timeout(data->scan_interval, 0,
bgscan_simple_timeout, data,
NULL);
}
} else if (data->scan_interval == data->short_interval && above) {
wpa_printf(MSG_DEBUG, "bgscan simple: Start using long bgscan "
"interval");
data->scan_interval = data->long_interval;
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
eloop_register_timeout(data->scan_interval, 0,
bgscan_simple_timeout, data, NULL);
} else if (!above) {
/*
* Signal dropped further 4 dB. Request a new scan if we have
* not yet scanned in a while.
*/
os_get_reltime(&now);
if (now.sec > data->last_bgscan.sec + 10)
scan = 1;
}
if (scan) {
wpa_printf(MSG_DEBUG, "bgscan simple: Trigger immediate scan");
eloop_cancel_timeout(bgscan_simple_timeout, data, NULL);
eloop_register_timeout(0, 0, bgscan_simple_timeout, data,
NULL);
}
}
const struct bgscan_ops bgscan_simple_ops = {
.name = "simple",
.init = bgscan_simple_init,
.deinit = bgscan_simple_deinit,
.notify_scan = bgscan_simple_notify_scan,
.notify_beacon_loss = bgscan_simple_notify_beacon_loss,
.notify_signal_change = bgscan_simple_notify_signal_change,
};

View File

@ -0,0 +1,9 @@
BasedOnStyle: LLVM
IndentWidth: 8
UseTab: Always
BreakBeforeBraces: Mozilla
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
AccessModifierOffset: -8
AlignAfterOpenBracket: AlwaysBreak
SortIncludes: false

View File

@ -0,0 +1,104 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include "binder_manager.h"
extern "C" {
#include "binder.h"
#include "binder_i.h"
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/includes.h"
}
void wpas_binder_sock_handler(int sock, void *eloop_ctx, void *sock_ctx)
{
struct wpa_global *global = (wpa_global *)eloop_ctx;
struct wpas_binder_priv *priv = (wpas_binder_priv *)sock_ctx;
wpa_printf(
MSG_DEBUG, "Processing binder events on FD %d", priv->binder_fd);
android::IPCThreadState::self()->handlePolledCommands();
}
struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global)
{
struct wpas_binder_priv *priv;
wpa_supplicant_binder::BinderManager *binder_manager;
priv = (wpas_binder_priv *)os_zalloc(sizeof(*priv));
if (!priv)
return NULL;
priv->global = global;
android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
android::IPCThreadState::self()->disableBackgroundScheduling(true);
android::IPCThreadState::self()->setupPolling(&priv->binder_fd);
wpa_printf(MSG_INFO, "Process binder events on FD %d", priv->binder_fd);
if (priv->binder_fd < 0)
goto err;
/* Look for read events from the binder socket in the eloop. */
if (eloop_register_read_sock(
priv->binder_fd, wpas_binder_sock_handler, global, priv) < 0)
goto err;
binder_manager = wpa_supplicant_binder::BinderManager::getInstance();
if (!binder_manager)
goto err;
binder_manager->registerBinderService(global);
/* We may not need to store this binder manager reference in the
* global data strucure because we've made it a singleton class. */
priv->binder_manager = (void *)binder_manager;
return priv;
err:
wpas_binder_deinit(priv);
return NULL;
}
void wpas_binder_deinit(struct wpas_binder_priv *priv)
{
if (!priv)
return;
wpa_supplicant_binder::BinderManager::destroyInstance();
eloop_unregister_read_sock(priv->binder_fd);
android::IPCThreadState::shutdown();
}
int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
{
if (!wpa_s->global->binder)
return 1;
wpa_supplicant_binder::BinderManager *binder_manager =
wpa_supplicant_binder::BinderManager::getInstance();
if (!binder_manager)
return 1;
return binder_manager->registerInterface(wpa_s);
}
int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
{
if (!wpa_s->global->binder)
return 1;
wpa_supplicant_binder::BinderManager *binder_manager =
wpa_supplicant_binder::BinderManager::getInstance();
if (!binder_manager)
return 1;
return binder_manager->unregisterInterface(wpa_s);
}

View File

@ -0,0 +1,46 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_SUPPLICANT_BINDER_BINDER_H
#define WPA_SUPPLICANT_BINDER_BINDER_H
#ifdef _cplusplus
extern "C" {
#endif /* _cplusplus */
/**
* This is the binder RPC interface entry point to the wpa_supplicant core.
* This initializes the binder driver & BinderManager instance and then forwards
* all the notifications from the supplicant core to the BinderManager.
*/
struct wpas_binder_priv;
struct wpa_global;
struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global);
void wpas_binder_deinit(struct wpas_binder_priv *priv);
#ifdef CONFIG_CTRL_IFACE_BINDER
int wpas_binder_register_interface(struct wpa_supplicant *wpa_s);
int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s);
#else /* CONFIG_CTRL_IFACE_BINDER */
static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
{
return 0;
}
static inline int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
{
return 0;
}
#endif /* CONFIG_CTRL_IFACE_BINDER */
#ifdef _cplusplus
}
#endif /* _cplusplus */
#endif /* WPA_SUPPLICANT_BINDER_BINDER_H */

View File

@ -0,0 +1,18 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "binder_constants.h"
namespace wpa_supplicant_binder {
namespace binder_constants {
const char kServiceName[] = "wpa_supplicant";
} /* namespace binder_constants */
} /* namespace wpa_supplicant_binder */

View File

@ -0,0 +1,21 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H
#define WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H
namespace wpa_supplicant_binder {
namespace binder_constants {
extern const char kServiceName[];
} /* namespace binder_constants */
} /* namespace wpa_supplicant_binder */
#endif /* WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H */

View File

@ -0,0 +1,28 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef BINDER_I_H
#define BINDER_I_H
#ifdef _cplusplus
extern "C" {
#endif // _cplusplus
struct wpas_binder_priv
{
int binder_fd;
struct wpa_global *global;
void *binder_manager;
};
#ifdef _cplusplus
}
#endif /* _cplusplus */
#endif /* BINDER_I_H */

View File

@ -0,0 +1,100 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include <binder/IServiceManager.h>
#include "binder_constants.h"
#include "binder_manager.h"
extern "C" {
#include "utils/common.h"
#include "utils/includes.h"
}
namespace wpa_supplicant_binder {
BinderManager *BinderManager::instance_ = NULL;
BinderManager *BinderManager::getInstance()
{
if (!instance_)
instance_ = new BinderManager();
return instance_;
}
void BinderManager::destroyInstance()
{
if (instance_)
delete instance_;
instance_ = NULL;
}
int BinderManager::registerBinderService(struct wpa_global *global)
{
/* Create the main binder service object and register with
* system service manager. */
supplicant_object_ = new Supplicant(global);
android::String16 service_name(binder_constants::kServiceName);
android::defaultServiceManager()->addService(
service_name, android::IInterface::asBinder(supplicant_object_));
return 0;
}
int BinderManager::registerInterface(struct wpa_supplicant *wpa_s)
{
if (!wpa_s)
return 1;
/* Using the corresponding wpa_supplicant pointer as key to our
* object map. */
const void *iface_key = wpa_s;
/* Return failure if we already have an object for that iface_key. */
if (iface_object_map_.find(iface_key) != iface_object_map_.end())
return 1;
iface_object_map_[iface_key] = new Iface(wpa_s);
if (!iface_object_map_[iface_key].get())
return 1;
wpa_s->binder_object_key = iface_key;
return 0;
}
int BinderManager::unregisterInterface(struct wpa_supplicant *wpa_s)
{
if (!wpa_s || !wpa_s->binder_object_key)
return 1;
const void *iface_key = wpa_s;
if (iface_object_map_.find(iface_key) == iface_object_map_.end())
return 1;
/* Delete the corresponding iface object from our map. */
iface_object_map_.erase(iface_key);
wpa_s->binder_object_key = NULL;
return 0;
}
int BinderManager::getIfaceBinderObjectByKey(
const void *iface_object_key,
android::sp<fi::w1::wpa_supplicant::IIface> *iface_object)
{
if (!iface_object_key || !iface_object)
return 1;
if (iface_object_map_.find(iface_object_key) == iface_object_map_.end())
return 1;
*iface_object = iface_object_map_[iface_object_key];
return 0;
}
} /* namespace wpa_supplicant_binder */

View File

@ -0,0 +1,58 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H
#define WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H
#include <map>
#include <string>
#include "iface.h"
#include "supplicant.h"
struct wpa_global;
struct wpa_supplicant;
namespace wpa_supplicant_binder {
/**
* BinderManager is responsible for managing the lifetime of all
* binder objects created by wpa_supplicant. This is a singleton
* class which is created by the supplicant core and can be used
* to get references to the binder objects.
*/
class BinderManager
{
public:
static BinderManager *getInstance();
static void destroyInstance();
int registerBinderService(struct wpa_global *global);
int registerInterface(struct wpa_supplicant *wpa_s);
int unregisterInterface(struct wpa_supplicant *wpa_s);
int getIfaceBinderObjectByKey(
const void *iface_object_key,
android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
private:
BinderManager() = default;
~BinderManager() = default;
/* Singleton instance of this class. */
static BinderManager *instance_;
/* The main binder service object. */
android::sp<Supplicant> supplicant_object_;
/* Map of all the interface specific binder objects controlled by
* wpa_supplicant. This map is keyed in by the corresponding
* wpa_supplicant structure pointer. */
std::map<const void *, android::sp<Iface>> iface_object_map_;
};
} /* namespace wpa_supplicant_binder */
#endif /* WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H */

View File

@ -0,0 +1,16 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "iface.h"
namespace wpa_supplicant_binder {
Iface::Iface(struct wpa_supplicant *wpa_s) : wpa_s_(wpa_s) {}
} /* namespace wpa_supplicant_binder */

View File

@ -0,0 +1,42 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_SUPPLICANT_BINDER_IFACE_H
#define WPA_SUPPLICANT_BINDER_IFACE_H
#include "fi/w1/wpa_supplicant/BnIface.h"
extern "C" {
#include "utils/common.h"
#include "utils/includes.h"
#include "../wpa_supplicant_i.h"
}
namespace wpa_supplicant_binder {
/**
* Implementation of Iface binder object. Each unique binder
* object is used for control operations on a specific interface
* controlled by wpa_supplicant.
*/
class Iface : public fi::w1::wpa_supplicant::BnIface
{
public:
Iface(struct wpa_supplicant *wpa_s);
virtual ~Iface() = default;
private:
/* Raw pointer to the structure maintained by the core for this
* interface. */
struct wpa_supplicant *wpa_s_;
};
} /* namespace wpa_supplicant_binder */
#endif /* WPA_SUPPLICANT_BINDER_IFACE_H */

View File

@ -0,0 +1,127 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "supplicant.h"
#include "binder_manager.h"
namespace wpa_supplicant_binder {
Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {}
android::binder::Status Supplicant::CreateInterface(
const android::os::PersistableBundle &params,
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
{
android::String16 driver, ifname, confname, bridge_ifname;
/* Check if required Ifname argument is missing */
if (!params.getString(android::String16("Ifname"), &ifname))
return android::binder::Status::fromServiceSpecificError(
ERROR_INVALID_ARGS,
android::String8("Ifname missing in params."));
/* Retrieve the remaining params from the dictionary */
params.getString(android::String16("Driver"), &driver);
params.getString(android::String16("ConfigFile"), &confname);
params.getString(android::String16("BridgeIfname"), &bridge_ifname);
/*
* Try to get the wpa_supplicant record for this iface, return
* an error if we already control it.
*/
if (wpa_supplicant_get_iface(
wpa_global_, android::String8(ifname).string()) != NULL)
return android::binder::Status::fromServiceSpecificError(
ERROR_IFACE_EXISTS,
android::String8("wpa_supplicant already controls this "
"interface."));
android::binder::Status status;
struct wpa_supplicant *wpa_s = NULL;
struct wpa_interface iface;
os_memset(&iface, 0, sizeof(iface));
iface.driver = os_strdup(android::String8(driver).string());
iface.ifname = os_strdup(android::String8(ifname).string());
iface.confname = os_strdup(android::String8(confname).string());
iface.bridge_ifname =
os_strdup(android::String8(bridge_ifname).string());
/* Otherwise, have wpa_supplicant attach to it. */
wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
/* The supplicant core creates a corresponding binder object via
* BinderManager when |wpa_supplicant_add_iface| is called. */
if (!wpa_s || !wpa_s->binder_object_key) {
status = android::binder::Status::fromServiceSpecificError(
ERROR_UNKNOWN,
android::String8(
"wpa_supplicant couldn't grab this interface."));
} else {
BinderManager *binder_manager = BinderManager::getInstance();
if (!binder_manager ||
binder_manager->getIfaceBinderObjectByKey(
wpa_s->binder_object_key, aidl_return))
status =
android::binder::Status::fromServiceSpecificError(
ERROR_UNKNOWN,
android::String8("wpa_supplicant encountered a "
"binder error."));
else
status = android::binder::Status::ok();
}
os_free((void *)iface.driver);
os_free((void *)iface.ifname);
os_free((void *)iface.confname);
os_free((void *)iface.bridge_ifname);
return status;
}
android::binder::Status Supplicant::RemoveInterface(const std::string &ifname)
{
struct wpa_supplicant *wpa_s;
wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
if (!wpa_s || !wpa_s->binder_object_key)
return android::binder::Status::fromServiceSpecificError(
ERROR_IFACE_UNKNOWN,
android::String8("wpa_supplicant does not control this "
"interface."));
if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0))
return android::binder::Status::fromServiceSpecificError(
ERROR_UNKNOWN,
android::String8(
"wpa_supplicant couldn't remove this interface."));
return android::binder::Status::ok();
}
android::binder::Status Supplicant::GetInterface(
const std::string &ifname,
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
{
struct wpa_supplicant *wpa_s;
wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
if (!wpa_s || !wpa_s->binder_object_key)
return android::binder::Status::fromServiceSpecificError(
ERROR_IFACE_UNKNOWN,
android::String8(
"wpa_supplicant does not control this interface."));
BinderManager *binder_manager = BinderManager::getInstance();
if (!binder_manager ||
binder_manager->getIfaceBinderObjectByKey(
wpa_s->binder_object_key, aidl_return))
return android::binder::Status::fromServiceSpecificError(
ERROR_UNKNOWN,
android::String8(
"wpa_supplicant encountered a binder error."));
return android::binder::Status::ok();
}
} /* namespace wpa_supplicant_binder */

View File

@ -0,0 +1,55 @@
/*
* binder interface for wpa_supplicant daemon
* Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_SUPPLICANT_BINDER_SUPPLICANT_H
#define WPA_SUPPLICANT_BINDER_SUPPLICANT_H
#include "fi/w1/wpa_supplicant/BnSupplicant.h"
#include "fi/w1/wpa_supplicant/IIface.h"
#include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
extern "C" {
#include "utils/common.h"
#include "utils/includes.h"
#include "../wpa_supplicant_i.h"
}
namespace wpa_supplicant_binder {
/**
* Implementation of the supplicant binder object. This binder
* object is used core for global control operations on
* wpa_supplicant.
*/
class Supplicant : public fi::w1::wpa_supplicant::BnSupplicant
{
public:
Supplicant(struct wpa_global *global);
virtual ~Supplicant() = default;
android::binder::Status CreateInterface(
const android::os::PersistableBundle &params,
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
android::binder::Status
RemoveInterface(const std::string &ifname) override;
android::binder::Status GetInterface(
const std::string &ifname,
android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
private:
/* Raw pointer to the global structure maintained by the core. */
struct wpa_global *wpa_global_;
/* All the callback objects registered by the clients. */
std::vector<android::sp<fi::w1::wpa_supplicant::ISupplicantCallbacks>>
callbacks_;
};
} /* namespace wpa_supplicant_binder */
#endif /* WPA_SUPPLICANT_BINDER_SUPPLICANT_H */

1385
wpa_supplicant/bss.c Normal file

File diff suppressed because it is too large Load Diff

200
wpa_supplicant/bss.h Normal file
View File

@ -0,0 +1,200 @@
/*
* BSS table
* Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef BSS_H
#define BSS_H
struct wpa_scan_res;
#define WPA_BSS_QUAL_INVALID BIT(0)
#define WPA_BSS_NOISE_INVALID BIT(1)
#define WPA_BSS_LEVEL_INVALID BIT(2)
#define WPA_BSS_LEVEL_DBM BIT(3)
#define WPA_BSS_AUTHENTICATED BIT(4)
#define WPA_BSS_ASSOCIATED BIT(5)
#define WPA_BSS_ANQP_FETCH_TRIED BIT(6)
#define WPA_BSS_OWE_TRANSITION BIT(7)
#define WPA_BSS_FREQ_CHANGED_FLAG BIT(0)
#define WPA_BSS_SIGNAL_CHANGED_FLAG BIT(1)
#define WPA_BSS_PRIVACY_CHANGED_FLAG BIT(2)
#define WPA_BSS_MODE_CHANGED_FLAG BIT(3)
#define WPA_BSS_WPAIE_CHANGED_FLAG BIT(4)
#define WPA_BSS_RSNIE_CHANGED_FLAG BIT(5)
#define WPA_BSS_WPS_CHANGED_FLAG BIT(6)
#define WPA_BSS_RATES_CHANGED_FLAG BIT(7)
#define WPA_BSS_IES_CHANGED_FLAG BIT(8)
struct wpa_bss_anqp_elem {
struct dl_list list;
u16 infoid;
bool protected_response; /* received in a protected GAS response */
struct wpabuf *payload;
};
/**
* struct wpa_bss_anqp - ANQP data for a BSS entry (struct wpa_bss)
*/
struct wpa_bss_anqp {
/** Number of BSS entries referring to this ANQP data instance */
unsigned int users;
#ifdef CONFIG_INTERWORKING
struct wpabuf *capability_list;
struct wpabuf *venue_name;
struct wpabuf *network_auth_type;
struct wpabuf *roaming_consortium;
struct wpabuf *ip_addr_type_availability;
struct wpabuf *nai_realm;
struct wpabuf *anqp_3gpp;
struct wpabuf *domain_name;
struct wpabuf *fils_realm_info;
struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
struct wpabuf *hs20_capability_list;
struct wpabuf *hs20_operator_friendly_name;
struct wpabuf *hs20_wan_metrics;
struct wpabuf *hs20_connection_capability;
struct wpabuf *hs20_operating_class;
struct wpabuf *hs20_osu_providers_list;
struct wpabuf *hs20_operator_icon_metadata;
struct wpabuf *hs20_osu_providers_nai_list;
#endif /* CONFIG_HS20 */
};
/**
* struct wpa_bss - BSS table
*
* This structure is used to store information about neighboring BSSes in
* generic format. It is mainly updated based on scan results from the driver.
*/
struct wpa_bss {
/** List entry for struct wpa_supplicant::bss */
struct dl_list list;
/** List entry for struct wpa_supplicant::bss_id */
struct dl_list list_id;
/** Unique identifier for this BSS entry */
unsigned int id;
/** Number of counts without seeing this BSS */
unsigned int scan_miss_count;
/** Index of the last scan update */
unsigned int last_update_idx;
/** Information flags about the BSS/IBSS (WPA_BSS_*) */
unsigned int flags;
/** BSSID */
u8 bssid[ETH_ALEN];
/** HESSID */
u8 hessid[ETH_ALEN];
/** SSID */
u8 ssid[SSID_MAX_LEN];
/** Length of SSID */
size_t ssid_len;
/** Frequency of the channel in MHz (e.g., 2412 = channel 1) */
int freq;
/** Beacon interval in TUs (host byte order) */
u16 beacon_int;
/** Capability information field in host byte order */
u16 caps;
/** Signal quality */
int qual;
/** Noise level */
int noise;
/** Signal level */
int level;
/** Timestamp of last Beacon/Probe Response frame */
u64 tsf;
/** Time of the last update (i.e., Beacon or Probe Response RX) */
struct os_reltime last_update;
/** Estimated throughput in kbps */
unsigned int est_throughput;
/** Signal-to-noise ratio in dB */
int snr;
/** ANQP data */
struct wpa_bss_anqp *anqp;
/** Length of the following IE field in octets (from Probe Response) */
size_t ie_len;
/** Length of the following Beacon IE field in octets */
size_t beacon_ie_len;
/* followed by ie_len octets of IEs */
/* followed by beacon_ie_len octets of IEs */
u8 ies[];
};
static inline const u8 * wpa_bss_ie_ptr(const struct wpa_bss *bss)
{
return bss->ies;
}
void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
const struct wpa_bss *bss);
void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *res,
struct os_reltime *fetch_time);
void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
const char *reason);
void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
int new_scan);
int wpa_bss_init(struct wpa_supplicant *wpa_s);
void wpa_bss_deinit(struct wpa_supplicant *wpa_s);
void wpa_bss_flush(struct wpa_supplicant *wpa_s);
void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age);
struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
const u8 *ssid, size_t ssid_len);
struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
const u8 *bssid);
struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
const u8 *bssid);
struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
const u8 *dev_addr);
struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id);
struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
unsigned int idf, unsigned int idl);
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext);
const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
u32 vendor_type);
struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
u32 vendor_type);
struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
u32 vendor_type);
int wpa_bss_get_max_rate(const struct wpa_bss *bss);
int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates);
struct wpa_bss_anqp * wpa_bss_anqp_alloc(void);
int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss);
const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss);
int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab);
static inline int bss_is_dmg(const struct wpa_bss *bss)
{
return bss->freq > 45000;
}
/**
* Test whether a BSS is a PBSS.
* This checks whether a BSS is a DMG-band PBSS. PBSS is used for P2P DMG
* network.
*/
static inline int bss_is_pbss(struct wpa_bss *bss)
{
return bss_is_dmg(bss) &&
(bss->caps & IEEE80211_CAP_DMG_MASK) == IEEE80211_CAP_DMG_PBSS;
}
static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
{
if (bss != NULL && new_level > -WPA_INVALID_NOISE && new_level < 0)
bss->level = new_level;
}
void calculate_update_time(const struct os_reltime *fetch_time,
unsigned int age_ms,
struct os_reltime *update_time);
#endif /* BSS_H */

View File

@ -0,0 +1,221 @@
/*
* wpa_supplicant - List of temporarily ignored BSSIDs
* Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "wpa_supplicant_i.h"
#include "bssid_ignore.h"
/**
* wpa_bssid_ignore_get - Get the ignore list entry for a BSSID
* @wpa_s: Pointer to wpa_supplicant data
* @bssid: BSSID
* Returns: Matching entry for the BSSID or %NULL if not found
*/
struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
const u8 *bssid)
{
struct wpa_bssid_ignore *e;
if (wpa_s == NULL || bssid == NULL)
return NULL;
if (wpa_s->current_ssid &&
wpa_s->current_ssid->was_recently_reconfigured) {
wpa_bssid_ignore_clear(wpa_s);
wpa_s->current_ssid->was_recently_reconfigured = false;
return NULL;
}
wpa_bssid_ignore_update(wpa_s);
e = wpa_s->bssid_ignore;
while (e) {
if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
return e;
e = e->next;
}
return NULL;
}
/**
* wpa_bssid_ignore_add - Add an BSSID to the ignore list
* @wpa_s: Pointer to wpa_supplicant data
* @bssid: BSSID to be added to the ignore list
* Returns: Current ignore list count on success, -1 on failure
*
* This function adds the specified BSSID to the ignore list or increases the
* ignore count if the BSSID was already listed. It should be called when
* an association attempt fails either due to the selected BSS rejecting
* association or due to timeout.
*
* This ignore list is used to force %wpa_supplicant to go through all available
* BSSes before retrying to associate with an BSS that rejected or timed out
* association. It does not prevent the listed BSS from being used; it only
* changes the order in which they are tried.
*/
int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
struct wpa_bssid_ignore *e;
struct os_reltime now;
if (wpa_s == NULL || bssid == NULL)
return -1;
e = wpa_bssid_ignore_get(wpa_s, bssid);
os_get_reltime(&now);
if (e) {
e->start = now;
e->count++;
if (e->count > 5)
e->timeout_secs = 1800;
else if (e->count == 5)
e->timeout_secs = 600;
else if (e->count == 4)
e->timeout_secs = 120;
else if (e->count == 3)
e->timeout_secs = 60;
else
e->timeout_secs = 10;
wpa_printf(MSG_INFO, "BSSID " MACSTR
" ignore list count incremented to %d, ignoring for %d seconds",
MAC2STR(bssid), e->count, e->timeout_secs);
return e->count;
}
e = os_zalloc(sizeof(*e));
if (e == NULL)
return -1;
os_memcpy(e->bssid, bssid, ETH_ALEN);
e->count = 1;
e->timeout_secs = 10;
e->start = now;
e->next = wpa_s->bssid_ignore;
wpa_s->bssid_ignore = e;
wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
" into ignore list, ignoring for %d seconds",
MAC2STR(bssid), e->timeout_secs);
return e->count;
}
/**
* wpa_bssid_ignore_del - Remove an BSSID from the ignore list
* @wpa_s: Pointer to wpa_supplicant data
* @bssid: BSSID to be removed from the ignore list
* Returns: 0 on success, -1 on failure
*/
int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
struct wpa_bssid_ignore *e, *prev = NULL;
if (wpa_s == NULL || bssid == NULL)
return -1;
e = wpa_s->bssid_ignore;
while (e) {
if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
if (prev == NULL) {
wpa_s->bssid_ignore = e->next;
} else {
prev->next = e->next;
}
wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
" from ignore list", MAC2STR(bssid));
os_free(e);
return 0;
}
prev = e;
e = e->next;
}
return -1;
}
/**
* wpa_bssid_ignore_is_listed - Check whether a BSSID is ignored temporarily
* @wpa_s: Pointer to wpa_supplicant data
* @bssid: BSSID to be checked
* Returns: count if BSS is currently considered to be ignored, 0 otherwise
*/
int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
struct wpa_bssid_ignore *e;
struct os_reltime now;
e = wpa_bssid_ignore_get(wpa_s, bssid);
if (!e)
return 0;
os_get_reltime(&now);
if (os_reltime_expired(&now, &e->start, e->timeout_secs))
return 0;
return e->count;
}
/**
* wpa_bssid_ignore_clear - Clear the ignore list of all entries
* @wpa_s: Pointer to wpa_supplicant data
*/
void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s)
{
struct wpa_bssid_ignore *e, *prev;
e = wpa_s->bssid_ignore;
wpa_s->bssid_ignore = NULL;
while (e) {
prev = e;
e = e->next;
wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
" from ignore list (clear)", MAC2STR(prev->bssid));
os_free(prev);
}
}
/**
* wpa_bssid_ignore_update - Update the entries in the ignore list,
* deleting entries that have been expired for over an hour.
* @wpa_s: Pointer to wpa_supplicant data
*/
void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s)
{
struct wpa_bssid_ignore *e, *prev = NULL;
struct os_reltime now;
if (!wpa_s)
return;
e = wpa_s->bssid_ignore;
os_get_reltime(&now);
while (e) {
if (os_reltime_expired(&now, &e->start,
e->timeout_secs + 3600)) {
struct wpa_bssid_ignore *to_delete = e;
if (prev) {
prev->next = e->next;
e = prev->next;
} else {
wpa_s->bssid_ignore = e->next;
e = wpa_s->bssid_ignore;
}
wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
" from ignore list (expired)",
MAC2STR(to_delete->bssid));
os_free(to_delete);
} else {
prev = e;
e = e->next;
}
}
}

View File

@ -0,0 +1,33 @@
/*
* wpa_supplicant - List of temporarily ignored BSSIDs
* Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef BSSID_IGNORE_H
#define BSSID_IGNORE_H
struct wpa_bssid_ignore {
struct wpa_bssid_ignore *next;
u8 bssid[ETH_ALEN];
int count;
/* Time of the most recent trigger to ignore this BSSID. */
struct os_reltime start;
/*
* Number of seconds after start that the entey will be considered
* valid.
*/
int timeout_secs;
};
struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
const u8 *bssid);
int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid);
int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid);
int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid);
void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s);
void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s);
#endif /* BSSID_IGNORE_H */

5429
wpa_supplicant/config.c Normal file

File diff suppressed because it is too large Load Diff

1797
wpa_supplicant/config.h Normal file

File diff suppressed because it is too large Load Diff

1656
wpa_supplicant/config_file.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
/*
* WPA Supplicant / Configuration backend: empty starting point
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*
* This file implements stub example of a configuration backend. None of the
* functions are actually implemented so this can be used as a simple
* compilation test or a starting point for a new configuration backend.
*/
#include "includes.h"
#include "common.h"
#include "config.h"
#include "base64.h"
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
{
struct wpa_config *config;
if (name == NULL)
return NULL;
if (cfgp)
config = cfgp;
else
config = wpa_config_alloc_empty(NULL, NULL);
if (config == NULL)
return NULL;
/* TODO: fill in configuration data */
return config;
}
int wpa_config_write(const char *name, struct wpa_config *config)
{
struct wpa_ssid *ssid;
struct wpa_config_blob *blob;
wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
/* TODO: write global config parameters */
for (ssid = config->ssid; ssid; ssid = ssid->next) {
/* TODO: write networks */
}
for (blob = config->blobs; blob; blob = blob->next) {
/* TODO: write blobs */
}
return 0;
}

1182
wpa_supplicant/config_ssid.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

13103
wpa_supplicant/ctrl_iface.c Normal file

File diff suppressed because it is too large Load Diff

167
wpa_supplicant/ctrl_iface.h Normal file
View File

@ -0,0 +1,167 @@
/*
* WPA Supplicant / UNIX domain socket -based control interface
* Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef CTRL_IFACE_H
#define CTRL_IFACE_H
#ifdef CONFIG_CTRL_IFACE
#ifndef CTRL_IFACE_MAX_LEN
#define CTRL_IFACE_MAX_LEN 8192
#endif /* CTRL_IFACE_MAX_LEN */
/* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */
/**
* wpa_supplicant_ctrl_iface_process - Process ctrl_iface command
* @wpa_s: Pointer to wpa_supplicant data
* @buf: Received command buffer (nul terminated string)
* @resp_len: Variable to be set to the response length
* Returns: Response (*resp_len bytes) or %NULL on failure
*
* Control interface backends call this function when receiving a message that
* they do not process internally, i.e., anything else than ATTACH, DETACH,
* and LEVEL. The return response value is then sent to the external program
* that sent the command. Caller is responsible for freeing the buffer after
* this. If %NULL is returned, *resp_len can be set to two special values:
* 1 = send "FAIL\n" response, 2 = send "OK\n" response. If *resp_len has any
* other value, no response is sent.
*/
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
char *buf, size_t *resp_len);
/**
* wpa_supplicant_global_ctrl_iface_process - Process global ctrl_iface command
* @global: Pointer to global data from wpa_supplicant_init()
* @buf: Received command buffer (nul terminated string)
* @resp_len: Variable to be set to the response length
* Returns: Response (*resp_len bytes) or %NULL on failure
*
* Control interface backends call this function when receiving a message from
* the global ctrl_iface connection. The return response value is then sent to
* the external program that sent the command. Caller is responsible for
* freeing the buffer after this. If %NULL is returned, *resp_len can be set to
* two special values: 1 = send "FAIL\n" response, 2 = send "OK\n" response. If
* *resp_len has any other value, no response is sent.
*/
char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
char *buf, size_t *resp_len);
/* Functions that each ctrl_iface backend must implement */
/**
* wpa_supplicant_ctrl_iface_init - Initialize control interface
* @wpa_s: Pointer to wpa_supplicant data
* Returns: Pointer to private data on success, %NULL on failure
*
* Initialize the control interface and start receiving commands from external
* programs.
*
* Required to be implemented in each control interface backend.
*/
struct ctrl_iface_priv *
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
/**
* wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
* @wpa_s: Pointer to wpa_supplicant data
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
*
* Deinitialize the control interface that was initialized with
* wpa_supplicant_ctrl_iface_init() and any data related to the wpa_s instance.
* @priv may be %NULL if the control interface has not yet been initialized.
*
* Required to be implemented in each control interface backend.
*/
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv);
/**
* wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
*
* Wait until the first message from an external program using the control
* interface is received. This function can be used to delay normal startup
* processing to allow control interface programs to attach with
* %wpa_supplicant before normal operations are started.
*
* Required to be implemented in each control interface backend.
*/
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv);
/**
* wpa_supplicant_global_ctrl_iface_init - Initialize global control interface
* @global: Pointer to global data from wpa_supplicant_init()
* Returns: Pointer to private data on success, %NULL on failure
*
* Initialize the global control interface and start receiving commands from
* external programs.
*
* Required to be implemented in each control interface backend.
*/
struct ctrl_iface_global_priv *
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global);
/**
* wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface
* @priv: Pointer to private data from wpa_supplicant_global_ctrl_iface_init()
*
* Deinitialize the global control interface that was initialized with
* wpa_supplicant_global_ctrl_iface_init().
*
* Required to be implemented in each control interface backend.
*/
void wpa_supplicant_global_ctrl_iface_deinit(
struct ctrl_iface_global_priv *priv);
void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s);
#else /* CONFIG_CTRL_IFACE */
static inline struct ctrl_iface_priv *
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
{
return (void *) -1;
}
static inline void
wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv)
{
}
static inline void
wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, int level,
char *buf, size_t len)
{
}
static inline void
wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
{
}
static inline struct ctrl_iface_global_priv *
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
{
return (void *) 1;
}
static inline void
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
{
}
static inline void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
{
}
#endif /* CONFIG_CTRL_IFACE */
#endif /* CTRL_IFACE_H */

View File

@ -0,0 +1,831 @@
/*
* WPA Supplicant / Windows Named Pipe -based control interface
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "eloop.h"
#include "config.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "wpa_supplicant_i.h"
#include "ctrl_iface.h"
#include "common/wpa_ctrl.h"
#ifdef __MINGW32_VERSION
/* mingw-w32api v3.1 does not yet include sddl.h, so define needed parts here
*/
#define SDDL_REVISION_1 1
BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
LPCSTR, DWORD, PSECURITY_DESCRIPTOR *, PULONG);
BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
LPCWSTR, DWORD, PSECURITY_DESCRIPTOR *, PULONG);
#ifdef UNICODE
#define ConvertStringSecurityDescriptorToSecurityDescriptor \
ConvertStringSecurityDescriptorToSecurityDescriptorW
#else
#define ConvertStringSecurityDescriptorToSecurityDescriptor \
ConvertStringSecurityDescriptorToSecurityDescriptorA
#endif
#else /* __MINGW32_VERSION */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif
#include <sddl.h>
#endif /* __MINGW32_VERSION */
#ifndef WPA_SUPPLICANT_NAMED_PIPE
#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
#endif
#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
/* Per-interface ctrl_iface */
#define REQUEST_BUFSIZE CTRL_IFACE_MAX_LEN
#define REPLY_BUFSIZE 4096
struct ctrl_iface_priv;
/**
* struct wpa_ctrl_dst - Internal data structure of control interface clients
*
* This structure is used to store information about registered control
* interface monitors into struct wpa_supplicant. This data is private to
* ctrl_iface_named_pipe.c and should not be touched directly from other files.
*/
struct wpa_ctrl_dst {
/* Note: OVERLAPPED must be the first member of struct wpa_ctrl_dst */
OVERLAPPED overlap;
struct wpa_ctrl_dst *next, *prev;
struct ctrl_iface_priv *priv;
HANDLE pipe;
int attached;
int debug_level;
int errors;
char req_buf[REQUEST_BUFSIZE];
char *rsp_buf;
int used;
};
struct ctrl_iface_priv {
struct wpa_supplicant *wpa_s;
struct wpa_ctrl_dst *ctrl_dst;
SECURITY_ATTRIBUTES attr;
int sec_attr_set;
};
static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
int level, const char *buf,
size_t len);
static void ctrl_close_pipe(struct wpa_ctrl_dst *dst);
static void wpa_supplicant_ctrl_iface_receive(void *, void *);
static VOID WINAPI ctrl_iface_read_completed(DWORD err, DWORD bytes,
LPOVERLAPPED overlap);
struct wpa_global_dst;
static void global_close_pipe(struct wpa_global_dst *dst);
static void wpa_supplicant_global_iface_receive(void *eloop_data,
void *user_ctx);
static VOID WINAPI global_iface_read_completed(DWORD err, DWORD bytes,
LPOVERLAPPED overlap);
static int ctrl_broken_pipe(HANDLE pipe, int used)
{
DWORD err;
if (PeekNamedPipe(pipe, NULL, 0, NULL, NULL, NULL))
return 0;
err = GetLastError();
if (err == ERROR_BROKEN_PIPE || (err == ERROR_BAD_PIPE && used))
return 1;
return 0;
}
static void ctrl_flush_broken_pipes(struct ctrl_iface_priv *priv)
{
struct wpa_ctrl_dst *dst, *next;
dst = priv->ctrl_dst;
while (dst) {
next = dst->next;
if (ctrl_broken_pipe(dst->pipe, dst->used)) {
wpa_printf(MSG_DEBUG, "CTRL: closing broken pipe %p",
dst);
ctrl_close_pipe(dst);
}
dst = next;
}
}
static int ctrl_open_pipe(struct ctrl_iface_priv *priv)
{
struct wpa_ctrl_dst *dst;
DWORD err;
TCHAR name[256];
dst = os_zalloc(sizeof(*dst));
if (dst == NULL)
return -1;
wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst);
dst->priv = priv;
dst->debug_level = MSG_INFO;
dst->pipe = INVALID_HANDLE_VALUE;
dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (dst->overlap.hEvent == NULL) {
wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d",
(int) GetLastError());
goto fail;
}
eloop_register_event(dst->overlap.hEvent,
sizeof(dst->overlap.hEvent),
wpa_supplicant_ctrl_iface_receive, dst, NULL);
#ifdef UNICODE
_snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
priv->wpa_s->ifname);
#else /* UNICODE */
os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
priv->wpa_s->ifname);
#endif /* UNICODE */
/* TODO: add support for configuring access list for the pipe */
dst->pipe = CreateNamedPipe(name,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT,
15, REPLY_BUFSIZE, REQUEST_BUFSIZE,
1000,
priv->sec_attr_set ? &priv->attr : NULL);
if (dst->pipe == INVALID_HANDLE_VALUE) {
wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d",
(int) GetLastError());
goto fail;
}
if (ConnectNamedPipe(dst->pipe, &dst->overlap)) {
wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d",
(int) GetLastError());
CloseHandle(dst->pipe);
os_free(dst);
return -1;
}
err = GetLastError();
switch (err) {
case ERROR_IO_PENDING:
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in "
"progress");
break;
case ERROR_PIPE_CONNECTED:
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already "
"connected");
if (SetEvent(dst->overlap.hEvent))
break;
/* fall through */
default:
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d",
(int) err);
CloseHandle(dst->pipe);
os_free(dst);
return -1;
}
dst->next = priv->ctrl_dst;
if (dst->next)
dst->next->prev = dst;
priv->ctrl_dst = dst;
return 0;
fail:
ctrl_close_pipe(dst);
return -1;
}
static void ctrl_close_pipe(struct wpa_ctrl_dst *dst)
{
wpa_printf(MSG_DEBUG, "CTRL: close pipe %p", dst);
if (dst->overlap.hEvent) {
eloop_unregister_event(dst->overlap.hEvent,
sizeof(dst->overlap.hEvent));
CloseHandle(dst->overlap.hEvent);
}
if (dst->pipe != INVALID_HANDLE_VALUE) {
/*
* Could use FlushFileBuffers() here to guarantee that all data
* gets delivered to the client, but that can block, so let's
* not do this for now.
* FlushFileBuffers(dst->pipe);
*/
CloseHandle(dst->pipe);
}
if (dst->prev)
dst->prev->next = dst->next;
else
dst->priv->ctrl_dst = dst->next;
if (dst->next)
dst->next->prev = dst->prev;
os_free(dst->rsp_buf);
os_free(dst);
}
static VOID WINAPI ctrl_iface_write_completed(DWORD err, DWORD bytes,
LPOVERLAPPED overlap)
{
struct wpa_ctrl_dst *dst = (struct wpa_ctrl_dst *) overlap;
wpa_printf(MSG_DEBUG, "CTRL: Overlapped write completed: dst=%p "
"err=%d bytes=%d", dst, (int) err, (int) bytes);
if (err) {
ctrl_close_pipe(dst);
return;
}
os_free(dst->rsp_buf);
dst->rsp_buf = NULL;
if (!ReadFileEx(dst->pipe, dst->req_buf, sizeof(dst->req_buf),
&dst->overlap, ctrl_iface_read_completed)) {
wpa_printf(MSG_DEBUG, "CTRL: ReadFileEx failed: %d",
(int) GetLastError());
ctrl_close_pipe(dst);
return;
}
wpa_printf(MSG_DEBUG, "CTRL: Overlapped read started for %p", dst);
}
static void wpa_supplicant_ctrl_iface_rx(struct wpa_ctrl_dst *dst, size_t len)
{
struct wpa_supplicant *wpa_s = dst->priv->wpa_s;
char *reply = NULL, *send_buf;
size_t reply_len = 0, send_len;
int new_attached = 0;
char *buf = dst->req_buf;
dst->used = 1;
if (len >= REQUEST_BUFSIZE)
len = REQUEST_BUFSIZE - 1;
buf[len] = '\0';
if (os_strcmp(buf, "ATTACH") == 0) {
dst->attached = 1;
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached");
new_attached = 1;
reply_len = 2;
} else if (os_strcmp(buf, "DETACH") == 0) {
dst->attached = 0;
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached");
reply_len = 2;
} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", buf + 6);
dst->debug_level = atoi(buf + 6);
reply_len = 2;
} else {
reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
&reply_len);
}
if (reply) {
send_buf = reply;
send_len = reply_len;
} else if (reply_len == 2) {
send_buf = "OK\n";
send_len = 3;
} else {
send_buf = "FAIL\n";
send_len = 5;
}
os_free(dst->rsp_buf);
dst->rsp_buf = os_memdup(send_buf, send_len);
if (dst->rsp_buf == NULL) {
ctrl_close_pipe(dst);
os_free(reply);
return;
}
os_free(reply);
if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap,
ctrl_iface_write_completed)) {
wpa_printf(MSG_DEBUG, "CTRL: WriteFileEx failed: %d",
(int) GetLastError());
ctrl_close_pipe(dst);
} else {
wpa_printf(MSG_DEBUG, "CTRL: Overlapped write started for %p",
dst);
}
if (new_attached)
eapol_sm_notify_ctrl_attached(wpa_s->eapol);
}
static VOID WINAPI ctrl_iface_read_completed(DWORD err, DWORD bytes,
LPOVERLAPPED overlap)
{
struct wpa_ctrl_dst *dst = (struct wpa_ctrl_dst *) overlap;
wpa_printf(MSG_DEBUG, "CTRL: Overlapped read completed: dst=%p err=%d "
"bytes=%d", dst, (int) err, (int) bytes);
if (err == 0 && bytes > 0)
wpa_supplicant_ctrl_iface_rx(dst, bytes);
}
static void wpa_supplicant_ctrl_iface_receive(void *eloop_data, void *user_ctx)
{
struct wpa_ctrl_dst *dst = eloop_data;
struct ctrl_iface_priv *priv = dst->priv;
DWORD bytes;
wpa_printf(MSG_DEBUG, "CTRL: wpa_supplicant_ctrl_iface_receive");
ResetEvent(dst->overlap.hEvent);
if (!GetOverlappedResult(dst->pipe, &dst->overlap, &bytes, FALSE)) {
wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult failed: %d",
(int) GetLastError());
return;
}
wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult: New client "
"connected");
/* Open a new named pipe for the next client. */
ctrl_open_pipe(priv);
/* Use write completion function to start reading a command */
ctrl_iface_write_completed(0, 0, &dst->overlap);
ctrl_flush_broken_pipes(priv);
}
static int ctrl_iface_parse(struct ctrl_iface_priv *priv, const char *params)
{
const char *sddl = NULL;
TCHAR *t_sddl;
if (os_strncmp(params, "SDDL=", 5) == 0)
sddl = params + 5;
if (!sddl) {
sddl = os_strstr(params, " SDDL=");
if (sddl)
sddl += 6;
}
if (!sddl)
return 0;
wpa_printf(MSG_DEBUG, "CTRL: SDDL='%s'", sddl);
os_memset(&priv->attr, 0, sizeof(priv->attr));
priv->attr.nLength = sizeof(priv->attr);
priv->attr.bInheritHandle = FALSE;
t_sddl = wpa_strdup_tchar(sddl);
if (t_sddl == NULL)
return -1;
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
t_sddl, SDDL_REVISION_1,
(PSECURITY_DESCRIPTOR *) (void *)
&priv->attr.lpSecurityDescriptor,
NULL)) {
os_free(t_sddl);
wpa_printf(MSG_ERROR, "CTRL: SDDL='%s' - could not convert to "
"security descriptor: %d",
sddl, (int) GetLastError());
return -1;
}
os_free(t_sddl);
priv->sec_attr_set = 1;
return 0;
}
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
enum wpa_msg_type type,
const char *txt, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
return;
wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
}
struct ctrl_iface_priv *
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
priv->wpa_s = wpa_s;
if (wpa_s->conf->ctrl_interface == NULL)
return priv;
if (ctrl_iface_parse(priv, wpa_s->conf->ctrl_interface) < 0) {
os_free(priv);
return NULL;
}
if (ctrl_open_pipe(priv) < 0) {
os_free(priv);
return NULL;
}
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
return priv;
}
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv)
{
if (!priv)
return;
while (priv->ctrl_dst)
ctrl_close_pipe(priv->ctrl_dst);
if (priv->sec_attr_set)
LocalFree(priv->attr.lpSecurityDescriptor);
os_free(priv);
}
static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
int level, const char *buf,
size_t len)
{
struct wpa_ctrl_dst *dst, *next;
char levelstr[10];
int idx;
char *sbuf;
int llen;
DWORD written;
dst = priv->ctrl_dst;
if (dst == NULL)
return;
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
llen = os_strlen(levelstr);
sbuf = os_malloc(llen + len);
if (sbuf == NULL)
return;
os_memcpy(sbuf, levelstr, llen);
os_memcpy(sbuf + llen, buf, len);
idx = 0;
while (dst) {
next = dst->next;
if (dst->attached && level >= dst->debug_level) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %p",
dst);
if (!WriteFile(dst->pipe, sbuf, llen + len, &written,
NULL)) {
wpa_printf(MSG_DEBUG, "CTRL: WriteFile to dst "
"%p failed: %d",
dst, (int) GetLastError());
dst->errors++;
if (dst->errors > 10)
ctrl_close_pipe(dst);
} else
dst->errors = 0;
}
idx++;
dst = next;
}
os_free(sbuf);
}
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
{
wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
priv->wpa_s->ifname);
if (priv->ctrl_dst == NULL)
return;
WaitForSingleObject(priv->ctrl_dst->pipe, INFINITE);
}
/* Global ctrl_iface */
struct ctrl_iface_global_priv;
struct wpa_global_dst {
/* Note: OVERLAPPED must be the first member of struct wpa_global_dst
*/
OVERLAPPED overlap;
struct wpa_global_dst *next, *prev;
struct ctrl_iface_global_priv *priv;
HANDLE pipe;
char req_buf[REQUEST_BUFSIZE];
char *rsp_buf;
int used;
};
struct ctrl_iface_global_priv {
struct wpa_global *global;
struct wpa_global_dst *ctrl_dst;
};
static void global_flush_broken_pipes(struct ctrl_iface_global_priv *priv)
{
struct wpa_global_dst *dst, *next;
dst = priv->ctrl_dst;
while (dst) {
next = dst->next;
if (ctrl_broken_pipe(dst->pipe, dst->used)) {
wpa_printf(MSG_DEBUG, "CTRL: closing broken pipe %p",
dst);
global_close_pipe(dst);
}
dst = next;
}
}
static int global_open_pipe(struct ctrl_iface_global_priv *priv)
{
struct wpa_global_dst *dst;
DWORD err;
dst = os_zalloc(sizeof(*dst));
if (dst == NULL)
return -1;
wpa_printf(MSG_DEBUG, "CTRL: Open pipe %p", dst);
dst->priv = priv;
dst->pipe = INVALID_HANDLE_VALUE;
dst->overlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (dst->overlap.hEvent == NULL) {
wpa_printf(MSG_ERROR, "CTRL: CreateEvent failed: %d",
(int) GetLastError());
goto fail;
}
eloop_register_event(dst->overlap.hEvent,
sizeof(dst->overlap.hEvent),
wpa_supplicant_global_iface_receive, dst, NULL);
/* TODO: add support for configuring access list for the pipe */
dst->pipe = CreateNamedPipe(NAMED_PIPE_PREFIX,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE |
PIPE_READMODE_MESSAGE |
PIPE_WAIT,
10, REPLY_BUFSIZE, REQUEST_BUFSIZE,
1000, NULL);
if (dst->pipe == INVALID_HANDLE_VALUE) {
wpa_printf(MSG_ERROR, "CTRL: CreateNamedPipe failed: %d",
(int) GetLastError());
goto fail;
}
if (ConnectNamedPipe(dst->pipe, &dst->overlap)) {
wpa_printf(MSG_ERROR, "CTRL: ConnectNamedPipe failed: %d",
(int) GetLastError());
CloseHandle(dst->pipe);
os_free(dst);
return -1;
}
err = GetLastError();
switch (err) {
case ERROR_IO_PENDING:
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: connection in "
"progress");
break;
case ERROR_PIPE_CONNECTED:
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe: already "
"connected");
if (SetEvent(dst->overlap.hEvent))
break;
/* fall through */
default:
wpa_printf(MSG_DEBUG, "CTRL: ConnectNamedPipe error: %d",
(int) err);
CloseHandle(dst->pipe);
os_free(dst);
return -1;
}
dst->next = priv->ctrl_dst;
if (dst->next)
dst->next->prev = dst;
priv->ctrl_dst = dst;
return 0;
fail:
global_close_pipe(dst);
return -1;
}
static void global_close_pipe(struct wpa_global_dst *dst)
{
wpa_printf(MSG_DEBUG, "CTRL: close pipe %p", dst);
if (dst->overlap.hEvent) {
eloop_unregister_event(dst->overlap.hEvent,
sizeof(dst->overlap.hEvent));
CloseHandle(dst->overlap.hEvent);
}
if (dst->pipe != INVALID_HANDLE_VALUE) {
/*
* Could use FlushFileBuffers() here to guarantee that all data
* gets delivered to the client, but that can block, so let's
* not do this for now.
* FlushFileBuffers(dst->pipe);
*/
CloseHandle(dst->pipe);
}
if (dst->prev)
dst->prev->next = dst->next;
else
dst->priv->ctrl_dst = dst->next;
if (dst->next)
dst->next->prev = dst->prev;
os_free(dst->rsp_buf);
os_free(dst);
}
static VOID WINAPI global_iface_write_completed(DWORD err, DWORD bytes,
LPOVERLAPPED overlap)
{
struct wpa_global_dst *dst = (struct wpa_global_dst *) overlap;
wpa_printf(MSG_DEBUG, "CTRL: Overlapped write completed: dst=%p "
"err=%d bytes=%d", dst, (int) err, (int) bytes);
if (err) {
global_close_pipe(dst);
return;
}
os_free(dst->rsp_buf);
dst->rsp_buf = NULL;
if (!ReadFileEx(dst->pipe, dst->req_buf, sizeof(dst->req_buf),
&dst->overlap, global_iface_read_completed)) {
wpa_printf(MSG_DEBUG, "CTRL: ReadFileEx failed: %d",
(int) GetLastError());
global_close_pipe(dst);
/* FIX: if this was the pipe waiting for new global
* connections, at this point there are no open global pipes..
* Should try to open a new pipe.. */
return;
}
wpa_printf(MSG_DEBUG, "CTRL: Overlapped read started for %p", dst);
}
static void wpa_supplicant_global_iface_rx(struct wpa_global_dst *dst,
size_t len)
{
struct wpa_global *global = dst->priv->global;
char *reply = NULL, *send_buf;
size_t reply_len = 0, send_len;
char *buf = dst->req_buf;
dst->used = 1;
if (len >= REQUEST_BUFSIZE)
len = REQUEST_BUFSIZE - 1;
buf[len] = '\0';
reply = wpa_supplicant_global_ctrl_iface_process(global, buf,
&reply_len);
if (reply) {
send_buf = reply;
send_len = reply_len;
} else if (reply_len) {
send_buf = "FAIL\n";
send_len = 5;
} else {
os_free(dst->rsp_buf);
dst->rsp_buf = NULL;
return;
}
os_free(dst->rsp_buf);
dst->rsp_buf = os_memdup(send_buf, send_len);
if (dst->rsp_buf == NULL) {
global_close_pipe(dst);
os_free(reply);
return;
}
os_free(reply);
if (!WriteFileEx(dst->pipe, dst->rsp_buf, send_len, &dst->overlap,
global_iface_write_completed)) {
wpa_printf(MSG_DEBUG, "CTRL: WriteFileEx failed: %d",
(int) GetLastError());
global_close_pipe(dst);
} else {
wpa_printf(MSG_DEBUG, "CTRL: Overlapped write started for %p",
dst);
}
}
static VOID WINAPI global_iface_read_completed(DWORD err, DWORD bytes,
LPOVERLAPPED overlap)
{
struct wpa_global_dst *dst = (struct wpa_global_dst *) overlap;
wpa_printf(MSG_DEBUG, "CTRL: Overlapped read completed: dst=%p err=%d "
"bytes=%d", dst, (int) err, (int) bytes);
if (err == 0 && bytes > 0)
wpa_supplicant_global_iface_rx(dst, bytes);
}
static void wpa_supplicant_global_iface_receive(void *eloop_data,
void *user_ctx)
{
struct wpa_global_dst *dst = eloop_data;
struct ctrl_iface_global_priv *priv = dst->priv;
DWORD bytes;
wpa_printf(MSG_DEBUG, "CTRL: wpa_supplicant_global_iface_receive");
ResetEvent(dst->overlap.hEvent);
if (!GetOverlappedResult(dst->pipe, &dst->overlap, &bytes, FALSE)) {
wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult failed: %d",
(int) GetLastError());
return;
}
wpa_printf(MSG_DEBUG, "CTRL: GetOverlappedResult: New client "
"connected");
/* Open a new named pipe for the next client. */
if (global_open_pipe(priv) < 0) {
wpa_printf(MSG_DEBUG, "CTRL: global_open_pipe failed");
return;
}
/* Use write completion function to start reading a command */
global_iface_write_completed(0, 0, &dst->overlap);
global_flush_broken_pipes(priv);
}
struct ctrl_iface_global_priv *
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
{
struct ctrl_iface_global_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
priv->global = global;
if (global_open_pipe(priv) < 0) {
os_free(priv);
return NULL;
}
return priv;
}
void
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
{
while (priv->ctrl_dst)
global_close_pipe(priv->ctrl_dst);
os_free(priv);
}

View File

@ -0,0 +1,831 @@
/*
* WPA Supplicant / UDP socket -based control interface
* Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "eloop.h"
#include "config.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "wpa_supplicant_i.h"
#include "ctrl_iface.h"
#include "common/wpa_ctrl.h"
#define COOKIE_LEN 8
/* Per-interface ctrl_iface */
/**
* struct wpa_ctrl_dst - Internal data structure of control interface monitors
*
* This structure is used to store information about registered control
* interface monitors into struct wpa_supplicant. This data is private to
* ctrl_iface_udp.c and should not be touched directly from other files.
*/
struct wpa_ctrl_dst {
struct wpa_ctrl_dst *next;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 addr;
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in addr;
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
socklen_t addrlen;
int debug_level;
int errors;
};
struct ctrl_iface_priv {
struct wpa_supplicant *wpa_s;
int sock;
struct wpa_ctrl_dst *ctrl_dst;
u8 cookie[COOKIE_LEN];
};
struct ctrl_iface_global_priv {
int sock;
struct wpa_ctrl_dst *ctrl_dst;
u8 cookie[COOKIE_LEN];
};
static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
const char *ifname, int sock,
struct wpa_ctrl_dst **head,
int level, const char *buf,
size_t len);
static void wpas_ctrl_iface_free_dst(struct wpa_ctrl_dst *dst)
{
struct wpa_ctrl_dst *prev;
while (dst) {
prev = dst;
dst = dst->next;
os_free(prev);
}
}
static int wpa_supplicant_ctrl_iface_attach(struct wpa_ctrl_dst **head,
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 *from,
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in *from,
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
socklen_t fromlen)
{
struct wpa_ctrl_dst *dst;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
char addr[INET6_ADDRSTRLEN];
#endif /* CONFIG_UDP_IPV6 */
dst = os_zalloc(sizeof(*dst));
if (dst == NULL)
return -1;
os_memcpy(&dst->addr, from, sizeof(*from));
dst->addrlen = fromlen;
dst->debug_level = MSG_INFO;
dst->next = *head;
*head = dst;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
inet_ntop(AF_INET6, &from->sin6_addr, addr, sizeof(*from)),
ntohs(from->sin6_port));
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
inet_ntoa(from->sin_addr), ntohs(from->sin_port));
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
return 0;
}
static int wpa_supplicant_ctrl_iface_detach(struct wpa_ctrl_dst **head,
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 *from,
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in *from,
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
socklen_t fromlen)
{
struct wpa_ctrl_dst *dst, *prev = NULL;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
char addr[INET6_ADDRSTRLEN];
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
dst = *head;
while (dst) {
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
if (from->sin6_port == dst->addr.sin6_port &&
!os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr,
sizeof(from->sin6_addr))) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s:%d",
inet_ntop(AF_INET6, &from->sin6_addr, addr,
sizeof(*from)),
ntohs(from->sin6_port));
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
from->sin_port == dst->addr.sin_port) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
"%s:%d", inet_ntoa(from->sin_addr),
ntohs(from->sin_port));
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (prev == NULL)
*head = dst->next;
else
prev->next = dst->next;
os_free(dst);
return 0;
}
prev = dst;
dst = dst->next;
}
return -1;
}
static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 *from,
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in *from,
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
socklen_t fromlen,
char *level)
{
struct wpa_ctrl_dst *dst;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
char addr[INET6_ADDRSTRLEN];
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
dst = priv->ctrl_dst;
while (dst) {
#if CONFIG_CTRL_IFACE_UDP_IPV6
if (from->sin6_port == dst->addr.sin6_port &&
!os_memcmp(&from->sin6_addr, &dst->addr.sin6_addr,
sizeof(from->sin6_addr))) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level %s:%d",
inet_ntop(AF_INET6, &from->sin6_addr, addr,
sizeof(*from)),
ntohs(from->sin6_port));
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
from->sin_port == dst->addr.sin_port) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
"level %s:%d", inet_ntoa(from->sin_addr),
ntohs(from->sin_port));
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
dst->debug_level = atoi(level);
return 0;
}
dst = dst->next;
}
return -1;
}
static char *
wpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv,
size_t *reply_len)
{
char *reply;
reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
if (reply == NULL) {
*reply_len = 1;
return NULL;
}
os_memcpy(reply, "COOKIE=", 7);
wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
priv->cookie, COOKIE_LEN);
*reply_len = 7 + 2 * COOKIE_LEN;
return reply;
}
static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct ctrl_iface_priv *priv = sock_ctx;
char *buf, *pos;
int res;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 from;
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
char addr[INET6_ADDRSTRLEN];
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in from;
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
socklen_t fromlen = sizeof(from);
char *reply = NULL;
size_t reply_len = 0;
int new_attached = 0;
u8 cookie[COOKIE_LEN];
buf = os_malloc(CTRL_IFACE_MAX_LEN + 1);
if (!buf)
return;
res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
strerror(errno));
os_free(buf);
return;
}
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from));
if (os_strcmp(addr, "::1")) {
wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s",
addr);
os_free(buf);
return;
}
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
/*
* The OS networking stack is expected to drop this kind of
* frames since the socket is bound to only localhost address.
* Just in case, drop the frame if it is coming from any other
* address.
*/
wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
"source %s", inet_ntoa(from.sin_addr));
os_free(buf);
return;
}
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
if ((size_t) res > CTRL_IFACE_MAX_LEN) {
wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated");
os_free(buf);
return;
}
buf[res] = '\0';
if (os_strcmp(buf, "GET_COOKIE") == 0) {
reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len);
goto done;
}
/*
* Require that the client includes a prefix with the 'cookie' value
* fetched with GET_COOKIE command. This is used to verify that the
* client has access to a bidirectional link over UDP in order to
* avoid attacks using forged localhost IP address even if the OS does
* not block such frames from remote destinations.
*/
if (os_strncmp(buf, "COOKIE=", 7) != 0) {
wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
"drop request");
os_free(buf);
return;
}
if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
"request - drop request");
os_free(buf);
return;
}
if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
"drop request");
os_free(buf);
return;
}
pos = buf + 7 + 2 * COOKIE_LEN;
while (*pos == ' ')
pos++;
if (os_strcmp(pos, "ATTACH") == 0) {
if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
&from, fromlen))
reply_len = 1;
else {
new_attached = 1;
reply_len = 2;
}
} else if (os_strcmp(pos, "DETACH") == 0) {
if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
&from, fromlen))
reply_len = 1;
else
reply_len = 2;
} else if (os_strncmp(pos, "LEVEL ", 6) == 0) {
if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
pos + 6))
reply_len = 1;
else
reply_len = 2;
} else {
reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos,
&reply_len);
}
done:
if (reply) {
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen);
os_free(reply);
} else if (reply_len == 1) {
sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
fromlen);
} else if (reply_len == 2) {
sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
fromlen);
}
os_free(buf);
if (new_attached)
eapol_sm_notify_ctrl_attached(wpa_s->eapol);
}
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
enum wpa_msg_type type,
const char *txt, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
if (!wpa_s)
return;
if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) {
struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
if (priv->ctrl_dst) {
wpa_supplicant_ctrl_iface_send(
wpa_s,
type != WPA_MSG_PER_INTERFACE ?
NULL : wpa_s->ifname,
priv->sock, &priv->ctrl_dst, level, txt, len);
}
}
if (type == WPA_MSG_ONLY_GLOBAL || !wpa_s->ctrl_iface)
return;
wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
&wpa_s->ctrl_iface->ctrl_dst,
level, txt, len);
}
struct ctrl_iface_priv *
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_priv *priv;
char port_str[40];
int port = WPA_CTRL_IFACE_PORT;
char *pos;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 addr;
int domain = PF_INET6;
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in addr;
int domain = PF_INET;
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
priv->wpa_s = wpa_s;
priv->sock = -1;
os_get_random(priv->cookie, COOKIE_LEN);
if (wpa_s->conf->ctrl_interface == NULL)
return priv;
pos = os_strstr(wpa_s->conf->ctrl_interface, "udp:");
if (pos) {
pos += 4;
port = atoi(pos);
if (port <= 0) {
wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port: %s",
wpa_s->conf->ctrl_interface);
goto fail;
}
}
priv->sock = socket(domain, SOCK_DGRAM, 0);
if (priv->sock < 0) {
wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
goto fail;
}
os_memset(&addr, 0, sizeof(addr));
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
addr.sin6_family = AF_INET6;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
addr.sin6_addr = in6addr_any;
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
inet_pton(AF_INET6, "::1", &addr.sin6_addr);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
addr.sin_family = AF_INET;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
addr.sin_addr.s_addr = INADDR_ANY;
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
addr.sin_addr.s_addr = htonl((127 << 24) | 1);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
try_again:
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
addr.sin6_port = htons(port);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
addr.sin_port = htons(port);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
port--;
if ((WPA_CTRL_IFACE_PORT - port) < WPA_CTRL_IFACE_PORT_LIMIT)
goto try_again;
wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
goto fail;
}
/* Update the ctrl_interface value to match the selected port */
os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
os_free(wpa_s->conf->ctrl_interface);
wpa_s->conf->ctrl_interface = os_strdup(port_str);
if (!wpa_s->conf->ctrl_interface) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to malloc ctrl_interface");
goto fail;
}
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
wpa_msg(wpa_s, MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
wpa_s, priv);
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
return priv;
fail:
if (priv->sock >= 0)
close(priv->sock);
os_free(priv);
return NULL;
}
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv)
{
if (!priv)
return;
if (priv->sock > -1) {
eloop_unregister_read_sock(priv->sock);
if (priv->ctrl_dst) {
/*
* Wait before closing the control socket if
* there are any attached monitors in order to allow
* them to receive any pending messages.
*/
wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
"monitors to receive messages");
os_sleep(0, 100000);
}
close(priv->sock);
priv->sock = -1;
}
wpas_ctrl_iface_free_dst(priv->ctrl_dst);
os_free(priv);
}
static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
const char *ifname, int sock,
struct wpa_ctrl_dst **head,
int level, const char *buf,
size_t len)
{
struct wpa_ctrl_dst *dst, *next;
char levelstr[64];
int idx;
char *sbuf;
int llen;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
char addr[INET6_ADDRSTRLEN];
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
dst = *head;
if (sock < 0 || dst == NULL)
return;
if (ifname)
os_snprintf(levelstr, sizeof(levelstr), "IFNAME=%s <%d>",
ifname, level);
else
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
llen = os_strlen(levelstr);
sbuf = os_malloc(llen + len);
if (sbuf == NULL)
return;
os_memcpy(sbuf, levelstr, llen);
os_memcpy(sbuf + llen, buf, len);
idx = 0;
while (dst) {
next = dst->next;
if (level >= dst->debug_level) {
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
inet_ntop(AF_INET6, &dst->addr.sin6_addr,
addr, sizeof(dst->addr)),
ntohs(dst->addr.sin6_port));
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
inet_ntoa(dst->addr.sin_addr),
ntohs(dst->addr.sin_port));
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (sendto(sock, sbuf, llen + len, 0,
(struct sockaddr *) &dst->addr,
sizeof(dst->addr)) < 0) {
wpa_printf(MSG_ERROR,
"sendto(CTRL_IFACE monitor): %s",
strerror(errno));
dst->errors++;
if (dst->errors > 10) {
wpa_supplicant_ctrl_iface_detach(
head, &dst->addr,
dst->addrlen);
}
} else
dst->errors = 0;
}
idx++;
dst = next;
}
os_free(sbuf);
}
void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
{
wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
priv->wpa_s->ifname);
eloop_wait_for_read_sock(priv->sock);
}
/* Global ctrl_iface */
static char *
wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv,
size_t *reply_len)
{
char *reply;
reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
if (reply == NULL) {
*reply_len = 1;
return NULL;
}
os_memcpy(reply, "COOKIE=", 7);
wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
priv->cookie, COOKIE_LEN);
*reply_len = 7 + 2 * COOKIE_LEN;
return reply;
}
static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct wpa_global *global = eloop_ctx;
struct ctrl_iface_global_priv *priv = sock_ctx;
char *buf, *pos;
int res;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 from;
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
char addr[INET6_ADDRSTRLEN];
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in from;
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
socklen_t fromlen = sizeof(from);
char *reply = NULL;
size_t reply_len;
u8 cookie[COOKIE_LEN];
buf = os_malloc(CTRL_IFACE_MAX_LEN + 1);
if (!buf)
return;
res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
strerror(errno));
os_free(buf);
return;
}
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from));
if (os_strcmp(addr, "::1")) {
wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s",
addr);
os_free(buf);
return;
}
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
/*
* The OS networking stack is expected to drop this kind of
* frames since the socket is bound to only localhost address.
* Just in case, drop the frame if it is coming from any other
* address.
*/
wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
"source %s", inet_ntoa(from.sin_addr));
os_free(buf);
return;
}
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
if ((size_t) res > CTRL_IFACE_MAX_LEN) {
wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated");
os_free(buf);
return;
}
buf[res] = '\0';
if (os_strcmp(buf, "GET_COOKIE") == 0) {
reply = wpa_supplicant_global_get_cookie(priv, &reply_len);
goto done;
}
if (os_strncmp(buf, "COOKIE=", 7) != 0) {
wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
"drop request");
os_free(buf);
return;
}
if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
"request - drop request");
os_free(buf);
return;
}
if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
"drop request");
os_free(buf);
return;
}
pos = buf + 7 + 2 * COOKIE_LEN;
while (*pos == ' ')
pos++;
if (os_strcmp(pos, "ATTACH") == 0) {
if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
&from, fromlen))
reply_len = 1;
else
reply_len = 2;
} else if (os_strcmp(pos, "DETACH") == 0) {
if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
&from, fromlen))
reply_len = 1;
else
reply_len = 2;
} else {
reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
&reply_len);
}
done:
if (reply) {
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen);
os_free(reply);
} else if (reply_len == 1) {
sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
fromlen);
} else if (reply_len == 2) {
sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
fromlen);
}
os_free(buf);
}
struct ctrl_iface_global_priv *
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
{
struct ctrl_iface_global_priv *priv;
struct sockaddr_in addr;
char *pos;
int port = WPA_GLOBAL_CTRL_IFACE_PORT;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
priv->sock = -1;
os_get_random(priv->cookie, COOKIE_LEN);
if (global->params.ctrl_interface == NULL)
return priv;
wpa_printf(MSG_DEBUG, "Global control interface '%s'",
global->params.ctrl_interface);
pos = os_strstr(global->params.ctrl_interface, "udp:");
if (pos) {
pos += 4;
port = atoi(pos);
if (port <= 0) {
wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port %s",
global->params.ctrl_interface);
goto fail;
}
}
priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (priv->sock < 0) {
wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
goto fail;
}
os_memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
addr.sin_addr.s_addr = INADDR_ANY;
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
addr.sin_addr.s_addr = htonl((127 << 24) | 1);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
try_again:
addr.sin_port = htons(port);
if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
port++;
if ((port - WPA_GLOBAL_CTRL_IFACE_PORT) <
WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
goto try_again;
wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
goto fail;
}
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
wpa_printf(MSG_DEBUG, "global_ctrl_iface_init UDP port: %d", port);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
eloop_register_read_sock(priv->sock,
wpa_supplicant_global_ctrl_iface_receive,
global, priv);
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
return priv;
fail:
if (priv->sock >= 0)
close(priv->sock);
os_free(priv);
return NULL;
}
void
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
{
if (priv->sock >= 0) {
eloop_unregister_read_sock(priv->sock);
close(priv->sock);
}
wpas_ctrl_iface_free_dst(priv->ctrl_dst);
os_free(priv);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
all: libwpadbus.a
clean:
rm -f *~ *.o *.d *.gcno *.gcda *.gcov
rm -f libwpadbus.a
install:
@echo Nothing to be made.
ifndef CC
CC=gcc
endif
ifndef CFLAGS
CFLAGS = -MMD -O2 -Wall -g
endif
PKG_CONFIG ?= pkg-config
CFLAGS += -I../../src -I../../src/utils
Q=@
E=echo
ifeq ($(V), 1)
Q=
E=true
endif
%.o: %.c
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
ifdef CONFIG_WPS
CFLAGS += -DCONFIG_WPS
endif
CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW
ifndef DBUS_LIBS
DBUS_LIBS := $(shell $(PKG_CONFIG) --libs dbus-1)
endif
ifndef DBUS_INCLUDE
DBUS_INCLUDE := $(shell $(PKG_CONFIG) --cflags dbus-1)
endif
ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
DBUS_INCLUDE += $(shell xml2-config --cflags)
DBUS_LIBS += $(shell xml2-config --libs)
endif
CFLAGS += $(DBUS_INCLUDE)
LIB_OBJS= \
dbus_common.o \
dbus_new.o \
dbus_new_handlers.o \
dbus_new_helpers.o \
dbus_new_introspect.o \
dbus_dict_helpers.o
ifdef CONFIG_WPS
LIB_OBJS += dbus_new_handlers_wps.o
endif
libwpadbus.a: $(LIB_OBJS)
$(AR) crT $@ $?
-include $(OBJS:%.o=%.d)

View File

@ -0,0 +1,17 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="fi.w1.wpa_supplicant1"/>
<allow send_destination="fi.w1.wpa_supplicant1"/>
<allow send_interface="fi.w1.wpa_supplicant1"/>
<allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
</policy>
<policy context="default">
<deny own="fi.w1.wpa_supplicant1"/>
<deny send_destination="fi.w1.wpa_supplicant1"/>
<deny receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
</policy>
</busconfig>

View File

@ -0,0 +1,373 @@
/*
* wpa_supplicant D-Bus control interface - common functionality
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include <dbus/dbus.h>
#include "utils/common.h"
#include "utils/eloop.h"
#include "dbus_common.h"
#include "dbus_common_i.h"
#include "dbus_new.h"
#include "../wpa_supplicant_i.h"
#ifndef SIGPOLL
#ifdef SIGIO
/*
* If we do not have SIGPOLL, try to use SIGIO instead. This is needed for
* FreeBSD.
*/
#define SIGPOLL SIGIO
#endif
#endif
static void dispatch_data(DBusConnection *con)
{
while (dbus_connection_get_dispatch_status(con) ==
DBUS_DISPATCH_DATA_REMAINS)
dbus_connection_dispatch(con);
}
/**
* dispatch_initial_dbus_messages - Dispatch initial dbus messages after
* claiming bus name
* @eloop_ctx: the DBusConnection to dispatch on
* @timeout_ctx: unused
*
* If clients are quick to notice that service claimed its bus name,
* there may have been messages that came in before initialization was
* all finished. Dispatch those here.
*/
static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
{
DBusConnection *con = eloop_ctx;
dispatch_data(con);
}
static void process_watch(struct wpas_dbus_priv *priv,
DBusWatch *watch, eloop_event_type type)
{
dbus_connection_ref(priv->con);
priv->should_dispatch = 0;
if (type == EVENT_TYPE_READ)
dbus_watch_handle(watch, DBUS_WATCH_READABLE);
else if (type == EVENT_TYPE_WRITE)
dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
else if (type == EVENT_TYPE_EXCEPTION)
dbus_watch_handle(watch, DBUS_WATCH_ERROR);
if (priv->should_dispatch) {
dispatch_data(priv->con);
priv->should_dispatch = 0;
}
dbus_connection_unref(priv->con);
}
static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
}
static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
}
static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
{
process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
}
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
{
struct wpas_dbus_priv *priv = data;
unsigned int flags;
int fd;
if (!dbus_watch_get_enabled(watch))
return TRUE;
flags = dbus_watch_get_flags(watch);
fd = dbus_watch_get_unix_fd(watch);
if (eloop_register_sock(fd, EVENT_TYPE_EXCEPTION,
process_watch_exception, priv, watch) < 0)
return FALSE;
if ((flags & DBUS_WATCH_READABLE) &&
eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
priv, watch) < 0)
return FALSE;
if ((flags & DBUS_WATCH_WRITABLE) &&
eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
priv, watch) < 0)
return FALSE;
dbus_watch_set_data(watch, priv, NULL);
return TRUE;
}
static void remove_watch(DBusWatch *watch, void *data)
{
unsigned int flags;
int fd;
flags = dbus_watch_get_flags(watch);
fd = dbus_watch_get_unix_fd(watch);
eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
if (flags & DBUS_WATCH_READABLE)
eloop_unregister_sock(fd, EVENT_TYPE_READ);
if (flags & DBUS_WATCH_WRITABLE)
eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
dbus_watch_set_data(watch, NULL, NULL);
}
static void watch_toggled(DBusWatch *watch, void *data)
{
if (dbus_watch_get_enabled(watch))
add_watch(watch, data);
else
remove_watch(watch, data);
}
static void process_timeout(void *eloop_ctx, void *sock_ctx)
{
DBusTimeout *timeout = sock_ctx;
dbus_timeout_handle(timeout);
}
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
{
struct wpas_dbus_priv *priv = data;
if (!dbus_timeout_get_enabled(timeout))
return TRUE;
eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
process_timeout, priv, timeout);
dbus_timeout_set_data(timeout, priv, NULL);
return TRUE;
}
static void remove_timeout(DBusTimeout *timeout, void *data)
{
struct wpas_dbus_priv *priv = data;
eloop_cancel_timeout(process_timeout, priv, timeout);
dbus_timeout_set_data(timeout, NULL, NULL);
}
static void timeout_toggled(DBusTimeout *timeout, void *data)
{
if (dbus_timeout_get_enabled(timeout))
add_timeout(timeout, data);
else
remove_timeout(timeout, data);
}
static void process_wakeup_main(int sig, void *signal_ctx)
{
struct wpas_dbus_priv *priv = signal_ctx;
if (sig != SIGPOLL || !priv->con)
return;
if (dbus_connection_get_dispatch_status(priv->con) !=
DBUS_DISPATCH_DATA_REMAINS)
return;
/* Only dispatch once - we do not want to starve other events */
dbus_connection_ref(priv->con);
dbus_connection_dispatch(priv->con);
dbus_connection_unref(priv->con);
}
/**
* wakeup_main - Attempt to wake our mainloop up
* @data: dbus control interface private data
*
* Try to wake up the main eloop so it will process
* dbus events that may have happened.
*/
static void wakeup_main(void *data)
{
struct wpas_dbus_priv *priv = data;
/* Use SIGPOLL to break out of the eloop select() */
raise(SIGPOLL);
priv->should_dispatch = 1;
}
/**
* integrate_with_eloop - Register our mainloop integration with dbus
* @connection: connection to the system message bus
* @priv: a dbus control interface data structure
* Returns: 0 on success, -1 on failure
*/
static int integrate_with_eloop(struct wpas_dbus_priv *priv)
{
if (!dbus_connection_set_watch_functions(priv->con, add_watch,
remove_watch, watch_toggled,
priv, NULL) ||
!dbus_connection_set_timeout_functions(priv->con, add_timeout,
remove_timeout,
timeout_toggled, priv,
NULL)) {
wpa_printf(MSG_ERROR, "dbus: Failed to set callback functions");
return -1;
}
if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv))
return -1;
dbus_connection_set_wakeup_main_function(priv->con, wakeup_main,
priv, NULL);
return 0;
}
static DBusHandlerResult disconnect_filter(DBusConnection *conn,
DBusMessage *message, void *data)
{
struct wpas_dbus_priv *priv = data;
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL,
"Disconnected")) {
wpa_printf(MSG_DEBUG, "dbus: bus disconnected, terminating");
dbus_connection_set_exit_on_disconnect(conn, FALSE);
wpa_supplicant_terminate_proc(priv->global);
return DBUS_HANDLER_RESULT_HANDLED;
} else
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static int wpas_dbus_init_common(struct wpas_dbus_priv *priv)
{
DBusError error;
int ret = 0;
/* Get a reference to the system bus */
dbus_error_init(&error);
priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
if (priv->con) {
dbus_connection_add_filter(priv->con, disconnect_filter, priv,
NULL);
} else {
wpa_printf(MSG_ERROR,
"dbus: Could not acquire the system bus: %s - %s",
error.name, error.message);
ret = -1;
}
dbus_error_free(&error);
return ret;
}
static int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv)
{
/* Tell dbus about our mainloop integration functions */
integrate_with_eloop(priv);
/*
* Dispatch initial DBus messages that may have come in since the bus
* name was claimed above. Happens when clients are quick to notice the
* service.
*
* FIXME: is there a better solution to this problem?
*/
eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
priv->con, NULL);
return 0;
}
static void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv)
{
if (priv->con) {
eloop_cancel_timeout(dispatch_initial_dbus_messages,
priv->con, NULL);
eloop_cancel_timeout(process_timeout, priv, ELOOP_ALL_CTX);
dbus_connection_set_watch_functions(priv->con, NULL, NULL,
NULL, NULL, NULL);
dbus_connection_set_timeout_functions(priv->con, NULL, NULL,
NULL, NULL, NULL);
dbus_connection_remove_filter(priv->con, disconnect_filter,
priv);
dbus_connection_unref(priv->con);
}
os_free(priv);
}
struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global)
{
struct wpas_dbus_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
priv->global = global;
if (wpas_dbus_init_common(priv) < 0 ||
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
wpas_dbus_ctrl_iface_init(priv) < 0 ||
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
wpas_dbus_init_common_finish(priv) < 0) {
wpas_dbus_deinit(priv);
return NULL;
}
return priv;
}
void wpas_dbus_deinit(struct wpas_dbus_priv *priv)
{
if (priv == NULL)
return;
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
wpas_dbus_ctrl_iface_deinit(priv);
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
wpas_dbus_deinit_common(priv);
}

View File

@ -0,0 +1,20 @@
/*
* wpa_supplicant D-Bus control interface - common definitions
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef DBUS_COMMON_H
#define DBUS_COMMON_H
struct wpas_dbus_priv;
struct wpa_global;
struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global);
void wpas_dbus_deinit(struct wpas_dbus_priv *priv);
#endif /* DBUS_COMMON_H */

View File

@ -0,0 +1,34 @@
/*
* wpa_supplicant D-Bus control interface - internal definitions
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef DBUS_COMMON_I_H
#define DBUS_COMMON_I_H
#include <dbus/dbus.h>
struct wpa_dbus_property_desc;
struct wpas_dbus_priv {
DBusConnection *con;
int should_dispatch;
struct wpa_global *global;
u32 next_objid;
int dbus_new_initialized;
#if defined(CONFIG_CTRL_IFACE_DBUS_NEW)
struct wpa_dbus_property_desc *all_interface_properties;
int globals_start;
#if defined(CONFIG_AP)
int dbus_noc_refcnt;
#endif /* CONFIG_AP */
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
};
#endif /* DBUS_COMMON_I_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
/*
* WPA Supplicant / dbus-based control interface
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef DBUS_DICT_HELPERS_H
#define DBUS_DICT_HELPERS_H
#include "wpabuf.h"
/*
* Adding a dict to a DBusMessage
*/
dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter,
DBusMessageIter *iter_dict);
dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter,
DBusMessageIter *iter_dict);
const char * wpa_dbus_type_as_string(const int type);
dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
const char *key, const char *value);
dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
const char *key,
const dbus_bool_t value);
dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
const char *key,
const dbus_int16_t value);
dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
const char *key,
const dbus_uint16_t value);
dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
const char *key,
const dbus_int32_t value);
dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
const char *key,
const dbus_uint32_t value);
dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
const char *key,
const char *value);
dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
const char *key,
const char *value,
const dbus_uint32_t value_len);
/* Manual construction and addition of array elements */
dbus_bool_t wpa_dbus_dict_begin_array(DBusMessageIter *iter_dict,
const char *key, const char *type,
DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array);
dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
const char *key,
DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array);
dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
const char *elem);
dbus_bool_t wpa_dbus_dict_bin_array_add_element(DBusMessageIter *iter_array,
const u8 *value,
size_t value_len);
dbus_bool_t wpa_dbus_dict_end_array(DBusMessageIter *iter_dict,
DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array);
static inline dbus_bool_t
wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict,
DBusMessageIter *iter_dict_entry,
DBusMessageIter *iter_dict_val,
DBusMessageIter *iter_array)
{
return wpa_dbus_dict_end_array(iter_dict, iter_dict_entry,
iter_dict_val, iter_array);
}
/* Convenience function to add a whole string list */
dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
const char *key,
const char **items,
const dbus_uint32_t num_items);
dbus_bool_t wpa_dbus_dict_append_wpabuf_array(DBusMessageIter *iter_dict,
const char *key,
const struct wpabuf **items,
const dbus_uint32_t num_items);
/*
* Reading a dict from a DBusMessage
*/
/*
* Used only in struct wpa_dbus_dict_entry::array_type internally to identify
* special binary array case.
*/
#define WPAS_DBUS_TYPE_BINARRAY ((int) '@')
struct wpa_dbus_dict_entry {
int type; /** the dbus type of the dict entry's value */
int array_type; /** the dbus type of the array elements if the dict
entry value contains an array, or the special
WPAS_DBUS_TYPE_BINARRAY */
const char *key; /** key of the dict entry */
/** Possible values of the property */
union {
char *str_value;
char byte_value;
dbus_bool_t bool_value;
dbus_int16_t int16_value;
dbus_uint16_t uint16_value;
dbus_int32_t int32_value;
dbus_uint32_t uint32_value;
dbus_int64_t int64_value;
dbus_uint64_t uint64_value;
double double_value;
char *bytearray_value;
char **strarray_value;
struct wpabuf **binarray_value;
};
dbus_uint32_t array_len; /** length of the array if the dict entry's
value contains an array */
};
dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
DBusMessageIter *iter_dict,
DBusError *error);
dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
struct wpa_dbus_dict_entry *entry);
dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict);
void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry);
#endif /* DBUS_DICT_HELPERS_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,648 @@
/*
* WPA Supplicant / dbus-based control interface
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef CTRL_IFACE_DBUS_NEW_H
#define CTRL_IFACE_DBUS_NEW_H
#include "common/defs.h"
#include "p2p/p2p.h"
struct wpa_global;
struct wpa_supplicant;
struct wpa_ssid;
struct wpa_cred;
struct wpa_bss;
struct wps_event_m2d;
struct wps_event_fail;
struct wps_credential;
enum wpas_dbus_prop {
WPAS_DBUS_PROP_AP_SCAN,
WPAS_DBUS_PROP_SCANNING,
WPAS_DBUS_PROP_STATE,
WPAS_DBUS_PROP_CURRENT_BSS,
WPAS_DBUS_PROP_CURRENT_NETWORK,
WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
WPAS_DBUS_PROP_BSSS,
WPAS_DBUS_PROP_STATIONS,
WPAS_DBUS_PROP_DISCONNECT_REASON,
WPAS_DBUS_PROP_AUTH_STATUS_CODE,
WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
WPAS_DBUS_PROP_ROAM_TIME,
WPAS_DBUS_PROP_ROAM_COMPLETE,
WPAS_DBUS_PROP_SESSION_LENGTH,
WPAS_DBUS_PROP_BSS_TM_STATUS,
};
enum wpas_dbus_bss_prop {
WPAS_DBUS_BSS_PROP_SIGNAL,
WPAS_DBUS_BSS_PROP_FREQ,
WPAS_DBUS_BSS_PROP_MODE,
WPAS_DBUS_BSS_PROP_PRIVACY,
WPAS_DBUS_BSS_PROP_RATES,
WPAS_DBUS_BSS_PROP_WPA,
WPAS_DBUS_BSS_PROP_RSN,
WPAS_DBUS_BSS_PROP_WPS,
WPAS_DBUS_BSS_PROP_IES,
WPAS_DBUS_BSS_PROP_AGE,
};
enum wpas_dbus_sta_prop {
WPAS_DBUS_STA_PROP_ADDRESS,
};
#define WPAS_DBUS_OBJECT_PATH_MAX 150
#define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1"
#define WPAS_DBUS_NEW_PATH "/fi/w1/wpa_supplicant1"
#define WPAS_DBUS_NEW_INTERFACE "fi.w1.wpa_supplicant1"
#define WPAS_DBUS_NEW_PATH_INTERFACES WPAS_DBUS_NEW_PATH "/Interfaces"
#define WPAS_DBUS_NEW_IFACE_INTERFACE WPAS_DBUS_NEW_INTERFACE ".Interface"
#define WPAS_DBUS_NEW_IFACE_WPS WPAS_DBUS_NEW_IFACE_INTERFACE ".WPS"
#define WPAS_DBUS_NEW_NETWORKS_PART "Networks"
#define WPAS_DBUS_NEW_IFACE_NETWORK WPAS_DBUS_NEW_INTERFACE ".Network"
#define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
#define WPAS_DBUS_NEW_IFACE_BSS WPAS_DBUS_NEW_INTERFACE ".BSS"
#define WPAS_DBUS_NEW_STAS_PART "Stations"
#define WPAS_DBUS_NEW_IFACE_STA WPAS_DBUS_NEW_INTERFACE ".Station"
#define WPAS_DBUS_NEW_IFACE_P2PDEVICE \
WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice"
#define WPAS_DBUS_NEW_IFACE_MESH WPAS_DBUS_NEW_IFACE_INTERFACE ".Mesh"
/*
* Groups correspond to P2P groups where this device is a GO (owner)
*/
#define WPAS_DBUS_NEW_P2P_GROUPS_PART "Groups"
#define WPAS_DBUS_NEW_IFACE_P2P_GROUP WPAS_DBUS_NEW_INTERFACE ".Group"
/*
* Different dbus object for persistent groups so they do not get confused
* with regular (configured) network objects.
*/
#define WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "PersistentGroups"
#define WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP \
WPAS_DBUS_NEW_INTERFACE ".PersistentGroup"
#define WPAS_DBUS_NEW_P2P_PEERS_PART "Peers"
#define WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
#define WPAS_DBUS_NEW_CREDENTIALS_PART "Credentials"
#define WPAS_DBUS_NEW_IFACE_CREDENTIAL WPAS_DBUS_NEW_INTERFACE ".Credential"
/* Top-level Errors */
#define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
WPAS_DBUS_NEW_INTERFACE ".UnknownError"
#define WPAS_DBUS_ERROR_INVALID_ARGS \
WPAS_DBUS_NEW_INTERFACE ".InvalidArgs"
#define WPAS_DBUS_ERROR_IFACE_EXISTS \
WPAS_DBUS_NEW_INTERFACE ".InterfaceExists"
#define WPAS_DBUS_ERROR_IFACE_DISABLED \
WPAS_DBUS_NEW_INTERFACE ".InterfaceDisabled"
#define WPAS_DBUS_ERROR_IFACE_UNKNOWN \
WPAS_DBUS_NEW_INTERFACE ".InterfaceUnknown"
#define WPAS_DBUS_ERROR_NOT_CONNECTED \
WPAS_DBUS_NEW_INTERFACE ".NotConnected"
#define WPAS_DBUS_ERROR_NETWORK_UNKNOWN \
WPAS_DBUS_NEW_INTERFACE ".NetworkUnknown"
#define WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE \
WPAS_DBUS_NEW_INTERFACE ".ConnectChannelUnavailable"
#define WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED \
WPAS_DBUS_NEW_INTERFACE ".ConnectChannelUnsupported"
#define WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR \
WPAS_DBUS_NEW_INTERFACE ".ConnectUnspecifiedError"
#define WPAS_DBUS_ERROR_BLOB_EXISTS \
WPAS_DBUS_NEW_INTERFACE ".BlobExists"
#define WPAS_DBUS_ERROR_BLOB_UNKNOWN \
WPAS_DBUS_NEW_INTERFACE ".BlobUnknown"
#define WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE \
WPAS_DBUS_NEW_INTERFACE ".SubscriptionInUse"
#define WPAS_DBUS_ERROR_NO_SUBSCRIPTION \
WPAS_DBUS_NEW_INTERFACE ".NoSubscription"
#define WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM \
WPAS_DBUS_NEW_INTERFACE ".SubscriptionNotYou"
/* Interface-level errors */
#define WPAS_DBUS_ERROR_IFACE_SCAN_ERROR \
WPAS_DBUS_NEW_IFACE_INTERFACE ".ScanError"
void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv);
void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv);
#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv);
void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface);
int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s);
int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s);
void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
enum wpas_dbus_prop property);
void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
enum wpas_dbus_bss_prop property,
unsigned int id);
void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id);
void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
enum wpa_ctrl_req_type rtype,
const char *default_text);
void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success);
void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
const struct wps_credential *cred);
void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
struct wps_event_m2d *m2d);
void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
struct wps_event_fail *fail);
void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s);
void wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s);
int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid);
int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id);
int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id);
int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta);
void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
const char *name);
void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
const char *name);
void wpas_dbus_signal_debug_level_changed(struct wpa_global *global);
void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global);
void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global);
int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr);
void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s);
void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
const u8 *dev_addr);
int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
const u8 *dev_addr);
void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
const u8 *dev_addr);
void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
const u8 *dev_addr);
void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
const char *role);
void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
const u8 *dev_addr, int request,
enum p2p_prov_disc_status status,
u16 config_methods,
unsigned int generated_pin);
void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
const u8 *src, u16 dev_passwd_id,
u8 go_intent);
void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
int client, int persistent,
const u8 *ip);
void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *res);
void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
const struct wpa_ssid *ssid);
int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
int nid);
void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
int status, const u8 *bssid);
void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
const u8 *member);
void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
int freq, const u8 *sa, u8 dialog_token,
u16 update_indic, const u8 *tlvs,
size_t tlvs_len);
void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
const u8 *sa, u16 update_indic,
const u8 *tlvs, size_t tlvs_len);
void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
const u8 *member);
void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
struct wps_event_fail *fail);
void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
int depth, const char *subject,
const char *altsubject[],
int num_altsubject,
const char *cert_hash,
const struct wpabuf *cert);
void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
const u8 *addr, const u8 *dst, const u8 *bssid,
const u8 *ie, size_t ie_len, u32 ssi_signal);
void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
const char *status, const char *parameter);
void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
const u8 *sta);
void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
const u8 *sta);
void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *dev_addr,
const u8 *bssid, int id,
int op_freq);
void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
const u8 *meshid, u8 meshid_len,
int reason);
void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
const u8 *peer_addr);
void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
const u8 *peer_addr, int reason);
void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss,
struct wpa_cred *cred,
const char *type, int excluded,
int bh, int bss_load,
int conn_capab);
void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s);
#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
static inline int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
{
return 0;
}
static inline int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
{
return 0;
}
#define wpas_dbus_signal_state_changed(w, n, o) do { } while (0)
static inline void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
enum wpas_dbus_prop property)
{
}
static inline void wpas_dbus_bss_signal_prop_changed(
struct wpa_supplicant *wpa_s, enum wpas_dbus_bss_prop property,
unsigned int id)
{
}
static inline void wpas_dbus_signal_network_enabled_changed(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
}
static inline void wpas_dbus_signal_network_selected(
struct wpa_supplicant *wpa_s, int id)
{
}
static inline void wpas_dbus_signal_network_request(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
enum wpa_ctrl_req_type rtype, const char *default_txt)
{
}
static inline void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
int success)
{
}
static inline void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
const struct wps_credential *cred)
{
}
static inline void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
struct wps_event_m2d *m2d)
{
}
static inline void wpas_dbus_signal_wps_event_fail(
struct wpa_supplicant *wpa_s, struct wps_event_fail *fail)
{
}
static inline void wpas_dbus_signal_wps_event_success(
struct wpa_supplicant *wpa_s)
{
}
static inline void wpas_dbus_signal_wps_event_pbc_overlap(
struct wpa_supplicant *wpa_s)
{
}
static inline int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
return 0;
}
static inline int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s,
int nid)
{
return 0;
}
static inline int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id)
{
return 0;
}
static inline int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
u8 bssid[ETH_ALEN], unsigned int id)
{
return 0;
}
static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
const u8 *sta)
{
return 0;
}
static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
const u8 *sta)
{
return 0;
}
static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
const char *name)
{
}
static inline void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
const char *name)
{
}
static inline void wpas_dbus_signal_debug_level_changed(
struct wpa_global *global)
{
}
static inline void wpas_dbus_signal_debug_timestamp_changed(
struct wpa_global *global)
{
}
static inline void wpas_dbus_signal_debug_show_keys_changed(
struct wpa_global *global)
{
}
static inline int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s,
const u8 *dev_addr)
{
return 0;
}
static inline int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
const u8 *dev_addr)
{
return 0;
}
static inline void
wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
const u8 *dev_addr)
{
}
static inline void
wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
const char *role)
{
}
static inline void
wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
const u8 *dev_addr, int request,
enum p2p_prov_disc_status status,
u16 config_methods,
unsigned int generated_pin)
{
}
static inline void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
const u8 *src,
u16 dev_passwd_id,
u8 go_intent)
{
}
static inline void
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
int client, int persistent,
const u8 *ip)
{
}
static inline void
wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason)
{
}
static inline void
wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
}
static inline int wpas_dbus_register_persistent_group(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
return 0;
}
static inline int wpas_dbus_unregister_persistent_group(
struct wpa_supplicant *wpa_s, int nid)
{
return 0;
}
static inline void
wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *res)
{
}
static inline void
wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
const struct wpa_ssid *ssid)
{
}
static inline void wpas_dbus_signal_p2p_invitation_result(
struct wpa_supplicant *wpa_s, int status,
const u8 *bssid)
{
}
static inline void
wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
const u8 *p2p_if_addr)
{
}
static inline void
wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, int freq,
const u8 *sa, u8 dialog_token, u16 update_indic,
const u8 *tlvs, size_t tlvs_len)
{
}
static inline void
wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
const u8 *sa, u16 update_indic,
const u8 *tlvs, size_t tlvs_len)
{
}
static inline void
wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
const u8 *p2p_if_addr)
{
}
static inline void
wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
const u8 *member)
{
}
static inline void
wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
{
}
static inline void
wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
const u8 *dev_addr)
{
}
static inline void
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
const u8 *dev_addr)
{
}
static inline void
wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
const u8 *member)
{
}
static inline void
wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
struct wps_event_fail *fail)
{
}
static inline void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
int depth,
const char *subject,
const char *altsubject[],
int num_altsubject,
const char *cert_hash,
const struct wpabuf *cert)
{
}
static inline void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
const u8 *addr, const u8 *dst,
const u8 *bssid,
const u8 *ie, size_t ie_len,
u32 ssi_signal)
{
}
static inline void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
const char *status,
const char *parameter)
{
}
static inline
void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
const u8 *sta)
{
}
static inline
void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
const u8 *sta)
{
}
static inline
void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *dev_addr,
const u8 *bssid, int id,
int op_freq)
{
}
static inline
void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
}
static inline
void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
const u8 *meshid, u8 meshid_len,
int reason)
{
}
static inline
void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
const u8 *peer_addr)
{
}
static inline
void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
const u8 *peer_addr, int reason)
{
}
static inline
void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss,
struct wpa_cred *cred,
const char *type, int excluded,
int bh, int bss_load,
int conn_capab)
{
}
static inline
void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
{
}
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
#endif /* CTRL_IFACE_DBUS_H_NEW */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,285 @@
/*
* WPA Supplicant / dbus-based control interface
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef CTRL_IFACE_DBUS_NEW_HANDLERS_H
#define CTRL_IFACE_DBUS_NEW_HANDLERS_H
#include "dbus_new_helpers.h"
struct network_handler_args {
struct wpa_supplicant *wpa_s;
struct wpa_ssid *ssid;
};
struct bss_handler_args {
struct wpa_supplicant *wpa_s;
unsigned int id;
};
struct sta_handler_args {
struct wpa_supplicant *wpa_s;
const u8 *sta;
};
dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter,
const int type,
const void *val,
DBusError *error);
dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter,
DBusError *error,
const int type, void *val);
dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
const int type,
const void *array,
size_t array_len,
DBusError *error);
dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter,
const int type,
struct wpabuf **array,
size_t array_len,
DBusError *error);
dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter,
const void *val,
DBusError *error);
DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
struct wpa_global *global);
DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
struct wpa_global *global);
DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
struct wpa_global *global);
DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
struct wpa_global *global);
DECLARE_ACCESSOR(wpas_dbus_getter_debug_level);
DECLARE_ACCESSOR(wpas_dbus_getter_debug_timestamp);
DECLARE_ACCESSOR(wpas_dbus_getter_debug_show_keys);
DECLARE_ACCESSOR(wpas_dbus_setter_debug_level);
DECLARE_ACCESSOR(wpas_dbus_setter_debug_timestamp);
DECLARE_ACCESSOR(wpas_dbus_setter_debug_show_keys);
DECLARE_ACCESSOR(wpas_dbus_getter_interfaces);
DECLARE_ACCESSOR(wpas_dbus_getter_eap_methods);
DECLARE_ACCESSOR(wpas_dbus_getter_global_capabilities);
DECLARE_ACCESSOR(wpas_dbus_getter_iface_global);
DECLARE_ACCESSOR(wpas_dbus_setter_iface_global);
DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
struct wpa_supplicant *wpa_s);
dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
DBusMessageIter *iter,
DBusError *error);
DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_remove_all_networks(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_roam(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage *
wpas_dbus_handler_interworking_select(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
DECLARE_ACCESSOR(wpas_dbus_getter_state);
DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
DECLARE_ACCESSOR(wpas_dbus_getter_ap_scan);
DECLARE_ACCESSOR(wpas_dbus_setter_ap_scan);
DECLARE_ACCESSOR(wpas_dbus_getter_fast_reauth);
DECLARE_ACCESSOR(wpas_dbus_setter_fast_reauth);
DECLARE_ACCESSOR(wpas_dbus_getter_disconnect_reason);
DECLARE_ACCESSOR(wpas_dbus_getter_disassociate_reason);
DECLARE_ACCESSOR(wpas_dbus_getter_auth_status_code);
DECLARE_ACCESSOR(wpas_dbus_getter_assoc_status_code);
DECLARE_ACCESSOR(wpas_dbus_getter_roam_time);
DECLARE_ACCESSOR(wpas_dbus_getter_roam_complete);
DECLARE_ACCESSOR(wpas_dbus_getter_session_length);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_tm_status);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_age);
DECLARE_ACCESSOR(wpas_dbus_setter_bss_expire_age);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_count);
DECLARE_ACCESSOR(wpas_dbus_setter_bss_expire_count);
DECLARE_ACCESSOR(wpas_dbus_getter_country);
DECLARE_ACCESSOR(wpas_dbus_setter_country);
DECLARE_ACCESSOR(wpas_dbus_getter_scan_interval);
DECLARE_ACCESSOR(wpas_dbus_setter_scan_interval);
DECLARE_ACCESSOR(wpas_dbus_getter_ifname);
DECLARE_ACCESSOR(wpas_dbus_getter_driver);
DECLARE_ACCESSOR(wpas_dbus_getter_bridge_ifname);
DECLARE_ACCESSOR(wpas_dbus_setter_bridge_ifname);
DECLARE_ACCESSOR(wpas_dbus_getter_config_file);
DECLARE_ACCESSOR(wpas_dbus_getter_current_bss);
DECLARE_ACCESSOR(wpas_dbus_getter_current_network);
DECLARE_ACCESSOR(wpas_dbus_getter_current_auth_mode);
DECLARE_ACCESSOR(wpas_dbus_getter_bsss);
DECLARE_ACCESSOR(wpas_dbus_getter_networks);
DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_engine_path);
DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_module_path);
DECLARE_ACCESSOR(wpas_dbus_getter_blobs);
DECLARE_ACCESSOR(wpas_dbus_getter_stas);
DECLARE_ACCESSOR(wpas_dbus_getter_mac_address_randomization_mask);
DECLARE_ACCESSOR(wpas_dbus_setter_mac_address_randomization_mask);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_address);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_aid);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_caps);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_packets);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_packets);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_tx_bytes);
DECLARE_ACCESSOR(wpas_dbus_getter_sta_rx_bytes);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_bssid);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_ssid);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_privacy);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_mode);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_signal);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_frequency);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_rates);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_wpa);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_rsn);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_wps);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_ies);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_age);
DECLARE_ACCESSOR(wpas_dbus_getter_enabled);
DECLARE_ACCESSOR(wpas_dbus_setter_enabled);
DECLARE_ACCESSOR(wpas_dbus_getter_network_properties);
DECLARE_ACCESSOR(wpas_dbus_setter_network_properties);
DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_wps_cancel(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DECLARE_ACCESSOR(wpas_dbus_getter_process_credentials);
DECLARE_ACCESSOR(wpas_dbus_setter_process_credentials);
DECLARE_ACCESSOR(wpas_dbus_getter_config_methods);
DECLARE_ACCESSOR(wpas_dbus_setter_config_methods);
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_name);
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_name);
DECLARE_ACCESSOR(wpas_dbus_getter_wps_manufacturer);
DECLARE_ACCESSOR(wpas_dbus_setter_wps_manufacturer);
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_model_name);
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_model_name);
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_model_number);
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_model_number);
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_serial_number);
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_serial_number);
DECLARE_ACCESSOR(wpas_dbus_getter_wps_device_device_type);
DECLARE_ACCESSOR(wpas_dbus_setter_wps_device_device_type);
DECLARE_ACCESSOR(wpas_dbus_getter_mesh_peers);
DECLARE_ACCESSOR(wpas_dbus_getter_mesh_group);
DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage *
wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage *
wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_vendor_elem_remove(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
const char *arg);
DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
const char *arg);
DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message);
DBusMessage * wpas_dbus_handler_subscribe_preq(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_unsubscribe_preq(
DBusMessage *message, struct wpa_supplicant *wpa_s);
#endif /* CTRL_IFACE_DBUS_HANDLERS_NEW_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
/*
* WPA Supplicant / dbus-based control interface for p2p
* Copyright (c) 2011-2012, Intel Corporation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef DBUS_NEW_HANDLERS_P2P_H
#define DBUS_NEW_HANDLERS_P2P_H
struct peer_handler_args {
struct wpa_supplicant *wpa_s;
u8 p2p_device_addr[ETH_ALEN];
};
/*
* P2P Device methods
*/
DBusMessage *wpas_dbus_handler_p2p_find(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_stop_find(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_rejectpeer(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_listen(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_extendedlisten(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_presence_request(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_prov_disc_req(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_group_add(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_connect(
DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_p2p_cancel(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_invite(
DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_disconnect(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_p2p_remove_client(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_flush(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_add_service(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_delete_service(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_flush_service(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_service_sd_req(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_service_sd_res(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_service_sd_cancel_req(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_service_update(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *wpas_dbus_handler_p2p_serv_disc_external(
DBusMessage *message, struct wpa_supplicant *wpa_s);
/*
* P2P Device property accessor methods.
*/
DECLARE_ACCESSOR(wpas_dbus_setter_p2p_device_config);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_device_config);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peers);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_role);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peergo);
/*
* P2P Peer properties.
*/
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_name);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_manufacturer);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_modelname);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_modelnumber);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_serialnumber);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_primary_device_type);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_config_method);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_level);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_capability);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_group_capability);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_secondary_device_types);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_vendor_extension);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_ies);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_address);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_groups);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_vsie);
/*
* P2P Group properties
*/
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_members);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_ssid);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_bssid);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_frequency);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_passphrase);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_psk);
DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_vendor_ext);
DECLARE_ACCESSOR(wpas_dbus_setter_p2p_group_vendor_ext);
/*
* P2P Persistent Groups and properties
*/
DECLARE_ACCESSOR(wpas_dbus_getter_persistent_groups);
DECLARE_ACCESSOR(wpas_dbus_getter_persistent_group_properties);
DECLARE_ACCESSOR(wpas_dbus_setter_persistent_group_properties);
DBusMessage * wpas_dbus_handler_add_persistent_group(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_remove_persistent_group(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
DBusMessage *message, struct wpa_supplicant *wpa_s);
#ifdef CONFIG_WIFI_DISPLAY
DECLARE_ACCESSOR(wpas_dbus_getter_global_wfd_ies);
DECLARE_ACCESSOR(wpas_dbus_setter_global_wfd_ies);
#endif /* CONFIG_WIFI_DISPLAY */
#endif /* DBUS_NEW_HANDLERS_P2P_H */

View File

@ -0,0 +1,804 @@
/*
* WPA Supplicant / dbus-based control interface (WPS)
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "../config.h"
#include "../wpa_supplicant_i.h"
#include "../wps_supplicant.h"
#include "../driver_i.h"
#include "../ap.h"
#include "dbus_new_helpers.h"
#include "dbus_new.h"
#include "dbus_new_handlers.h"
#include "dbus_dict_helpers.h"
struct wps_start_params {
int role; /* 0 - not set, 1 - enrollee, 2 - registrar */
int type; /* 0 - not set, 1 - pin, 2 - pbc */
u8 *bssid;
char *pin;
u8 *p2p_dev_addr;
};
static int wpas_dbus_handler_wps_role(DBusMessage *message,
DBusMessageIter *entry_iter,
struct wps_start_params *params,
DBusMessage **reply)
{
DBusMessageIter variant_iter;
char *val;
dbus_message_iter_recurse(entry_iter, &variant_iter);
if (dbus_message_iter_get_arg_type(&variant_iter) !=
DBUS_TYPE_STRING) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start - Wrong Role type, string required");
*reply = wpas_dbus_error_invalid_args(message,
"Role must be a string");
return -1;
}
dbus_message_iter_get_basic(&variant_iter, &val);
if (os_strcmp(val, "enrollee") == 0)
params->role = 1;
else if (os_strcmp(val, "registrar") == 0)
params->role = 2;
else {
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown role %s", val);
*reply = wpas_dbus_error_invalid_args(message, val);
return -1;
}
return 0;
}
static int wpas_dbus_handler_wps_type(DBusMessage *message,
DBusMessageIter *entry_iter,
struct wps_start_params *params,
DBusMessage **reply)
{
DBusMessageIter variant_iter;
char *val;
dbus_message_iter_recurse(entry_iter, &variant_iter);
if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_STRING) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start - Wrong Type type, string required");
*reply = wpas_dbus_error_invalid_args(message,
"Type must be a string");
return -1;
}
dbus_message_iter_get_basic(&variant_iter, &val);
if (os_strcmp(val, "pin") == 0)
params->type = 1;
else if (os_strcmp(val, "pbc") == 0)
params->type = 2;
else {
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown type %s",
val);
*reply = wpas_dbus_error_invalid_args(message, val);
return -1;
}
return 0;
}
static int wpas_dbus_handler_wps_bssid(DBusMessage *message,
DBusMessageIter *entry_iter,
struct wps_start_params *params,
DBusMessage **reply)
{
DBusMessageIter variant_iter, array_iter;
int len;
dbus_message_iter_recurse(entry_iter, &variant_iter);
if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&variant_iter) !=
DBUS_TYPE_BYTE) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start - Wrong Bssid type, byte array required");
*reply = wpas_dbus_error_invalid_args(
message, "Bssid must be a byte array");
return -1;
}
dbus_message_iter_recurse(&variant_iter, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &params->bssid, &len);
if (len != ETH_ALEN) {
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Bssid length %d",
len);
*reply = wpas_dbus_error_invalid_args(message,
"Bssid is wrong length");
return -1;
}
return 0;
}
static int wpas_dbus_handler_wps_pin(DBusMessage *message,
DBusMessageIter *entry_iter,
struct wps_start_params *params,
DBusMessage **reply)
{
DBusMessageIter variant_iter;
dbus_message_iter_recurse(entry_iter, &variant_iter);
if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_STRING) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start - Wrong Pin type, string required");
*reply = wpas_dbus_error_invalid_args(message,
"Pin must be a string");
return -1;
}
dbus_message_iter_get_basic(&variant_iter, &params->pin);
return 0;
}
#ifdef CONFIG_P2P
static int wpas_dbus_handler_wps_p2p_dev_addr(DBusMessage *message,
DBusMessageIter *entry_iter,
struct wps_start_params *params,
DBusMessage **reply)
{
DBusMessageIter variant_iter, array_iter;
int len;
dbus_message_iter_recurse(entry_iter, &variant_iter);
if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
dbus_message_iter_get_element_type(&variant_iter) !=
DBUS_TYPE_BYTE) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start - Wrong P2PDeviceAddress type, byte array required");
*reply = wpas_dbus_error_invalid_args(
message, "P2PDeviceAddress must be a byte array");
return -1;
}
dbus_message_iter_recurse(&variant_iter, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &params->p2p_dev_addr,
&len);
if (len != ETH_ALEN) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start - Wrong P2PDeviceAddress length %d",
len);
*reply = wpas_dbus_error_invalid_args(
message, "P2PDeviceAddress has wrong length");
return -1;
}
return 0;
}
#endif /* CONFIG_P2P */
static int wpas_dbus_handler_wps_start_entry(DBusMessage *message, char *key,
DBusMessageIter *entry_iter,
struct wps_start_params *params,
DBusMessage **reply)
{
if (os_strcmp(key, "Role") == 0)
return wpas_dbus_handler_wps_role(message, entry_iter,
params, reply);
else if (os_strcmp(key, "Type") == 0)
return wpas_dbus_handler_wps_type(message, entry_iter,
params, reply);
else if (os_strcmp(key, "Bssid") == 0)
return wpas_dbus_handler_wps_bssid(message, entry_iter,
params, reply);
else if (os_strcmp(key, "Pin") == 0)
return wpas_dbus_handler_wps_pin(message, entry_iter,
params, reply);
#ifdef CONFIG_P2P
else if (os_strcmp(key, "P2PDeviceAddress") == 0)
return wpas_dbus_handler_wps_p2p_dev_addr(message, entry_iter,
params, reply);
#endif /* CONFIG_P2P */
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - unknown key %s", key);
*reply = wpas_dbus_error_invalid_args(message, key);
return -1;
}
/**
* wpas_dbus_handler_wps_start - Start WPS configuration
* @message: Pointer to incoming dbus message
* @wpa_s: %wpa_supplicant data structure
* Returns: DBus message dictionary on success or DBus error on failure
*
* Handler for "Start" method call. DBus dictionary argument contains
* information about role (enrollee or registrar), authorization method
* (pin or push button) and optionally pin and bssid. Returned message
* has a dictionary argument which may contain newly generated pin (optional).
*/
DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
struct wpa_supplicant *wpa_s)
{
DBusMessage *reply = NULL;
DBusMessageIter iter, dict_iter, entry_iter;
struct wps_start_params params;
char *key;
char npin[9] = { '\0' };
int ret;
os_memset(&params, 0, sizeof(params));
dbus_message_iter_init(message, &iter);
dbus_message_iter_recurse(&iter, &dict_iter);
while (dbus_message_iter_get_arg_type(&dict_iter) ==
DBUS_TYPE_DICT_ENTRY) {
dbus_message_iter_recurse(&dict_iter, &entry_iter);
dbus_message_iter_get_basic(&entry_iter, &key);
dbus_message_iter_next(&entry_iter);
if (wpas_dbus_handler_wps_start_entry(message, key,
&entry_iter,
&params, &reply))
return reply;
dbus_message_iter_next(&dict_iter);
}
#ifdef CONFIG_AP
if (wpa_s->ap_iface && params.type == 1) {
if (params.pin == NULL) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start - Pin required for registrar role");
return wpas_dbus_error_invalid_args(
message, "Pin required for registrar role.");
}
ret = wpa_supplicant_ap_wps_pin(wpa_s,
params.bssid,
params.pin,
npin, sizeof(npin), 0);
} else if (wpa_s->ap_iface) {
ret = wpa_supplicant_ap_wps_pbc(wpa_s,
params.bssid,
params.p2p_dev_addr);
} else
#endif /* CONFIG_AP */
if (params.role == 0) {
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Role not specified");
return wpas_dbus_error_invalid_args(message,
"Role not specified");
} else if (params.role == 2) {
if (params.pin == NULL) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start - Pin required for registrar role");
return wpas_dbus_error_invalid_args(
message, "Pin required for registrar role.");
}
ret = wpas_wps_start_reg(wpa_s, params.bssid, params.pin,
NULL);
} else if (params.type == 0) {
wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Type not specified");
return wpas_dbus_error_invalid_args(message,
"Type not specified");
} else if (params.type == 1) {
ret = wpas_wps_start_pin(wpa_s, params.bssid,
params.pin, 0,
DEV_PW_DEFAULT);
if (ret > 0) {
ret = os_snprintf(npin, sizeof(npin), "%08d", ret);
if (os_snprintf_error(sizeof(npin), ret))
return wpas_dbus_error_unknown_error(
message, "invalid PIN");
}
} else {
ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0, 0);
}
if (ret < 0) {
wpa_printf(MSG_DEBUG,
"dbus: WPS.Start wpas_wps_failed in role %s and key %s",
(params.role == 1 ? "enrollee" : "registrar"),
(params.type == 0 ? "" :
(params.type == 1 ? "pin" : "pbc")));
return wpas_dbus_error_unknown_error(message,
"WPS start failed");
}
reply = dbus_message_new_method_return(message);
if (!reply)
return wpas_dbus_error_no_memory(message);
dbus_message_iter_init_append(reply, &iter);
if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
(os_strlen(npin) > 0 &&
!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) ||
!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
dbus_message_unref(reply);
return wpas_dbus_error_no_memory(message);
}
return reply;
}
/**
* wpas_dbus_handler_wps_cancel - Cancel ongoing WPS configuration
* @message: Pointer to incoming dbus message
* @wpa_s: %wpa_supplicant data structure
* Returns: NULL on success or DBus error on failure
*
* Handler for "Cancel" method call. Returns NULL if WPS cancel successful
* or DBus error on WPS cancel failure
*/
DBusMessage * wpas_dbus_handler_wps_cancel(DBusMessage *message,
struct wpa_supplicant *wpa_s)
{
if (wpas_wps_cancel(wpa_s))
return wpas_dbus_error_unknown_error(message,
"WPS cancel failed");
return NULL;
}
/**
* wpas_dbus_getter_process_credentials - Check if credentials are processed
* @message: Pointer to incoming dbus message
* @wpa_s: %wpa_supplicant data structure
* Returns: TRUE on success, FALSE on failure
*
* Getter for "ProcessCredentials" property. Returns returned boolean will be
* true if wps_cred_processing configuration field is not equal to 1 or false
* if otherwise.
*/
dbus_bool_t wpas_dbus_getter_process_credentials(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_bool_t process = wpa_s->conf->wps_cred_processing != 1;
return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
&process, error);
}
/**
* wpas_dbus_setter_process_credentials - Set credentials_processed conf param
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Setter for "ProcessCredentials" property. Sets credentials_processed on 2
* if boolean argument is true or on 1 if otherwise.
*/
dbus_bool_t wpas_dbus_setter_process_credentials(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_bool_t process_credentials, old_pc;
if (!wpa_s->dbus_new_path)
return FALSE;
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
&process_credentials))
return FALSE;
old_pc = wpa_s->conf->wps_cred_processing != 1;
wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
wpa_dbus_mark_property_changed(wpa_s->global->dbus,
wpa_s->dbus_new_path,
WPAS_DBUS_NEW_IFACE_WPS,
"ProcessCredentials");
return TRUE;
}
/**
* wpas_dbus_getter_config_methods - Get current WPS configuration methods
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Getter for "ConfigMethods" property. Returned boolean will be true if
* providing the relevant string worked, or false otherwise.
*/
dbus_bool_t wpas_dbus_getter_config_methods(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
return wpas_dbus_string_property_getter(iter,
wpa_s->conf->config_methods,
error);
}
/**
* wpas_dbus_setter_config_methods - Set WPS configuration methods
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Setter for "ConfigMethods" property. Sets the methods string, apply such
* change and returns true on success. Returns false otherwise.
*/
dbus_bool_t wpas_dbus_setter_config_methods(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *methods, *new_methods;
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
&methods))
return FALSE;
new_methods = os_strdup(methods);
if (!new_methods)
return FALSE;
os_free(wpa_s->conf->config_methods);
wpa_s->conf->config_methods = new_methods;
wpa_s->conf->changed_parameters |= CFG_CHANGED_CONFIG_METHODS;
wpa_supplicant_update_config(wpa_s);
return TRUE;
}
/**
* wpas_dbus_getter_wps_device_name - Get current WPS device name
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Getter for "DeviceName" property.
*/
dbus_bool_t wpas_dbus_getter_wps_device_name(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
return wpas_dbus_string_property_getter(iter, wpa_s->conf->device_name,
error);
}
/**
* wpas_dbus_setter_wps_device_name - Set current WPS device name
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Setter for "DeviceName" property.
*/
dbus_bool_t wpas_dbus_setter_wps_device_name(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *methods, *devname;
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
&methods))
return FALSE;
if (os_strlen(methods) > WPS_DEV_NAME_MAX_LEN)
return FALSE;
devname = os_strdup(methods);
if (!devname)
return FALSE;
os_free(wpa_s->conf->device_name);
wpa_s->conf->device_name = devname;
wpa_s->conf->changed_parameters |= CFG_CHANGED_DEVICE_NAME;
wpa_supplicant_update_config(wpa_s);
return TRUE;
}
/**
* wpas_dbus_getter_wps_manufacturer - Get current manufacturer name
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Getter for "Manufacturer" property.
*/
dbus_bool_t wpas_dbus_getter_wps_manufacturer(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
return wpas_dbus_string_property_getter(iter, wpa_s->conf->manufacturer,
error);
}
/**
* wpas_dbus_setter_wps_manufacturer - Set current manufacturer name
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Setter for "Manufacturer" property.
*/
dbus_bool_t wpas_dbus_setter_wps_manufacturer(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *methods, *manufacturer;
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
&methods))
return FALSE;
if (os_strlen(methods) > WPS_MANUFACTURER_MAX_LEN)
return FALSE;
manufacturer = os_strdup(methods);
if (!manufacturer)
return FALSE;
os_free(wpa_s->conf->manufacturer);
wpa_s->conf->manufacturer = manufacturer;
wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
wpa_supplicant_update_config(wpa_s);
return TRUE;
}
/**
* wpas_dbus_getter_wps_device_model_name - Get current device model name
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Getter for "ModelName" property.
*/
dbus_bool_t wpas_dbus_getter_wps_device_model_name(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
return wpas_dbus_string_property_getter(iter, wpa_s->conf->model_name,
error);
}
/**
* wpas_dbus_setter_wps_device_model_name - Set current device model name
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Setter for "ModelName" property.
*/
dbus_bool_t wpas_dbus_setter_wps_device_model_name(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *methods, *model_name;
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
&methods))
return FALSE;
if (os_strlen(methods) > WPS_MODEL_NAME_MAX_LEN)
return FALSE;
model_name = os_strdup(methods);
if (!model_name)
return FALSE;
os_free(wpa_s->conf->model_name);
wpa_s->conf->model_name = model_name;
wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
wpa_supplicant_update_config(wpa_s);
return TRUE;
}
/**
* wpas_dbus_getter_wps_device_model_number - Get current device model number
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Getter for "ModelNumber" property.
*/
dbus_bool_t wpas_dbus_getter_wps_device_model_number(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
return wpas_dbus_string_property_getter(iter, wpa_s->conf->model_number,
error);
}
/**
* wpas_dbus_setter_wps_device_model_number - Set current device model number
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Setter for "ModelNumber" property.
*/
dbus_bool_t wpas_dbus_setter_wps_device_model_number(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *methods, *model_number;
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
&methods))
return FALSE;
if (os_strlen(methods) > WPS_MODEL_NUMBER_MAX_LEN)
return FALSE;
model_number = os_strdup(methods);
if (!model_number)
return FALSE;
os_free(wpa_s->conf->model_number);
wpa_s->conf->model_number = model_number;
wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
wpa_supplicant_update_config(wpa_s);
return TRUE;
}
/**
* wpas_dbus_getter_wps_device_serial_number - Get current device serial number
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Getter for "SerialNumber" property.
*/
dbus_bool_t wpas_dbus_getter_wps_device_serial_number(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
return wpas_dbus_string_property_getter(iter,
wpa_s->conf->serial_number,
error);
}
/**
* wpas_dbus_setter_wps_device_serial_number - Set current device serial number
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Setter for "SerialNumber" property.
*/
dbus_bool_t wpas_dbus_setter_wps_device_serial_number(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *methods, *serial_number;
if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
&methods))
return FALSE;
if (os_strlen(methods) > WPS_SERIAL_NUMBER_MAX_LEN)
return FALSE;
serial_number = os_strdup(methods);
if (!serial_number)
return FALSE;
os_free(wpa_s->conf->serial_number);
wpa_s->conf->serial_number = serial_number;
wpa_s->conf->changed_parameters |= CFG_CHANGED_WPS_STRING;
wpa_supplicant_update_config(wpa_s);
return TRUE;
}
/**
* wpas_dbus_getter_wps_device_device_type - Get current device type
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Getter for "DeviceType" property.
*/
dbus_bool_t wpas_dbus_getter_wps_device_device_type(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
(char *)
wpa_s->conf->device_type,
WPS_DEV_TYPE_LEN, error)) {
dbus_set_error(error, DBUS_ERROR_FAILED,
"%s: error constructing reply", __func__);
return FALSE;
}
return TRUE;
}
/**
* wpas_dbus_setter_wps_device_device_type - Set current device type
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
* @user_data: Function specific data
* Returns: TRUE on success, FALSE on failure
*
* Setter for "DeviceType" property.
*/
dbus_bool_t wpas_dbus_setter_wps_device_device_type(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
u8 *dev_type;
int dev_len;
DBusMessageIter variant, array_iter;
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
return FALSE;
dbus_message_iter_recurse(iter, &variant);
if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
return FALSE;
dbus_message_iter_recurse(&variant, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &dev_type, &dev_len);
if (dev_len != WPS_DEV_TYPE_LEN)
return FALSE;
os_memcpy(wpa_s->conf->device_type, dev_type, WPS_DEV_TYPE_LEN);
wpa_s->conf->changed_parameters |= CFG_CHANGED_DEVICE_TYPE;
wpa_supplicant_update_config(wpa_s);
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
/*
* WPA Supplicant / dbus-based control interface
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_DBUS_CTRL_H
#define WPA_DBUS_CTRL_H
#include <dbus/dbus.h>
typedef DBusMessage * (*WPADBusMethodHandler)(DBusMessage *message,
void *user_data);
typedef void (*WPADBusArgumentFreeFunction)(void *handler_arg);
struct wpa_dbus_property_desc;
typedef dbus_bool_t (*WPADBusPropertyAccessor)(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data);
#define DECLARE_ACCESSOR(f) \
dbus_bool_t f(const struct wpa_dbus_property_desc *property_desc, \
DBusMessageIter *iter, DBusError *error, void *user_data)
struct wpa_dbus_object_desc {
DBusConnection *connection;
char *path;
/* list of methods, properties and signals registered with object */
const struct wpa_dbus_method_desc *methods;
const struct wpa_dbus_signal_desc *signals;
const struct wpa_dbus_property_desc *properties;
/* property changed flags */
u8 *prop_changed_flags;
/* argument for method handlers and properties
* getter and setter functions */
void *user_data;
/* function used to free above argument */
WPADBusArgumentFreeFunction user_data_free_func;
};
enum dbus_arg_direction { ARG_IN, ARG_OUT };
struct wpa_dbus_argument {
char *name;
char *type;
enum dbus_arg_direction dir;
};
#define END_ARGS { NULL, NULL, ARG_IN }
/**
* struct wpa_dbus_method_desc - DBus method description
*/
struct wpa_dbus_method_desc {
/* method name */
const char *dbus_method;
/* method interface */
const char *dbus_interface;
/* method handling function */
WPADBusMethodHandler method_handler;
/* array of arguments */
struct wpa_dbus_argument args[4];
};
/**
* struct wpa_dbus_signal_desc - DBus signal description
*/
struct wpa_dbus_signal_desc {
/* signal name */
const char *dbus_signal;
/* signal interface */
const char *dbus_interface;
/* array of arguments */
struct wpa_dbus_argument args[4];
};
/**
* struct wpa_dbus_property_desc - DBus property description
*/
struct wpa_dbus_property_desc {
/* property name */
const char *dbus_property;
/* property interface */
const char *dbus_interface;
/* property type signature in DBus type notation */
const char *type;
/* property getter function */
WPADBusPropertyAccessor getter;
/* property setter function */
WPADBusPropertyAccessor setter;
/* other data */
const char *data;
};
#define WPAS_DBUS_OBJECT_PATH_MAX 150
#define WPAS_DBUS_INTERFACE_MAX 150
#define WPAS_DBUS_METHOD_SIGNAL_PROP_MAX 50
#define WPAS_DBUS_AUTH_MODE_MAX 64
#define WPA_DBUS_INTROSPECTION_INTERFACE "org.freedesktop.DBus.Introspectable"
#define WPA_DBUS_INTROSPECTION_METHOD "Introspect"
#define WPA_DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
#define WPA_DBUS_PROPERTIES_GET "Get"
#define WPA_DBUS_PROPERTIES_SET "Set"
#define WPA_DBUS_PROPERTIES_GETALL "GetAll"
void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc);
int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface, char *dbus_path,
char *dbus_service,
struct wpa_dbus_object_desc *obj_desc);
int wpa_dbus_register_object_per_iface(
struct wpas_dbus_priv *ctrl_iface,
const char *path, const char *ifname,
struct wpa_dbus_object_desc *obj_desc);
int wpa_dbus_unregister_object_per_iface(
struct wpas_dbus_priv *ctrl_iface,
const char *path);
dbus_bool_t wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface,
const char *path,
const char *interface,
DBusMessageIter *iter);
void wpa_dbus_flush_all_changed_properties(DBusConnection *con);
void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
const char *path);
void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface,
const char *path, const char *interface,
const char *property);
DBusMessage * wpa_dbus_introspect(DBusMessage *message,
struct wpa_dbus_object_desc *obj_dsc);
char * wpas_dbus_new_decompose_object_path(const char *path, const char *sep,
char **item);
DBusMessage *wpas_dbus_reply_new_from_error(DBusMessage *message,
DBusError *error,
const char *fallback_name,
const char *fallback_string);
#endif /* WPA_DBUS_CTRL_H */

View File

@ -0,0 +1,286 @@
/*
* wpa_supplicant - D-Bus introspection
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
* Copyright (c) 2010, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "utils/list.h"
#include "utils/wpabuf.h"
#include "dbus_common_i.h"
#include "dbus_new_helpers.h"
struct interfaces {
struct dl_list list;
char *dbus_interface;
struct wpabuf *xml;
};
static struct interfaces * add_interface(struct dl_list *list,
const char *dbus_interface)
{
struct interfaces *iface;
dl_list_for_each(iface, list, struct interfaces, list) {
if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
return iface; /* already in the list */
}
iface = os_zalloc(sizeof(struct interfaces));
if (!iface)
return NULL;
iface->dbus_interface = os_strdup(dbus_interface);
iface->xml = wpabuf_alloc(15000);
if (iface->dbus_interface == NULL || iface->xml == NULL) {
os_free(iface->dbus_interface);
wpabuf_free(iface->xml);
os_free(iface);
return NULL;
}
wpabuf_printf(iface->xml, "<interface name=\"%s\">", dbus_interface);
dl_list_add_tail(list, &iface->list);
return iface;
}
static void add_arg(struct wpabuf *xml, const char *name, const char *type,
const char *direction)
{
wpabuf_printf(xml, "<arg name=\"%s\"", name);
if (type)
wpabuf_printf(xml, " type=\"%s\"", type);
if (direction)
wpabuf_printf(xml, " direction=\"%s\"", direction);
wpabuf_put_str(xml, "/>");
}
static void add_entry(struct wpabuf *xml, const char *type, const char *name,
const struct wpa_dbus_argument *args, int include_dir)
{
const struct wpa_dbus_argument *arg;
if (args == NULL || args->name == NULL) {
wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
return;
}
wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
for (arg = args; arg && arg->name; arg++) {
add_arg(xml, arg->name, arg->type,
include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
NULL);
}
wpabuf_printf(xml, "</%s>", type);
}
static void add_property(struct wpabuf *xml,
const struct wpa_dbus_property_desc *dsc)
{
wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" "
"access=\"%s%s\"/>",
dsc->dbus_property, dsc->type,
dsc->getter ? "read" : "",
dsc->setter ? "write" : "");
}
static void extract_interfaces_methods(
struct dl_list *list, const struct wpa_dbus_method_desc *methods)
{
const struct wpa_dbus_method_desc *dsc;
struct interfaces *iface;
for (dsc = methods; dsc && dsc->dbus_method; dsc++) {
iface = add_interface(list, dsc->dbus_interface);
if (iface)
add_entry(iface->xml, "method", dsc->dbus_method,
dsc->args, 1);
}
}
static void extract_interfaces_signals(
struct dl_list *list, const struct wpa_dbus_signal_desc *signals)
{
const struct wpa_dbus_signal_desc *dsc;
struct interfaces *iface;
for (dsc = signals; dsc && dsc->dbus_signal; dsc++) {
iface = add_interface(list, dsc->dbus_interface);
if (iface)
add_entry(iface->xml, "signal", dsc->dbus_signal,
dsc->args, 0);
}
}
static void extract_interfaces_properties(
struct dl_list *list, const struct wpa_dbus_property_desc *properties)
{
const struct wpa_dbus_property_desc *dsc;
struct interfaces *iface;
for (dsc = properties; dsc && dsc->dbus_property; dsc++) {
iface = add_interface(list, dsc->dbus_interface);
if (iface)
add_property(iface->xml, dsc);
}
}
/**
* extract_interfaces - Extract interfaces from methods, signals and props
* @list: Interface list to be filled
* @obj_dsc: Description of object from which interfaces will be extracted
*
* Iterates over all methods, signals, and properties registered with an
* object and collects all declared DBus interfaces and create interfaces'
* node in XML root node for each. Returned list elements contain interface
* name and XML node of corresponding interface.
*/
static void extract_interfaces(struct dl_list *list,
struct wpa_dbus_object_desc *obj_dsc)
{
extract_interfaces_methods(list, obj_dsc->methods);
extract_interfaces_signals(list, obj_dsc->signals);
extract_interfaces_properties(list, obj_dsc->properties);
}
static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
{
struct interfaces *iface, *n;
dl_list_for_each_safe(iface, n, list, struct interfaces, list) {
if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) {
wpabuf_put_buf(xml, iface->xml);
wpabuf_put_str(xml, "</interface>");
} else {
wpa_printf(MSG_DEBUG,
"dbus: Not enough room for add_interfaces inspect data: tailroom %u, add %u",
(unsigned int) wpabuf_tailroom(xml),
(unsigned int) wpabuf_len(iface->xml));
}
dl_list_del(&iface->list);
wpabuf_free(iface->xml);
os_free(iface->dbus_interface);
os_free(iface);
}
}
static void add_child_nodes(struct wpabuf *xml, DBusConnection *con,
const char *path)
{
char **children;
int i;
/* add child nodes to introspection tree */
dbus_connection_list_registered(con, path, &children);
for (i = 0; children[i]; i++)
wpabuf_printf(xml, "<node name=\"%s\"/>", children[i]);
dbus_free_string_array(children);
}
static void add_introspectable_interface(struct wpabuf *xml)
{
wpabuf_printf(xml, "<interface name=\"%s\">"
"<method name=\"%s\">"
"<arg name=\"data\" type=\"s\" direction=\"out\"/>"
"</method>"
"</interface>",
WPA_DBUS_INTROSPECTION_INTERFACE,
WPA_DBUS_INTROSPECTION_METHOD);
}
static void add_properties_interface(struct wpabuf *xml)
{
wpabuf_printf(xml, "<interface name=\"%s\">",
WPA_DBUS_PROPERTIES_INTERFACE);
wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GET);
add_arg(xml, "interface", "s", "in");
add_arg(xml, "propname", "s", "in");
add_arg(xml, "value", "v", "out");
wpabuf_put_str(xml, "</method>");
wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GETALL);
add_arg(xml, "interface", "s", "in");
add_arg(xml, "props", "a{sv}", "out");
wpabuf_put_str(xml, "</method>");
wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_SET);
add_arg(xml, "interface", "s", "in");
add_arg(xml, "propname", "s", "in");
add_arg(xml, "value", "v", "in");
wpabuf_put_str(xml, "</method>");
wpabuf_put_str(xml, "</interface>");
}
static void add_wpas_interfaces(struct wpabuf *xml,
struct wpa_dbus_object_desc *obj_dsc)
{
struct dl_list ifaces;
dl_list_init(&ifaces);
extract_interfaces(&ifaces, obj_dsc);
add_interfaces(&ifaces, xml);
}
/**
* wpa_dbus_introspect - Responds for Introspect calls on object
* @message: Message with Introspect call
* @obj_dsc: Object description on which Introspect was called
* Returns: Message with introspection result XML string as only argument
*
* Iterates over all methods, signals and properties registered with
* object and generates introspection data for the object as XML string.
*/
DBusMessage * wpa_dbus_introspect(DBusMessage *message,
struct wpa_dbus_object_desc *obj_dsc)
{
DBusMessage *reply;
struct wpabuf *xml;
xml = wpabuf_alloc(30000);
if (xml == NULL)
return NULL;
wpabuf_put_str(xml, "<?xml version=\"1.0\"?>\n");
wpabuf_put_str(xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
wpabuf_put_str(xml, "<node>");
add_introspectable_interface(xml);
add_properties_interface(xml);
add_wpas_interfaces(xml, obj_dsc);
add_child_nodes(xml, obj_dsc->connection,
dbus_message_get_path(message));
wpabuf_put_str(xml, "</node>\n");
reply = dbus_message_new_method_return(message);
if (reply) {
const char *intro_str = wpabuf_head(xml);
dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
DBUS_TYPE_INVALID);
}
wpabuf_free(xml);
return reply;
}

View File

@ -0,0 +1,5 @@
[D-BUS Service]
Name=fi.w1.wpa_supplicant1
Exec=@BINDIR@/wpa_supplicant -u
User=root
SystemdService=wpa_supplicant.service

635
wpa_supplicant/defconfig Normal file
View File

@ -0,0 +1,635 @@
# Example wpa_supplicant build time configuration
#
# This file lists the configuration options that are used when building the
# wpa_supplicant binary. All lines starting with # are ignored. Configuration
# option lines must be commented out complete, if they are not to be included,
# i.e., just setting VARIABLE=n is not disabling that variable.
#
# This file is included in Makefile, so variables like CFLAGS and LIBS can also
# be modified from here. In most cases, these lines should use += in order not
# to override previous values of the variables.
# Uncomment following two lines and fix the paths if you have installed OpenSSL
# or GnuTLS in non-default location
#CFLAGS += -I/usr/local/openssl/include
#LIBS += -L/usr/local/openssl/lib
# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
# the kerberos files are not in the default include path. Following line can be
# used to fix build issues on such systems (krb5.h not found).
#CFLAGS += -I/usr/include/kerberos
# Driver interface for generic Linux wireless extensions
# Note: WEXT is deprecated in the current Linux kernel version and no new
# functionality is added to it. nl80211-based interface is the new
# replacement for WEXT and its use allows wpa_supplicant to properly control
# the driver to improve existing functionality like roaming and to support new
# functionality.
CONFIG_DRIVER_WEXT=y
# Driver interface for Linux drivers using the nl80211 kernel interface
CONFIG_DRIVER_NL80211=y
# QCA vendor extensions to nl80211
#CONFIG_DRIVER_NL80211_QCA=y
# driver_nl80211.c requires libnl. If you are compiling it yourself
# you may need to point hostapd to your version of libnl.
#
#CFLAGS += -I$<path to libnl include files>
#LIBS += -L$<path to libnl library files>
# Use libnl v2.0 (or 3.0) libraries.
#CONFIG_LIBNL20=y
# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
CONFIG_LIBNL32=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
#LIBS += -L/usr/local/lib
#LIBS_p += -L/usr/local/lib
#LIBS_c += -L/usr/local/lib
# Driver interface for Windows NDIS
#CONFIG_DRIVER_NDIS=y
#CFLAGS += -I/usr/include/w32api/ddk
#LIBS += -L/usr/local/lib
# For native build using mingw
#CONFIG_NATIVE_WINDOWS=y
# Additional directories for cross-compilation on Linux host for mingw target
#CFLAGS += -I/opt/mingw/mingw32/include/ddk
#LIBS += -L/opt/mingw/mingw32/lib
#CC=mingw32-gcc
# By default, driver_ndis uses WinPcap for low-level operations. This can be
# replaced with the following option which replaces WinPcap calls with NDISUIO.
# However, this requires that WZC is disabled (net stop wzcsvc) before starting
# wpa_supplicant.
# CONFIG_USE_NDISUIO=y
# Driver interface for wired Ethernet drivers
CONFIG_DRIVER_WIRED=y
# Driver interface for MACsec capable Qualcomm Atheros drivers
#CONFIG_DRIVER_MACSEC_QCA=y
# Driver interface for Linux MACsec drivers
CONFIG_DRIVER_MACSEC_LINUX=y
# Driver interface for the Broadcom RoboSwitch family
#CONFIG_DRIVER_ROBOSWITCH=y
# Driver interface for no driver (e.g., WPS ER only)
#CONFIG_DRIVER_NONE=y
# Solaris libraries
#LIBS += -lsocket -ldlpi -lnsl
#LIBS_c += -lsocket
# Enable IEEE 802.1X Supplicant (automatically included if any EAP method or
# MACsec is included)
CONFIG_IEEE8021X_EAPOL=y
# EAP-MD5
CONFIG_EAP_MD5=y
# EAP-MSCHAPv2
CONFIG_EAP_MSCHAPV2=y
# EAP-TLS
CONFIG_EAP_TLS=y
# EAL-PEAP
CONFIG_EAP_PEAP=y
# EAP-TTLS
CONFIG_EAP_TTLS=y
# EAP-FAST
CONFIG_EAP_FAST=y
# EAP-TEAP
# Note: The current EAP-TEAP implementation is experimental and should not be
# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
# of conflicting statements and missing details and the implementation has
# vendor specific workarounds for those and as such, may not interoperate with
# any other implementation. This should not be used for anything else than
# experimentation and interoperability testing until those issues has been
# resolved.
#CONFIG_EAP_TEAP=y
# EAP-GTC
CONFIG_EAP_GTC=y
# EAP-OTP
CONFIG_EAP_OTP=y
# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
#CONFIG_EAP_SIM=y
# Enable SIM simulator (Milenage) for EAP-SIM
#CONFIG_SIM_SIMULATOR=y
# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
#CONFIG_EAP_PSK=y
# EAP-pwd (secure authentication using only a password)
CONFIG_EAP_PWD=y
# EAP-PAX
CONFIG_EAP_PAX=y
# LEAP
CONFIG_EAP_LEAP=y
# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
#CONFIG_EAP_AKA=y
# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
# This requires CONFIG_EAP_AKA to be enabled, too.
#CONFIG_EAP_AKA_PRIME=y
# Enable USIM simulator (Milenage) for EAP-AKA
#CONFIG_USIM_SIMULATOR=y
# EAP-SAKE
CONFIG_EAP_SAKE=y
# EAP-GPSK
CONFIG_EAP_GPSK=y
# Include support for optional SHA256 cipher suite in EAP-GPSK
CONFIG_EAP_GPSK_SHA256=y
# EAP-TNC and related Trusted Network Connect support (experimental)
CONFIG_EAP_TNC=y
# Wi-Fi Protected Setup (WPS)
CONFIG_WPS=y
# Enable WPS external registrar functionality
#CONFIG_WPS_ER=y
# Disable credentials for an open network by default when acting as a WPS
# registrar.
#CONFIG_WPS_REG_DISABLE_OPEN=y
# Enable WPS support with NFC config method
#CONFIG_WPS_NFC=y
# EAP-IKEv2
CONFIG_EAP_IKEV2=y
# EAP-EKE
#CONFIG_EAP_EKE=y
# MACsec
CONFIG_MACSEC=y
# PKCS#12 (PFX) support (used to read private key and certificate file from
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
# engine.
CONFIG_SMARTCARD=y
# PC/SC interface for smartcards (USIM, GSM SIM)
# Enable this if EAP-SIM or EAP-AKA is included
#CONFIG_PCSC=y
# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
#CONFIG_HT_OVERRIDES=y
# Support VHT overrides (disable VHT, mask MCS rates, etc.)
#CONFIG_VHT_OVERRIDES=y
# Development testing
#CONFIG_EAPOL_TEST=y
# Select control interface backend for external programs, e.g, wpa_cli:
# unix = UNIX domain sockets (default for Linux/*BSD)
# udp = UDP sockets using localhost (127.0.0.1)
# udp6 = UDP IPv6 sockets using localhost (::1)
# named_pipe = Windows Named Pipe (default for Windows)
# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
# y = use default (backwards compatibility)
# If this option is commented out, control interface is not included in the
# build.
CONFIG_CTRL_IFACE=y
# Include support for GNU Readline and History Libraries in wpa_cli.
# When building a wpa_cli binary for distribution, please note that these
# libraries are licensed under GPL and as such, BSD license may not apply for
# the resulting binary.
#CONFIG_READLINE=y
# Include internal line edit mode in wpa_cli. This can be used as a replacement
# for GNU Readline to provide limited command line editing and history support.
#CONFIG_WPA_CLI_EDIT=y
# Remove debugging code that is printing out debug message to stdout.
# This can be used to reduce the size of the wpa_supplicant considerably
# if debugging code is not needed. The size reduction can be around 35%
# (e.g., 90 kB).
#CONFIG_NO_STDOUT_DEBUG=y
# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
# 35-50 kB in code size.
#CONFIG_NO_WPA=y
# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
# This option can be used to reduce code size by removing support for
# converting ASCII passphrases into PSK. If this functionality is removed, the
# PSK can only be configured as the 64-octet hexstring (e.g., from
# wpa_passphrase). This saves about 0.5 kB in code size.
#CONFIG_NO_WPA_PASSPHRASE=y
# Simultaneous Authentication of Equals (SAE), WPA3-Personal
CONFIG_SAE=y
# Disable scan result processing (ap_scan=1) to save code size by about 1 kB.
# This can be used if ap_scan=1 mode is never enabled.
#CONFIG_NO_SCAN_PROCESSING=y
# Select configuration backend:
# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
# path is given on command line, not here; this option is just used to
# select the backend that allows configuration files to be used)
# winreg = Windows registry (see win_example.reg for an example)
CONFIG_BACKEND=file
# Remove configuration write functionality (i.e., to allow the configuration
# file to be updated based on runtime configuration changes). The runtime
# configuration can still be changed, the changes are just not going to be
# persistent over restarts. This option can be used to reduce code size by
# about 3.5 kB.
#CONFIG_NO_CONFIG_WRITE=y
# Remove support for configuration blobs to reduce code size by about 1.5 kB.
#CONFIG_NO_CONFIG_BLOBS=y
# Select program entry point implementation:
# main = UNIX/POSIX like main() function (default)
# main_winsvc = Windows service (read parameters from registry)
# main_none = Very basic example (development use only)
#CONFIG_MAIN=main
# Select wrapper for operating system and C library specific functions
# unix = UNIX/POSIX like systems (default)
# win32 = Windows systems
# none = Empty template
#CONFIG_OS=unix
# Select event loop implementation
# eloop = select() loop (default)
# eloop_win = Windows events and WaitForMultipleObject() loop
#CONFIG_ELOOP=eloop
# Should we use poll instead of select? Select is used by default.
#CONFIG_ELOOP_POLL=y
# Should we use epoll instead of select? Select is used by default.
#CONFIG_ELOOP_EPOLL=y
# Should we use kqueue instead of select? Select is used by default.
#CONFIG_ELOOP_KQUEUE=y
# Select layer 2 packet implementation
# linux = Linux packet socket (default)
# pcap = libpcap/libdnet/WinPcap
# freebsd = FreeBSD libpcap
# winpcap = WinPcap with receive thread
# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
# none = Empty template
#CONFIG_L2_PACKET=linux
# Disable Linux packet socket workaround applicable for station interface
# in a bridge for EAPOL frames. This should be uncommented only if the kernel
# is known to not have the regression issue in packet socket behavior with
# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
#CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
# Support Operating Channel Validation
#CONFIG_OCV=y
# Select TLS implementation
# openssl = OpenSSL (default)
# gnutls = GnuTLS
# internal = Internal TLSv1 implementation (experimental)
# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
# none = Empty template
#CONFIG_TLS=openssl
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
# can be enabled to get a stronger construction of messages when block ciphers
# are used. It should be noted that some existing TLS v1.0 -based
# implementation may not be compatible with TLS v1.1 message (ClientHello is
# sent prior to negotiating which version will be used)
#CONFIG_TLSV11=y
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
# can be enabled to enable use of stronger crypto algorithms. It should be
# noted that some existing TLS v1.0 -based implementation may not be compatible
# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
# will be used)
#CONFIG_TLSV12=y
# Select which ciphers to use by default with OpenSSL if the user does not
# specify them.
#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
# If CONFIG_TLS=internal is used, additional library and include paths are
# needed for LibTomMath. Alternatively, an integrated, minimal version of
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
# and drawbacks of this option.
#CONFIG_INTERNAL_LIBTOMMATH=y
#ifndef CONFIG_INTERNAL_LIBTOMMATH
#LTM_PATH=/usr/src/libtommath-0.39
#CFLAGS += -I$(LTM_PATH)
#LIBS += -L$(LTM_PATH)
#LIBS_p += -L$(LTM_PATH)
#endif
# At the cost of about 4 kB of additional binary size, the internal LibTomMath
# can be configured to include faster routines for exptmod, sqr, and div to
# speed up DH and RSA calculation considerably
#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
# This is only for Windows builds and requires WMI-related header files and
# WbemUuid.Lib from Platform SDK even when building with MinGW.
#CONFIG_NDIS_EVENTS_INTEGRATED=y
#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
# Add support for new DBus control interface
# (fi.w1.wpa_supplicant1)
CONFIG_CTRL_IFACE_DBUS_NEW=y
# Add introspection support for new DBus control interface
CONFIG_CTRL_IFACE_DBUS_INTRO=y
# Add support for loading EAP methods dynamically as shared libraries.
# When this option is enabled, each EAP method can be either included
# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
# be loaded in the beginning of the wpa_supplicant configuration file
# (see load_dynamic_eap parameter in the example file) before being used in
# the network blocks.
#
# Note that some shared parts of EAP methods are included in the main program
# and in order to be able to use dynamic EAP methods using these parts, the
# main program must have been build with the EAP method enabled (=y or =dyn).
# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
# unless at least one of them was included in the main build to force inclusion
# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
# in the main build to be able to load these methods dynamically.
#
# Please also note that using dynamic libraries will increase the total binary
# size. Thus, it may not be the best option for targets that have limited
# amount of memory/flash.
#CONFIG_DYNAMIC_EAP_METHODS=y
# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
CONFIG_IEEE80211R=y
# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
CONFIG_DEBUG_FILE=y
# Send debug messages to syslog instead of stdout
CONFIG_DEBUG_SYSLOG=y
# Set syslog facility for debug messages
#CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
# Add support for sending all debug messages (regardless of debug verbosity)
# to the Linux kernel tracing facility. This helps debug the entire stack by
# making it easy to record everything happening from the driver up into the
# same file, e.g., using trace-cmd.
#CONFIG_DEBUG_LINUX_TRACING=y
# Add support for writing debug log to Android logcat instead of standard
# output
#CONFIG_ANDROID_LOG=y
# Enable privilege separation (see README 'Privilege separation' for details)
#CONFIG_PRIVSEP=y
# Enable mitigation against certain attacks against TKIP by delaying Michael
# MIC error reports by a random amount of time between 0 and 60 seconds
#CONFIG_DELAYED_MIC_ERROR_REPORT=y
# Enable tracing code for developer debugging
# This tracks use of memory allocations and other registrations and reports
# incorrect use with a backtrace of call (or allocation) location.
#CONFIG_WPA_TRACE=y
# For BSD, uncomment these.
#LIBS += -lexecinfo
#LIBS_p += -lexecinfo
#LIBS_c += -lexecinfo
# Use libbfd to get more details for developer debugging
# This enables use of libbfd to get more detailed symbols for the backtraces
# generated by CONFIG_WPA_TRACE=y.
#CONFIG_WPA_TRACE_BFD=y
# For BSD, uncomment these.
#LIBS += -lbfd -liberty -lz
#LIBS_p += -lbfd -liberty -lz
#LIBS_c += -lbfd -liberty -lz
# wpa_supplicant depends on strong random number generation being available
# from the operating system. os_get_random() function is used to fetch random
# data when needed, e.g., for key generation. On Linux and BSD systems, this
# works by reading /dev/urandom. It should be noted that the OS entropy pool
# needs to be properly initialized before wpa_supplicant is started. This is
# important especially on embedded devices that do not have a hardware random
# number generator and may by default start up with minimal entropy available
# for random number generation.
#
# As a safety net, wpa_supplicant is by default trying to internally collect
# additional entropy for generating random data to mix in with the data fetched
# from the OS. This by itself is not considered to be very strong, but it may
# help in cases where the system pool is not initialized properly. However, it
# is very strongly recommended that the system pool is initialized with enough
# entropy either by using hardware assisted random number generator or by
# storing state over device reboots.
#
# wpa_supplicant can be configured to maintain its own entropy store over
# restarts to enhance random number generation. This is not perfect, but it is
# much more secure than using the same sequence of random numbers after every
# reboot. This can be enabled with -e<entropy file> command line option. The
# specified file needs to be readable and writable by wpa_supplicant.
#
# If the os_get_random() is known to provide strong random data (e.g., on
# Linux/BSD, the board in question is known to have reliable source of random
# data from /dev/urandom), the internal wpa_supplicant random pool can be
# disabled. This will save some in binary size and CPU use. However, this
# should only be considered for builds that are known to be used on devices
# that meet the requirements described above.
#CONFIG_NO_RANDOM_POOL=y
# Should we attempt to use the getrandom(2) call that provides more reliable
# yet secure randomness source than /dev/random on Linux 3.17 and newer.
# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
#CONFIG_GETRANDOM=y
# IEEE 802.11ac (Very High Throughput) support (mainly for AP mode)
CONFIG_IEEE80211AC=y
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
#CONFIG_WNM=y
# Interworking (IEEE 802.11u)
# This can be used to enable functionality to improve interworking with
# external networks (GAS/ANQP to learn more about the networks and network
# selection based on available credentials).
CONFIG_INTERWORKING=y
# Hotspot 2.0
CONFIG_HS20=y
# Enable interface matching in wpa_supplicant
#CONFIG_MATCH_IFACE=y
# Disable roaming in wpa_supplicant
#CONFIG_NO_ROAMING=y
# AP mode operations with wpa_supplicant
# This can be used for controlling AP mode operations with wpa_supplicant. It
# should be noted that this is mainly aimed at simple cases like
# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
# external RADIUS server can be supported with hostapd.
CONFIG_AP=y
# P2P (Wi-Fi Direct)
# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
# more information on P2P operations.
CONFIG_P2P=y
# Enable TDLS support
CONFIG_TDLS=y
# Wi-Fi Display
# This can be used to enable Wi-Fi Display extensions for P2P using an external
# program to control the additional information exchanges in the messages.
CONFIG_WIFI_DISPLAY=y
# Autoscan
# This can be used to enable automatic scan support in wpa_supplicant.
# See wpa_supplicant.conf for more information on autoscan usage.
#
# Enabling directly a module will enable autoscan support.
# For exponential module:
#CONFIG_AUTOSCAN_EXPONENTIAL=y
# For periodic module:
#CONFIG_AUTOSCAN_PERIODIC=y
# Password (and passphrase, etc.) backend for external storage
# These optional mechanisms can be used to add support for storing passwords
# and other secrets in external (to wpa_supplicant) location. This allows, for
# example, operating system specific key storage to be used
#
# External password backend for testing purposes (developer use)
#CONFIG_EXT_PASSWORD_TEST=y
# File-based backend to read passwords from an external file.
#CONFIG_EXT_PASSWORD_FILE=y
# Enable Fast Session Transfer (FST)
#CONFIG_FST=y
# Enable CLI commands for FST testing
#CONFIG_FST_TEST=y
# OS X builds. This is only for building eapol_test.
#CONFIG_OSX=y
# Automatic Channel Selection
# This will allow wpa_supplicant to pick the channel automatically when channel
# is set to "0".
#
# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
# to "channel=0". This would enable us to eventually add other ACS algorithms in
# similar way.
#
# Automatic selection is currently only done through initialization, later on
# we hope to do background checks to keep us moving to more ideal channels as
# time goes by. ACS is currently only supported through the nl80211 driver and
# your driver must have survey dump capability that is filled by the driver
# during scanning.
#
# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
# a newly to create wpa_supplicant.conf variable acs_num_scans.
#
# Supported ACS drivers:
# * ath9k
# * ath5k
# * ath10k
#
# For more details refer to:
# http://wireless.kernel.org/en/users/Documentation/acs
#CONFIG_ACS=y
# Support Multi Band Operation
#CONFIG_MBO=y
# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
#CONFIG_FILS=y
# FILS shared key authentication with PFS
#CONFIG_FILS_SK_PFS=y
# Support RSN on IBSS networks
# This is needed to be able to use mode=1 network profile with proto=RSN and
# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
CONFIG_IBSS_RSN=y
# External PMKSA cache control
# This can be used to enable control interface commands that allow the current
# PMKSA cache entries to be fetched and new entries to be added.
#CONFIG_PMKSA_CACHE_EXTERNAL=y
# Mesh Networking (IEEE 802.11s)
#CONFIG_MESH=y
# Background scanning modules
# These can be used to request wpa_supplicant to perform background scanning
# operations for roaming within an ESS (same SSID). See the bgscan parameter in
# the wpa_supplicant.conf file for more details.
# Periodic background scans based on signal strength
CONFIG_BGSCAN_SIMPLE=y
# Learn channels used by the network and try to avoid bgscans on other
# channels (experimental)
#CONFIG_BGSCAN_LEARN=y
# Opportunistic Wireless Encryption (OWE)
# Experimental implementation of draft-harkins-owe-07.txt
#CONFIG_OWE=y
# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect)
CONFIG_DPP=y
# DPP version 2 support
CONFIG_DPP2=y
# DPP version 3 support (experimental and still changing; do not enable for
# production use)
#CONFIG_DPP3=y
# Wired equivalent privacy (WEP)
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
# considered secure. It should not be used for anything anymore. The
# functionality needed to use WEP is available in the current wpa_supplicant
# release under this optional build parameter. This functionality is subject to
# be completely removed in a future release.
#CONFIG_WEP=y
# Remove all TKIP functionality
# TKIP is an old cryptographic data confidentiality algorithm that is not
# considered secure. It should not be used anymore for anything else than a
# backwards compatibility option as a group cipher when connecting to APs that
# use WPA+WPA2 mixed mode. For now, the default wpa_supplicant build includes
# support for this by default, but that functionality is subject to be removed
# in the future.
#CONFIG_NO_TKIP=y
# Pre-Association Security Negotiation (PASN)
# Experimental implementation based on IEEE P802.11z/D2.6 and the protocol
# design is still subject to change. As such, this should not yet be enabled in
# production use.
#CONFIG_PASN=y

View File

@ -0,0 +1,28 @@
all: man html pdf
FILES += wpa_background
FILES += wpa_cli
FILES += wpa_gui
FILES += wpa_passphrase
FILES += wpa_priv
FILES += wpa_supplicant.conf
FILES += wpa_supplicant
FILES += eapol_test
man:
for i in $(FILES); do docbook2man $$i.sgml; done
html:
for i in $(FILES); do docbook2html $$i.sgml && \
mv index.html $$i.html; done
pdf:
for i in $(FILES); do docbook2pdf $$i.sgml; done
clean:
rm -f wpa_background.8 wpa_cli.8 wpa_gui.8 wpa_passphrase.8 wpa_priv.8 wpa_supplicant.8 eapol_test.8
rm -f wpa_supplicant.conf.5
rm -f manpage.links manpage.refs
rm -f $(FILES:%=%.pdf)
rm -f $(FILES:%=%.html)

View File

@ -0,0 +1,209 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>07 August 2019</date>
</refentryinfo>
<refmeta>
<refentrytitle>eapol_test</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>eapol_test</refname>
<refpurpose>EAP peer and RADIUS client testing</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>eapol_test</command>
<arg>-nWS</arg>
<arg>-c<replaceable>config file</replaceable></arg>
<arg>-a<replaceable>server IP address</replaceable></arg>
<arg>-A<replaceable>client IP address</replaceable></arg>
<arg>-p<replaceable>UDP port</replaceable></arg>
<arg>-s<replaceable>shared secret</replaceable></arg>
<arg>-r<replaceable>re-authentications</replaceable></arg>
<arg>-t<replaceable>timeout</replaceable></arg>
<arg>-C<replaceable>Connect-Info</replaceable></arg>
<arg>-M<replaceable>MAC address</replaceable></arg>
<arg>-o<replaceable>file</replaceable></arg>
<arg>-N<replaceable>attr spec</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>eapol_test scard</command>
</cmdsynopsis>
<cmdsynopsis>
<command>eapol_test sim</command>
<arg>PIN</arg>
<arg>num triplets</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Overview</title>
<para>eapol_test is a program that links together the same EAP
peer implementation that wpa_supplicant is using and the RADIUS
authentication client code from hostapd. In addition, it has
minimal glue code to combine these two components in similar
ways to IEEE 802.1X/EAPOL Authenticator state machines. In other
words, it integrates IEEE 802.1X Authenticator (normally, an
access point) and IEEE 802.1X Supplicant (normally, a wireless
client) together to generate a single program that can be used to
test EAP methods without having to setup an access point and a
wireless client.</para>
<para>The main uses for eapol_test are in interoperability testing
of EAP methods against RADIUS servers and in development testing
for new EAP methods. It can be easily used to automate EAP testing
for interoperability and regression since the program can be run
from shell scripts without require additional test components apart
from a RADIUS server. For example, the automated EAP tests described
in eap_testing.txt are implemented with eapol_test. Similarly,
eapol_test could be used to implement an automated regression
test suite for a RADIUS authentication server.</para>
<para>As an example:</para>
<blockquote><programlisting>
eapol_test -ctest.conf -a127.0.0.1 -p1812 -ssecret -r1
</programlisting></blockquote>
<para>tries to complete EAP authentication based on the network
configuration from test.conf against the RADIUS server running
on the local host. A re-authentication is triggered to test fast
re-authentication. The configuration file uses the same format for
network blocks as wpa_supplicant.</para>
</refsect1>
<refsect1>
<title>Command Arguments</title>
<variablelist>
<varlistentry>
<term>-c configuration file path</term>
<listitem><para>A configuration to use. The configuration should
use the same format for network blocks as wpa_supplicant.
</para></listitem>
</varlistentry>
<varlistentry>
<term>-a AS address</term>
<listitem><para>IP address of the authentication server. The
default is '127.0.0.1'.</para></listitem>
</varlistentry>
<varlistentry>
<term>-A client address</term>
<listitem><para>IP address of the client. The default is to
select an address automatically.</para></listitem>
</varlistentry>
<varlistentry>
<term>-p AS port</term>
<listitem><para>UDP port of the authentication server. The
default is '1812'.</para></listitem>
</varlistentry>
<varlistentry>
<term>-s AS secret</term>
<listitem><para>Shared secret with the authentication server.
The default is 'radius'.</para></listitem>
</varlistentry>
<varlistentry>
<term>-r count</term>
<listitem><para>Number of reauthentications.</para></listitem>
</varlistentry>
<varlistentry>
<term>-t timeout</term>
<listitem><para>Timeout in seconds. The default is 30.</para></listitem>
</varlistentry>
<varlistentry>
<term>-C info</term>
<listitem><para>RADIUS Connect-Info. The default is
'CONNECT 11Mbps 802.11b'.</para></listitem>
</varlistentry>
<varlistentry>
<term>-M mac address</term>
<listitem><para>Client MAC address (Calling-Station-Id). The
default is '02:00:00:00:00:01'.</para></listitem>
</varlistentry>
<varlistentry>
<term>-o file</term>
<listitem><para>Location to write out server certificate.
</para></listitem>
</varlistentry>
<varlistentry>
<term>-N attr spec</term>
<listitem><para>Send arbitrary attribute specific by
attr_id:syntax:value, or attr_id alone. attr_id should be the numeric
ID of the attribute, and syntax should be one of 's' (string),
'd' (integer), or 'x' (octet string). The value is the attribute value
to send. When attr_id is given alone, NULL is used as the attribute
value. Multiple attributes can be specified by using the option
several times.</para></listitem>
</varlistentry>
<varlistentry>
<term>-n</term>
<listitem><para>Indicates that no MPPE keys are expected.
</para></listitem>
</varlistentry>
<varlistentry>
<term>-W</term>
<listitem><para>Wait for a control interface monitor before starting.
</para></listitem>
</varlistentry>
<varlistentry>
<term>-S</term>
<listitem><para>Save configuration after authentication.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
</para>
</refsect1>
<refsect1>
<title>Legal</title>
<para>wpa_supplicant is copyright (c) 2003-2022,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
<para>This program is licensed under the BSD license (the one with
advertisement clause removed).</para>
</refsect1>
</refentry>

View File

@ -0,0 +1,105 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>07 August 2019</date>
</refentryinfo>
<refmeta>
<refentrytitle>wpa_background</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>wpa_background</refname>
<refpurpose>Background information on Wi-Fi Protected Access and IEEE 802.11i</refpurpose>
</refnamediv>
<refsect1>
<title>WPA</title>
<para>The original security mechanism of IEEE 802.11 standard was
not designed to be strong and has proven to be insufficient for
most networks that require some kind of security. Task group I
(Security) of IEEE 802.11 working group
(http://www.ieee802.org/11/) has worked to address the flaws of
the base standard and has in practice completed its work in May
2004. The IEEE 802.11i amendment to the IEEE 802.11 standard was
approved in June 2004 and published in July 2004.</para>
<para>Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version
of the IEEE 802.11i work (draft 3.0) to define a subset of the
security enhancements that can be implemented with existing wlan
hardware. This is called Wi-Fi Protected Access&lt;TM&gt; (WPA). This
has now become a mandatory component of interoperability testing
and certification done by Wi-Fi Alliance. Wi-Fi provides
information about WPA at its web site
(http://www.wi-fi.org/OpenSection/protected_access.asp).</para>
<para>IEEE 802.11 standard defined wired equivalent privacy (WEP)
algorithm for protecting wireless networks. WEP uses RC4 with
40-bit keys, 24-bit initialization vector (IV), and CRC32 to
protect against packet forgery. All these choices have proven to
be insufficient: key space is too small against current attacks,
RC4 key scheduling is insufficient (beginning of the pseudorandom
stream should be skipped), IV space is too small and IV reuse
makes attacks easier, there is no replay protection, and non-keyed
authentication does not protect against bit flipping packet
data.</para>
<para>WPA is an intermediate solution for the security issues. It
uses Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP
is a compromise on strong security and possibility to use existing
hardware. It still uses RC4 for the encryption like WEP, but with
per-packet RC4 keys. In addition, it implements replay protection,
keyed packet authentication mechanism (Michael MIC).</para>
<para>Keys can be managed using two different mechanisms. WPA can
either use an external authentication server (e.g., RADIUS) and
EAP just like IEEE 802.1X is using or pre-shared keys without need
for additional servers. Wi-Fi calls these "WPA-Enterprise" and
"WPA-Personal", respectively. Both mechanisms will generate a
master session key for the Authenticator (AP) and Supplicant
(client station).</para>
<para>WPA implements a new key handshake (4-Way Handshake and
Group Key Handshake) for generating and exchanging data encryption
keys between the Authenticator and Supplicant. This handshake is
also used to verify that both Authenticator and Supplicant know
the master session key. These handshakes are identical regardless
of the selected key management mechanism (only the method for
generating master session key changes).</para>
</refsect1>
<refsect1>
<title>IEEE 802.11i / WPA2</title>
<para>The design for parts of IEEE 802.11i that were not included
in WPA has finished (May 2004) and this amendment to IEEE 802.11
was approved in June 2004. Wi-Fi Alliance is using the final IEEE
802.11i as a new version of WPA called WPA2. This includes, e.g.,
support for more robust encryption algorithm (CCMP: AES in Counter
mode with CBC-MAC) to replace TKIP and optimizations for handoff
(reduced number of messages in initial key handshake,
pre-authentication, and PMKSA caching).</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
</para>
</refsect1>
<refsect1>
<title>Legal</title>
<para>wpa_supplicant is copyright (c) 2003-2022,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
<para>This program is licensed under the BSD license (the one with
advertisement clause removed).</para>
</refsect1>
</refentry>

View File

@ -0,0 +1,360 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>07 August 2019</date>
</refentryinfo>
<refmeta>
<refentrytitle>wpa_cli</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>wpa_cli</refname>
<refpurpose>WPA command line client</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>wpa_cli</command>
<arg>-p <replaceable>path to ctrl sockets</replaceable></arg>
<arg>-g <replaceable>path to global ctrl_interface socket</replaceable></arg>
<arg>-i <replaceable>ifname</replaceable></arg>
<arg>-hvB</arg>
<arg>-a <replaceable>action file</replaceable></arg>
<arg>-P <replaceable>pid file</replaceable></arg>
<arg>-G <replaceable>ping interval</replaceable></arg>
<arg><replaceable>command ...</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Overview</title>
<para>wpa_cli is a text-based frontend program for interacting
with wpa_supplicant. It is used to query current status, change
configuration, trigger events, and request interactive user
input.</para>
<para>wpa_cli can show the current authentication status, selected
security mode, dot11 and dot1x MIBs, etc. In addition, it can
configure some variables like EAPOL state machine parameters and
trigger events like reassociation and IEEE 802.1X
logoff/logon. wpa_cli provides a user interface to request
authentication information, like username and password, if these
are not included in the configuration. This can be used to
implement, e.g., one-time-passwords or generic token card
authentication where the authentication is based on a
challenge-response that uses an external device for generating the
response.</para>
<para>The control interface of wpa_supplicant can be configured to
allow non-root user access (ctrl_interface GROUP= parameter in the
configuration file). This makes it possible to run wpa_cli with a
normal user account.</para>
<para>wpa_cli supports two modes: interactive and command
line. Both modes share the same command set and the main
difference is in interactive mode providing access to unsolicited
messages (event messages, username/password requests).</para>
<para>Interactive mode is started when wpa_cli is executed without
including the command as a command line parameter. Commands are
then entered on the wpa_cli prompt. In command line mode, the same
commands are entered as command line arguments for wpa_cli.</para>
</refsect1>
<refsect1>
<title>Interactive authentication parameters request</title>
<para>When wpa_supplicant need authentication parameters, like
username and password, which are not present in the configuration
file, it sends a request message to all attached frontend programs,
e.g., wpa_cli in interactive mode. wpa_cli shows these requests
with "CTRL-REQ-&lt;type&gt;-&lt;id&gt;:&lt;text&gt;"
prefix. &lt;type&gt; is IDENTITY, PASSWORD, or OTP
(one-time-password). &lt;id&gt; is a unique identifier for the
current network. &lt;text&gt; is description of the request. In
case of OTP request, it includes the challenge from the
authentication server.</para>
<para>The reply to these requests can be given with
<emphasis>identity</emphasis>, <emphasis>password</emphasis>, and
<emphasis>otp</emphasis> commands. &lt;id&gt; needs to be copied from
the matching request. <emphasis>password</emphasis> and
<emphasis>otp</emphasis> commands can be used regardless of whether
the request was for PASSWORD or OTP. The main difference between these
two commands is that values given with <emphasis>password</emphasis> are
remembered as long as wpa_supplicant is running whereas values given
with <emphasis>otp</emphasis> are used only once and then forgotten,
i.e., wpa_supplicant will ask frontend for a new value for every use.
This can be used to implement one-time-password lists and generic token
card -based authentication.</para>
<para>Example request for password and a matching reply:</para>
<blockquote><programlisting>
CTRL-REQ-PASSWORD-1:Password needed for SSID foobar
> password 1 mysecretpassword
</programlisting></blockquote>
<para>Example request for generic token card challenge-response:</para>
<blockquote><programlisting>
CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar
> otp 2 9876
</programlisting></blockquote>
</refsect1>
<refsect1>
<title>Command Arguments</title>
<variablelist>
<varlistentry>
<term>-p path</term>
<listitem><para>Change the path where control sockets should
be found.</para></listitem>
</varlistentry>
<varlistentry>
<term>-g control socket path</term>
<listitem><para>Connect to the global control socket at the
indicated path rather than an interface-specific control
socket.</para></listitem>
</varlistentry>
<varlistentry>
<term>-i ifname</term>
<listitem><para>Specify the interface that is being
configured. By default, choose the first interface found with
a control socket in the socket path.</para></listitem>
</varlistentry>
<varlistentry>
<term>-h</term>
<listitem><para>Help. Show a usage message.</para></listitem>
</varlistentry>
<varlistentry>
<term>-v</term>
<listitem><para>Show version information.</para></listitem>
</varlistentry>
<varlistentry>
<term>-B</term>
<listitem><para>Run as a daemon in the background.</para></listitem>
</varlistentry>
<varlistentry>
<term>-a file</term>
<listitem><para>Run in daemon mode executing the action file
based on events from wpa_supplicant. The specified file will
be executed with the first argument set to interface name and
second to "CONNECTED" or "DISCONNECTED" depending on the event.
This can be used to execute networking tools required to configure
the interface.</para>
<para>Additionally, three environmental variables are available to
the file: WPA_CTRL_DIR, WPA_ID, and WPA_ID_STR. WPA_CTRL_DIR
contains the absolute path to the ctrl_interface socket. WPA_ID
contains the unique network_id identifier assigned to the active
network, and WPA_ID_STR contains the content of the id_str option.
</para></listitem>
</varlistentry>
<varlistentry>
<term>-P file</term>
<listitem><para>Set the location of the PID
file.</para></listitem>
</varlistentry>
<varlistentry>
<term>-G ping interval</term>
<listitem><para>Set the interval (in seconds) at which
wpa_cli pings the supplicant.</para></listitem>
</varlistentry>
<varlistentry>
<term>command</term>
<listitem><para>Run a command. The available commands are
listed in the next section.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Commands</title>
<para>The following commands are available:</para>
<variablelist>
<varlistentry>
<term>status</term>
<listitem>
<para>get current WPA/EAPOL/EAP status</para>
</listitem>
</varlistentry>
<varlistentry>
<term>mib</term>
<listitem>
<para>get MIB variables (dot1x, dot11)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>help</term>
<listitem>
<para>show this usage help</para>
</listitem>
</varlistentry>
<varlistentry>
<term>interface [ifname]</term>
<listitem>
<para>show interfaces/select interface</para>
</listitem>
</varlistentry>
<varlistentry>
<term>level &lt;debug level&gt;</term>
<listitem>
<para>change debug level</para>
</listitem>
</varlistentry>
<varlistentry>
<term>license</term>
<listitem>
<para>show full wpa_cli license</para>
</listitem>
</varlistentry>
<varlistentry>
<term>logoff</term>
<listitem>
<para>IEEE 802.1X EAPOL state machine logoff</para>
</listitem>
</varlistentry>
<varlistentry>
<term>logon</term>
<listitem>
<para>IEEE 802.1X EAPOL state machine logon</para>
</listitem>
</varlistentry>
<varlistentry>
<term>set</term>
<listitem>
<para>set variables (shows list of variables when run without arguments)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pmksa</term>
<listitem>
<para>show PMKSA cache</para>
</listitem>
</varlistentry>
<varlistentry>
<term>reassociate</term>
<listitem>
<para>force reassociation</para>
</listitem>
</varlistentry>
<varlistentry>
<term>reconfigure</term>
<listitem>
<para>force wpa_supplicant to re-read its configuration file</para>
</listitem>
</varlistentry>
<varlistentry>
<term>preauthenticate &lt;BSSID&gt;</term>
<listitem>
<para>force preauthentication</para>
</listitem>
</varlistentry>
<varlistentry>
<term>identity &lt;network id&gt; &lt;identity&gt;</term>
<listitem>
<para>configure identity for an SSID</para>
</listitem>
</varlistentry>
<varlistentry>
<term>password &lt;network id&gt; &lt;password&gt;</term>
<listitem>
<para>configure password for an SSID</para>
</listitem>
</varlistentry>
<varlistentry>
<term>pin &lt;network id&gt; &lt;pin&gt;</term>
<listitem>
<para>configure pin for an SSID</para>
</listitem>
</varlistentry>
<varlistentry>
<term>otp &lt;network id&gt; &lt;password&gt;</term>
<listitem>
<para>configure one-time-password for an SSID</para>
</listitem>
</varlistentry>
<varlistentry>
<term>bssid &lt;network id&gt; &lt;BSSID&gt;</term>
<listitem>
<para>set preferred BSSID for an SSID</para>
</listitem>
</varlistentry>
<varlistentry>
<term>list_networks</term>
<listitem>
<para>list configured networks</para>
</listitem>
</varlistentry>
<varlistentry>
<term>terminate</term>
<listitem>
<para>terminate <command>wpa_supplicant</command></para>
</listitem>
</varlistentry>
<varlistentry>
<term>quit</term>
<listitem><para>exit wpa_cli</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
</para>
</refsect1>
<refsect1>
<title>Legal</title>
<para>wpa_supplicant is copyright (c) 2003-2022,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
<para>This program is licensed under the BSD license (the one with
advertisement clause removed).</para>
</refsect1>
</refentry>

View File

@ -0,0 +1,106 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>07 August 2019</date>
</refentryinfo>
<refmeta>
<refentrytitle>wpa_gui</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>wpa_gui</refname>
<refpurpose>WPA Graphical User Interface</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>wpa_gui</command>
<arg>-p <replaceable>path to ctrl sockets</replaceable></arg>
<arg>-i <replaceable>ifname</replaceable></arg>
<arg>-m <replaceable>seconds</replaceable></arg>
<arg>-t</arg>
<arg>-q</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Overview</title>
<para>wpa_gui is a QT graphical frontend program for interacting
with wpa_supplicant. It is used to query current status, change
configuration and request interactive user input.</para>
<para>wpa_gui supports (almost) all of the interactive status and
configuration features of the command line client, wpa_cli. Refer
to the wpa_cli manpage for a comprehensive list of the
interactive mode features.</para>
</refsect1>
<refsect1>
<title>Command Arguments</title>
<variablelist>
<varlistentry>
<term>-p path</term>
<listitem><para>Change the path where control sockets should
be found.</para></listitem>
</varlistentry>
<varlistentry>
<term>-i ifname</term>
<listitem><para>Specify the interface that is being
configured. By default, choose the first interface found with
a control socket in the socket path.</para></listitem>
</varlistentry>
<varlistentry>
<term>-m seconds</term>
<listitem><para>Set the update interval in seconds for the signal
strength meter. This value must be a positive integer, otherwise
meter is not enabled (default behavior).</para></listitem>
</varlistentry>
<varlistentry>
<term>-t</term>
<listitem><para>Start program in the system tray only (if the window
manager supports it). By default the main status window is
shown.</para></listitem>
</varlistentry>
<varlistentry>
<term>-q</term>
<listitem><para>Run program in the quiet mode - do not display tray
icon pop-up messages.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wpa_cli</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
<citerefentry>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
</para>
</refsect1>
<refsect1>
<title>Legal</title>
<para>wpa_supplicant is copyright (c) 2003-2022,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
<para>This program is licensed under the BSD license (the one with
advertisement clause removed).</para>
</refsect1>
</refentry>

View File

@ -0,0 +1,77 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>07 August 2019</date>
</refentryinfo>
<refmeta>
<refentrytitle>wpa_passphrase</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>wpa_passphrase</refname>
<refpurpose>Generate a WPA PSK from an ASCII passphrase for a SSID</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>wpa_passphrase</command>
<arg><replaceable>ssid</replaceable></arg>
<arg><replaceable>passphrase</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Overview</title>
<para><command>wpa_passphrase</command> pre-computes PSK entries for
network configuration blocks of a
<filename>wpa_supplicant.conf</filename> file. An ASCII passphrase
and SSID are used to generate a 256-bit PSK.</para>
</refsect1>
<refsect1>
<title>Options</title>
<variablelist>
<varlistentry>
<term>ssid</term>
<listitem>
<para>The SSID whose passphrase should be derived.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>passphrase</term>
<listitem>
<para>The passphrase to use. If not included on the command line,
passphrase will be read from standard input.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wpa_supplicant.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>
<citerefentry>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
</para>
</refsect1>
<refsect1>
<title>Legal</title>
<para>wpa_supplicant is copyright (c) 2003-2022,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
<para>This program is licensed under the BSD license (the one with
advertisement clause removed).</para>
</refsect1>
</refentry>

View File

@ -0,0 +1,152 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>07 August 2019</date>
</refentryinfo>
<refmeta>
<refentrytitle>wpa_priv</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>wpa_priv</refname>
<refpurpose>wpa_supplicant privilege separation helper</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>wpa_priv</command>
<arg>-c <replaceable>ctrl path</replaceable></arg>
<arg>-Bdd</arg>
<arg>-P <replaceable>pid file</replaceable></arg>
<arg>driver:ifname <replaceable>[driver:ifname ...]</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Overview</title>
<para><command>wpa_priv</command> is a privilege separation helper that
minimizes the size of <command>wpa_supplicant</command> code that needs
to be run with root privileges.</para>
<para>If enabled, privileged operations are done in the wpa_priv process
while leaving rest of the code (e.g., EAP authentication and WPA
handshakes) to operate in an unprivileged process (wpa_supplicant) that
can be run as non-root user. Privilege separation restricts the effects
of potential software errors by containing the majority of the code in an
unprivileged process to avoid the possibility of a full system
compromise.</para>
<para><command>wpa_priv</command> needs to be run with network admin
privileges (usually, root user). It opens a UNIX domain socket for each
interface that is included on the command line; any other interface will
be off limits for <command>wpa_supplicant</command> in this kind of
configuration. After this, <command>wpa_supplicant</command> can be run as
a non-root user (e.g., all standard users on a laptop or as a special
non-privileged user account created just for this purpose to limit access
to user files even further).</para>
</refsect1>
<refsect1>
<title>Example configuration</title>
<para>The following steps are an example of how to configure
<command>wpa_priv</command> to allow users in the
<emphasis>wpapriv</emphasis> group to communicate with
<command>wpa_supplicant</command> with privilege separation:</para>
<para>Create user group (e.g., wpapriv) and assign users that
should be able to use wpa_supplicant into that group.</para>
<para>Create /var/run/wpa_priv directory for UNIX domain sockets and
control user access by setting it accessible only for the wpapriv
group:</para>
<blockquote><programlisting>
mkdir /var/run/wpa_priv
chown root:wpapriv /var/run/wpa_priv
chmod 0750 /var/run/wpa_priv
</programlisting></blockquote>
<para>Start <command>wpa_priv</command> as root (e.g., from system
startup scripts) with the enabled interfaces configured on the
command line:</para>
<blockquote><programlisting>
wpa_priv -B -c /var/run/wpa_priv -P /var/run/wpa_priv.pid wext:wlan0
</programlisting></blockquote>
<para>Run <command>wpa_supplicant</command> as non-root with a user
that is in the wpapriv group:</para>
<blockquote><programlisting>
wpa_supplicant -i ath0 -c wpa_supplicant.conf
</programlisting></blockquote>
</refsect1>
<refsect1>
<title>Command Arguments</title>
<variablelist>
<varlistentry>
<term>-c ctrl path</term>
<listitem><para>Specify the path to wpa_priv control directory
(Default: /var/run/wpa_priv/).</para></listitem>
</varlistentry>
<varlistentry>
<term>-B</term>
<listitem><para>Run as a daemon in the background.</para></listitem>
</varlistentry>
<varlistentry>
<term>-P file</term>
<listitem><para>Set the location of the PID
file.</para></listitem>
</varlistentry>
<varlistentry>
<term>driver:ifname [driver:ifname ...]</term>
<listitem><para>The &lt;driver&gt; string dictates which of the
supported <command>wpa_supplicant</command> driver backends is to be
used. To get a list of supported driver types see wpa_supplicant help
(e.g, wpa_supplicant -h). The driver backend supported by most good
drivers is <emphasis>wext</emphasis>.</para>
<para>The &lt;ifname&gt; string specifies which network
interface is to be managed by <command>wpa_supplicant</command>
(e.g., wlan0 or ath0).</para>
<para><command>wpa_priv</command> does not use the network interface
before <command>wpa_supplicant</command> is started, so it is fine to
include network interfaces that are not available at the time wpa_priv
is started. wpa_priv can control multiple interfaces with one process,
but it is also possible to run multiple <command>wpa_priv</command>
processes at the same time, if desired.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
</para>
</refsect1>
<refsect1>
<title>Legal</title>
<para>wpa_supplicant is copyright (c) 2003-2022,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
<para>This program is licensed under the BSD license (the one with
advertisement clause removed).</para>
</refsect1>
</refentry>

View File

@ -0,0 +1,243 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>07 August 2019</date>
</refentryinfo>
<refmeta>
<refentrytitle>wpa_supplicant.conf</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>wpa_supplicant.conf</refname>
<refpurpose>configuration file for wpa_supplicant</refpurpose>
</refnamediv>
<refsect1>
<title>Overview</title>
<para><command>wpa_supplicant</command> is configured using a text
file that lists all accepted networks and security policies,
including pre-shared keys. See the example configuration file,
probably in <command>/usr/share/doc/wpa_supplicant/</command>, for
detailed information about the configuration format and supported
fields.</para>
<para>All file paths in this configuration file should use full
(absolute, not relative to working directory) path in order to allow
working directory to be changed. This can happen if wpa_supplicant is
run in the background.</para>
<para>Changes to configuration file can be reloaded be sending
SIGHUP signal to <command>wpa_supplicant</command> ('killall -HUP
wpa_supplicant'). Similarly, reloading can be triggered with
the <emphasis>wpa_cli reconfigure</emphasis> command.</para>
<para>Configuration file can include one or more network blocks,
e.g., one for each used SSID. wpa_supplicant will automatically
select the best network based on the order of network blocks in
the configuration file, network security level (WPA/WPA2 is
preferred), and signal strength.</para>
</refsect1>
<refsect1>
<title>Quick Examples</title>
<orderedlist>
<listitem>
<para>WPA-Personal (PSK) as home network and WPA-Enterprise with
EAP-TLS as work network.</para>
<blockquote><programlisting>
# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
#
# home network; allow all valid ciphers
network={
ssid="home"
scan_ssid=1
key_mgmt=WPA-PSK
psk="very secret passphrase"
}
#
# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers
network={
ssid="work"
scan_ssid=1
key_mgmt=WPA-EAP
pairwise=CCMP TKIP
group=CCMP TKIP
eap=TLS
identity="user@example.com"
ca_cert="/etc/cert/ca.pem"
client_cert="/etc/cert/user.pem"
private_key="/etc/cert/user.prv"
private_key_passwd="password"
}
</programlisting></blockquote>
</listitem>
<listitem>
<para>WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that
use old peaplabel (e.g., Funk Odyssey and SBR, Meetinghouse
Aegis, Interlink RAD-Series)</para>
<blockquote><programlisting>
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
network={
ssid="example"
scan_ssid=1
key_mgmt=WPA-EAP
eap=PEAP
identity="user@example.com"
password="foobar"
ca_cert="/etc/cert/ca.pem"
phase1="peaplabel=0"
phase2="auth=MSCHAPV2"
}
</programlisting></blockquote>
</listitem>
<listitem>
<para>EAP-TTLS/EAP-MD5-Challenge configuration with anonymous
identity for the unencrypted use. Real identity is sent only
within an encrypted TLS tunnel.</para>
<blockquote><programlisting>
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
network={
ssid="example"
scan_ssid=1
key_mgmt=WPA-EAP
eap=TTLS
identity="user@example.com"
anonymous_identity="anonymous@example.com"
password="foobar"
ca_cert="/etc/cert/ca.pem"
phase2="auth=MD5"
}
</programlisting></blockquote>
</listitem>
<listitem>
<para>IEEE 802.1X (i.e., no WPA) with dynamic WEP keys
(require both unicast and broadcast); use EAP-TLS for
authentication</para>
<blockquote><programlisting>
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
network={
ssid="1x-test"
scan_ssid=1
key_mgmt=IEEE8021X
eap=TLS
identity="user@example.com"
ca_cert="/etc/cert/ca.pem"
client_cert="/etc/cert/user.pem"
private_key="/etc/cert/user.prv"
private_key_passwd="password"
eapol_flags=3
}
</programlisting></blockquote>
</listitem>
<listitem>
<para>Catch all example that allows more or less all
configuration modes. The configuration options are used based
on what security policy is used in the selected SSID. This is
mostly for testing and is not recommended for normal
use.</para>
<blockquote><programlisting>
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
network={
ssid="example"
scan_ssid=1
key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
pairwise=CCMP TKIP
group=CCMP TKIP WEP104 WEP40
psk="very secret passphrase"
eap=TTLS PEAP TLS
identity="user@example.com"
password="foobar"
ca_cert="/etc/cert/ca.pem"
client_cert="/etc/cert/user.pem"
private_key="/etc/cert/user.prv"
private_key_passwd="password"
phase1="peaplabel=0"
ca_cert2="/etc/cert/ca2.pem"
client_cert2="/etc/cer/user.pem"
private_key2="/etc/cer/user.prv"
private_key2_passwd="password"
}
</programlisting></blockquote>
</listitem>
<listitem>
<para>Authentication for wired Ethernet. This can be used with
<emphasis>wired</emphasis> or <emphasis>roboswitch</emphasis> interface
(-Dwired or -Droboswitch on command line).</para>
<blockquote><programlisting>
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
ap_scan=0
network={
key_mgmt=IEEE8021X
eap=MD5
identity="user"
password="password"
eapol_flags=0
}
</programlisting></blockquote>
</listitem>
</orderedlist>
</refsect1>
<refsect1>
<title>Certificates</title>
<para>Some EAP authentication methods require use of
certificates. EAP-TLS uses both server side and client
certificates whereas EAP-PEAP and EAP-TTLS only require the server
side certificate. When client certificate is used, a matching
private key file has to also be included in configuration. If the
private key uses a passphrase, this has to be configured in
wpa_supplicant.conf ("private_key_passwd").</para>
<para>wpa_supplicant supports X.509 certificates in PEM and DER
formats. User certificate and private key can be included in the
same file.</para>
<para>If the user certificate and private key is received in
PKCS#12/PFX format, they need to be converted to suitable PEM/DER
format for wpa_supplicant. This can be done, e.g., with following
commands:</para>
<blockquote><programlisting>
# convert client certificate and private key to PEM format
openssl pkcs12 -in example.pfx -out user.pem -clcerts
# convert CA certificate (if included in PFX file) to PEM format
openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys
</programlisting></blockquote>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
<citerefentry>
<refentrytitle>openssl</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -0,0 +1,764 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
<refentryinfo>
<date>07 August 2019</date>
</refentryinfo>
<refmeta>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>wpa_supplicant</refname>
<refpurpose>Wi-Fi Protected Access client and IEEE 802.1X supplicant</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>wpa_supplicant</command>
<arg>-BddfhKLqqsTtuvW</arg>
<arg>-i<replaceable>ifname</replaceable></arg>
<arg>-c<replaceable>config file</replaceable></arg>
<arg>-D<replaceable>driver</replaceable></arg>
<arg>-P<replaceable>PID_file</replaceable></arg>
<arg>-f<replaceable>output file</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Overview</title>
<para>
Wireless networks do not require physical access to the network equipment
in the same way as wired networks. This makes it easier for unauthorized
users to passively monitor a network and capture all transmitted frames.
In addition, unauthorized use of the network is much easier. In many cases,
this can happen even without user's explicit knowledge since the wireless
LAN adapter may have been configured to automatically join any available
network.
</para>
<para>
Link-layer encryption can be used to provide a layer of security for
wireless networks. The original wireless LAN standard, IEEE 802.11,
included a simple encryption mechanism, WEP. However, that proved to
be flawed in many areas and network protected with WEP cannot be consider
secure. IEEE 802.1X authentication and frequently changed dynamic WEP keys
can be used to improve the network security, but even that has inherited
security issues due to the use of WEP for encryption. Wi-Fi Protected
Access and IEEE 802.11i amendment to the wireless LAN standard introduce
a much improved mechanism for securing wireless networks. IEEE 802.11i
enabled networks that are using CCMP (encryption mechanism based on strong
cryptographic algorithm AES) can finally be called secure used for
applications which require efficient protection against unauthorized
access.
</para>
<para><command>wpa_supplicant</command> is an implementation of
the WPA Supplicant component, i.e., the part that runs in the
client stations. It implements WPA key negotiation with a WPA
Authenticator and EAP authentication with Authentication
Server. In addition, it controls the roaming and IEEE 802.11
authentication/association of the wireless LAN driver.</para>
<para><command>wpa_supplicant</command> is designed to be a
"daemon" program that runs in the background and acts as the
backend component controlling the wireless
connection. <command>wpa_supplicant</command> supports separate
frontend programs and an example text-based frontend,
<command>wpa_cli</command>, is included with
wpa_supplicant.</para>
<para>Before wpa_supplicant can do its work, the network interface
must be available. That means that the physical device must be
present and enabled, and the driver for the device must be
loaded. The daemon will exit immediately if the device is not already
available.</para>
<para>After <command>wpa_supplicant</command> has configured the
network device, higher level configuration such as DHCP may
proceed. There are a variety of ways to integrate wpa_supplicant
into a machine's networking scripts, a few of which are described
in sections below.</para>
<para>The following steps are used when associating with an AP
using WPA:</para>
<itemizedlist>
<listitem>
<para><command>wpa_supplicant</command> requests the kernel
driver to scan neighboring BSSes</para>
</listitem>
<listitem>
<para><command>wpa_supplicant</command> selects a BSS based on
its configuration</para>
</listitem>
<listitem>
<para><command>wpa_supplicant</command> requests the kernel
driver to associate with the chosen BSS</para>
</listitem>
<listitem>
<para>If WPA-EAP: integrated IEEE 802.1X Supplicant
completes EAP authentication with the
authentication server (proxied by the Authenticator in the
AP)</para>
</listitem>
<listitem>
<para>If WPA-EAP: master key is received from the IEEE 802.1X
Supplicant</para>
</listitem>
<listitem>
<para>If WPA-PSK: <command>wpa_supplicant</command> uses PSK
as the master session key</para>
</listitem>
<listitem>
<para><command>wpa_supplicant</command> completes WPA 4-Way
Handshake and Group Key Handshake with the Authenticator
(AP)</para>
</listitem>
<listitem>
<para><command>wpa_supplicant</command> configures encryption
keys for unicast and broadcast</para>
</listitem>
<listitem>
<para>normal data packets can be transmitted and received</para>
</listitem>
</itemizedlist>
</refsect1>
<refsect1>
<title>Supported Features</title>
<para>Supported WPA/IEEE 802.11i features:</para>
<itemizedlist>
<listitem>
<para>WPA-PSK ("WPA-Personal")</para>
</listitem>
<listitem>
<para>WPA with EAP (e.g., with RADIUS authentication server)
("WPA-Enterprise") Following authentication methods are
supported with an integrate IEEE 802.1X Supplicant:</para>
<itemizedlist>
<listitem>
<para>EAP-TLS</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1)</para>
</listitem>
<listitem>
<para>EAP-PEAP/TLS (both PEAPv0 and PEAPv1)</para>
</listitem>
<listitem>
<para>EAP-PEAP/GTC (both PEAPv0 and PEAPv1)</para>
</listitem>
<listitem>
<para>EAP-PEAP/OTP (both PEAPv0 and PEAPv1)</para>
</listitem>
<listitem>
<para>EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1)</para>
</listitem>
<listitem>
<para>EAP-TTLS/EAP-MD5-Challenge</para>
</listitem>
<listitem>
<para>EAP-TTLS/EAP-GTC</para>
</listitem>
<listitem><para>EAP-TTLS/EAP-OTP</para></listitem>
<listitem><para>EAP-TTLS/EAP-MSCHAPv2</para></listitem>
<listitem><para>EAP-TTLS/EAP-TLS</para></listitem>
<listitem><para>EAP-TTLS/MSCHAPv2</para></listitem>
<listitem><para>EAP-TTLS/MSCHAP</para></listitem>
<listitem><para>EAP-TTLS/PAP</para></listitem>
<listitem><para>EAP-TTLS/CHAP</para></listitem>
<listitem><para>EAP-SIM</para></listitem>
<listitem><para>EAP-AKA</para></listitem>
<listitem><para>EAP-PSK</para></listitem>
<listitem><para>EAP-PAX</para></listitem>
<listitem><para>LEAP (note: requires special support from
the driver for IEEE 802.11 authentication)</para></listitem>
<listitem><para>(following methods are supported, but since
they do not generate keying material, they cannot be used
with WPA or IEEE 802.1X WEP keying)</para></listitem>
<listitem><para>EAP-MD5-Challenge </para></listitem>
<listitem><para>EAP-MSCHAPv2</para></listitem>
<listitem><para>EAP-GTC</para></listitem>
<listitem><para>EAP-OTP</para></listitem>
</itemizedlist>
</listitem>
<listitem>
<para>key management for CCMP, TKIP, WEP104, WEP40</para>
</listitem>
<listitem>
<para>RSN/WPA2 (IEEE 802.11i)</para>
<itemizedlist>
<listitem>
<para>pre-authentication</para>
</listitem>
<listitem>
<para>PMKSA caching</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</refsect1>
<refsect1>
<title>Available Drivers</title>
<para>A summary of available driver backends is below. Support for each
of the driver backends is chosen at wpa_supplicant compile time. For a
list of supported driver backends that may be used with the -D option on
your system, refer to the help output of wpa_supplicant
(<emphasis>wpa_supplicant -h</emphasis>).</para>
<variablelist>
<varlistentry>
<term>nl80211</term>
<listitem>
<para>Uses the modern Linux nl80211/cfg80211 netlink-based
interface (most new drivers).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>wext</term>
<listitem>
<para>Uses the legacy Linux wireless extensions ioctl-based
interface (older hardware/drivers).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>wired</term>
<listitem>
<para>wpa_supplicant wired Ethernet driver</para>
</listitem>
</varlistentry>
<varlistentry>
<term>roboswitch</term>
<listitem>
<para>wpa_supplicant Broadcom switch driver</para>
</listitem>
</varlistentry>
<varlistentry>
<term>bsd</term>
<listitem>
<para>BSD 802.11 support (Atheros, etc.).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ndis</term>
<listitem>
<para>Windows NDIS driver.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Command Line Options</title>
<para>Most command line options have global scope. Some are given per
interface, and are only valid if at least one <option>-i</option> option
is specified, otherwise they're ignored. Option groups for different
interfaces must be separated by <option>-N</option> option.</para>
<variablelist>
<varlistentry>
<term>-b br_ifname</term>
<listitem>
<para>Optional bridge interface name. (Per interface)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-B</term>
<listitem>
<para>Run daemon in the background.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-c filename</term>
<listitem>
<para>Path to configuration file. (Per interface)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-C ctrl_interface</term>
<listitem>
<para>Path to ctrl_interface socket (Per interface. Only used if
<option>-c</option> is not).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-i ifname</term>
<listitem>
<para>Interface to listen on. Multiple instances of this option can
be present, one per interface, separated by <option>-N</option>
option (see below).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-d</term>
<listitem>
<para>Increase debugging verbosity (<option>-dd</option> even
more).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-D driver</term>
<listitem>
<para>Driver to use (can be multiple drivers: nl80211,wext).
(Per interface, see the available options below.)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-e entropy file</term>
<listitem>
<para>File for <command>wpa_supplicant</command> to use to
maintain its internal entropy store in over restarts.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-f output file</term>
<listitem>
<para>Log output to specified file instead of stdout. (This
is only available if <command>wpa_supplicant</command> was
built with the <literal>CONFIG_DEBUG_FILE</literal>
option.)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-g global ctrl_interface</term>
<listitem>
<para>Path to global ctrl_interface socket. If specified, interface
definitions may be omitted.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-K</term>
<listitem>
<para>Include keys (passwords, etc.) in debug output.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-h</term>
<listitem>
<para>Help. Show a usage message.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-L</term>
<listitem>
<para>Show license (BSD).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-o override driver</term>
<listitem>
<para>Override the driver parameter for new
interfaces.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-O override ctrl_interface</term>
<listitem>
<para>Override the ctrl_interface parameter for new
interfaces.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-p</term>
<listitem>
<para>Driver parameters. (Per interface)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-P PID_file</term>
<listitem>
<para>Path to PID file.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-q</term>
<listitem>
<para>Decrease debugging verbosity (<option>-qq</option> even
less).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-s</term>
<listitem>
<para>Log output to syslog instead of stdout. (This is only
available if <command>wpa_supplicant</command> was built
with the <literal>CONFIG_DEBUG_SYSLOG</literal>
option.)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-T</term>
<listitem>
<para>Log output to Linux tracing in addition to any other
destinations. (This is only available
if <command>wpa_supplicant</command> was built with
the <literal>CONFIG_DEBUG_LINUX_TRACING</literal>
option.)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-t</term>
<listitem>
<para>Include timestamp in debug messages.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-u</term>
<listitem>
<para>Enable DBus control interface. If enabled, interface
definitions may be omitted. (This is only available
if <command>wpa_supplicant</command> was built with
the <literal>CONFIG_CTRL_IFACE_DBUS_NEW</literal> option.)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-v</term>
<listitem>
<para>Show version.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-W</term>
<listitem>
<para>Wait for a control interface monitor before starting.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-N</term>
<listitem>
<para>Start describing new interface.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>In most common cases, <command>wpa_supplicant</command> is
started with:</para>
<blockquote><programlisting>
wpa_supplicant -B -c/etc/wpa_supplicant.conf -iwlan0
</programlisting></blockquote>
<para>This makes the process fork into background.</para>
<para>The easiest way to debug problems, and to get debug log for
bug reports, is to start <command>wpa_supplicant</command> on
foreground with debugging enabled:</para>
<blockquote><programlisting>
wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d
</programlisting></blockquote>
<para>If the specific driver wrapper is not known beforehand, it is
possible to specify multiple comma separated driver wrappers on the command
line. <command>wpa_supplicant</command> will use the first driver
wrapper that is able to initialize the interface.</para>
<blockquote><programlisting>
wpa_supplicant -Dnl80211,wext -c/etc/wpa_supplicant.conf -iwlan0
</programlisting></blockquote>
<para><command>wpa_supplicant</command> can control multiple
interfaces (radios) either by running one process for each
interface separately or by running just one process and list of
options at command line. Each interface is separated with -N
argument. As an example, following command would start
wpa_supplicant for two interfaces:</para>
<blockquote><programlisting>
wpa_supplicant \
-c wpa1.conf -i wlan0 -D nl80211 -N \
-c wpa2.conf -i ath0 -D wext
</programlisting></blockquote>
</refsect1>
<refsect1>
<title>OS Requirements</title>
<para>Current hardware/software requirements:</para>
<itemizedlist>
<listitem>
<para>Linux kernel 2.6.30 or higher with
nl80211/cfg80211 support</para>
</listitem>
<listitem>
<para>Linux kernel 2.4.x or higher with Linux Wireless
Extensions v15 or newer</para>
</listitem>
<listitem>
<para>FreeBSD 6-CURRENT</para>
</listitem>
<listitem>
<para>Microsoft Windows with WinPcap (at least WinXP, may work
with other versions)</para>
</listitem>
</itemizedlist>
</refsect1>
<refsect1>
<title>Supported Drivers</title>
<variablelist>
<varlistentry>
<term>Linux nl80211/cfg80211</term>
<listitem>
<para>This is the preferred driver for Linux.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Linux wireless extensions</term>
<listitem>
<para>In theory, any driver that supports Linux wireless
extensions can be used with IEEE 802.1X (i.e., not WPA) when
using ap_scan=0 option in configuration file.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Wired Ethernet drivers</term>
<listitem>
<para>Use ap_scan=0.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>BSD net80211 layer (e.g., Atheros driver)</term>
<listitem>
<para>At the moment, this is for FreeBSD 6-CURRENT branch.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Windows NDIS</term>
<listitem>
<para>The current Windows port requires WinPcap
(http://winpcap.polito.it/). See README-Windows.txt for more
information.</para>
</listitem>
</varlistentry>
</variablelist>
<para>wpa_supplicant was designed to be portable for different
drivers and operating systems. Hopefully, support for more wlan
cards and OSes will be added in the future. See developer.txt for
more information about the design of wpa_supplicant and porting to
other drivers. One main goal is to add full WPA/WPA2 support to
Linux wireless extensions to allow new drivers to be supported
without having to implement new driver-specific interface code in
wpa_supplicant.</para>
</refsect1>
<refsect1>
<title>Architecture</title> <para>The
<command>wpa_supplicant</command> system consists of the following
components:</para>
<variablelist>
<varlistentry>
<term><filename>wpa_supplicant.conf</filename> </term>
<listitem>
<para>the configuration file describing all networks that the
user wants the computer to connect to. </para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>wpa_supplicant</command></term>
<listitem><para>the program that directly interacts with the
network interface. </para></listitem>
</varlistentry>
<varlistentry>
<term><command>wpa_cli</command></term> <listitem><para> the
client program that provides a high-level interface to the
functionality of the daemon. </para></listitem>
</varlistentry>
<varlistentry>
<term><command>wpa_passphrase</command></term>
<listitem><para>a utility needed to construct
<filename>wpa_supplicant.conf</filename> files that include
encrypted passwords.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Quick Start</title>
<para>First, make a configuration file, e.g.
<filename>/etc/wpa_supplicant.conf</filename>, that describes the networks
you are interested in. See <citerefentry>
<refentrytitle>wpa_supplicant.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>
for details.</para>
<para>Once the configuration is ready, you can test whether the
configuration works by running <command>wpa_supplicant</command>
with following command to start it on foreground with debugging
enabled:</para>
<blockquote><programlisting>
wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d
</programlisting></blockquote>
<para>Assuming everything goes fine, you can start using following
command to start <command>wpa_supplicant</command> on background
without debugging:</para>
<blockquote><programlisting>
wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B
</programlisting></blockquote>
<para>Please note that if you included more than one driver
interface in the build time configuration (.config), you may need
to specify which interface to use by including -D&lt;driver
name&gt; option on the command line.</para>
<!-- XXX at this point, the page could include a little script
based on wpa_cli to wait for a connection and then run
dhclient -->
</refsect1>
<refsect1>
<title>Interface to pcmcia-cs/cardmrg</title>
<para>For example, following small changes to pcmcia-cs scripts
can be used to enable WPA support:</para>
<para>Add MODE="Managed" and WPA="y" to the network scheme in
<filename>/etc/pcmcia/wireless.opts</filename>.</para>
<para>Add the following block to the end of <emphasis>start</emphasis>
action handler in <filename>/etc/pcmcia/wireless</filename>:</para>
<blockquote><programlisting>
if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
/usr/local/bin/wpa_supplicant -B -c/etc/wpa_supplicant.conf -i$DEVICE
fi
</programlisting></blockquote>
<para>Add the following block to the end of <emphasis>stop</emphasis>
action handler (may need to be separated from other actions) in
<filename>/etc/pcmcia/wireless</filename>:</para>
<blockquote><programlisting>
if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
killall wpa_supplicant
fi
</programlisting></blockquote>
<para>This will make <command>cardmgr</command> start
<command>wpa_supplicant</command> when the card is plugged
in.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry>
<refentrytitle>wpa_background</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
<citerefentry>
<refentrytitle>wpa_supplicant.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>
<citerefentry>
<refentrytitle>wpa_cli</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
<citerefentry>
<refentrytitle>wpa_passphrase</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>
</para>
</refsect1>
<refsect1>
<title>Legal</title>
<para>wpa_supplicant is copyright (c) 2003-2022,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
<para>This program is licensed under the BSD license (the one with
advertisement clause removed).</para>
</refsect1>
</refentry>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
/*
* wpa_supplicant - DPP
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef DPP_SUPPLICANT_H
#define DPP_SUPPLICANT_H
enum dpp_status_error;
int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
unsigned int freq, unsigned int duration);
void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
unsigned int freq);
void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
const u8 *buf, size_t len, unsigned int freq);
int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id);
void wpas_dpp_stop(struct wpa_supplicant *wpa_s);
int wpas_dpp_init(struct wpa_supplicant *wpa_s);
void wpas_dpp_deinit(struct wpa_supplicant *wpa_s);
int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss);
int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd);
void wpas_dpp_connected(struct wpa_supplicant *wpa_s);
void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
enum dpp_status_error result);
int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd);
void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s);
int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd);
#endif /* DPP_SUPPLICANT_H */

1120
wpa_supplicant/driver_i.h Normal file

File diff suppressed because it is too large Load Diff

View File

View File

View File

@ -0,0 +1,271 @@
/*
* EAP method registration
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "eap_peer/eap_methods.h"
#include "eap_server/eap_methods.h"
#include "wpa_supplicant_i.h"
/**
* eap_register_methods - Register statically linked EAP methods
* Returns: 0 on success, -1 or -2 on failure
*
* This function is called at program initialization to register all EAP
* methods that were linked in statically.
*/
int eap_register_methods(void)
{
int ret = 0;
#ifdef EAP_MD5
if (ret == 0)
ret = eap_peer_md5_register();
#endif /* EAP_MD5 */
#ifdef EAP_TLS
if (ret == 0)
ret = eap_peer_tls_register();
#endif /* EAP_TLS */
#ifdef EAP_UNAUTH_TLS
if (ret == 0)
ret = eap_peer_unauth_tls_register();
#endif /* EAP_UNAUTH_TLS */
#ifdef EAP_TLS
#ifdef CONFIG_HS20
if (ret == 0)
ret = eap_peer_wfa_unauth_tls_register();
#endif /* CONFIG_HS20 */
#endif /* EAP_TLS */
#ifdef EAP_MSCHAPv2
if (ret == 0)
ret = eap_peer_mschapv2_register();
#endif /* EAP_MSCHAPv2 */
#ifdef EAP_PEAP
if (ret == 0)
ret = eap_peer_peap_register();
#endif /* EAP_PEAP */
#ifdef EAP_TTLS
if (ret == 0)
ret = eap_peer_ttls_register();
#endif /* EAP_TTLS */
#ifdef EAP_GTC
if (ret == 0)
ret = eap_peer_gtc_register();
#endif /* EAP_GTC */
#ifdef EAP_OTP
if (ret == 0)
ret = eap_peer_otp_register();
#endif /* EAP_OTP */
#ifdef EAP_SIM
if (ret == 0)
ret = eap_peer_sim_register();
#endif /* EAP_SIM */
#ifdef EAP_LEAP
if (ret == 0)
ret = eap_peer_leap_register();
#endif /* EAP_LEAP */
#ifdef EAP_PSK
if (ret == 0)
ret = eap_peer_psk_register();
#endif /* EAP_PSK */
#ifdef EAP_AKA
if (ret == 0)
ret = eap_peer_aka_register();
#endif /* EAP_AKA */
#ifdef EAP_AKA_PRIME
if (ret == 0)
ret = eap_peer_aka_prime_register();
#endif /* EAP_AKA_PRIME */
#ifdef EAP_FAST
if (ret == 0)
ret = eap_peer_fast_register();
#endif /* EAP_FAST */
#ifdef EAP_TEAP
if (ret == 0)
ret = eap_peer_teap_register();
#endif /* EAP_TEAP */
#ifdef EAP_PAX
if (ret == 0)
ret = eap_peer_pax_register();
#endif /* EAP_PAX */
#ifdef EAP_SAKE
if (ret == 0)
ret = eap_peer_sake_register();
#endif /* EAP_SAKE */
#ifdef EAP_GPSK
if (ret == 0)
ret = eap_peer_gpsk_register();
#endif /* EAP_GPSK */
#ifdef EAP_WSC
if (ret == 0)
ret = eap_peer_wsc_register();
#endif /* EAP_WSC */
#ifdef EAP_IKEV2
if (ret == 0)
ret = eap_peer_ikev2_register();
#endif /* EAP_IKEV2 */
#ifdef EAP_VENDOR_TEST
if (ret == 0)
ret = eap_peer_vendor_test_register();
#endif /* EAP_VENDOR_TEST */
#ifdef EAP_TNC
if (ret == 0)
ret = eap_peer_tnc_register();
#endif /* EAP_TNC */
#ifdef EAP_PWD
if (ret == 0)
ret = eap_peer_pwd_register();
#endif /* EAP_PWD */
#ifdef EAP_EKE
if (ret == 0)
ret = eap_peer_eke_register();
#endif /* EAP_EKE */
#ifdef EAP_SERVER_IDENTITY
if (ret == 0)
ret = eap_server_identity_register();
#endif /* EAP_SERVER_IDENTITY */
#ifdef EAP_SERVER_MD5
if (ret == 0)
ret = eap_server_md5_register();
#endif /* EAP_SERVER_MD5 */
#ifdef EAP_SERVER_TLS
if (ret == 0)
ret = eap_server_tls_register();
#endif /* EAP_SERVER_TLS */
#ifdef EAP_SERVER_UNAUTH_TLS
if (ret == 0)
ret = eap_server_unauth_tls_register();
#endif /* EAP_SERVER_UNAUTH_TLS */
#ifdef EAP_SERVER_MSCHAPV2
if (ret == 0)
ret = eap_server_mschapv2_register();
#endif /* EAP_SERVER_MSCHAPV2 */
#ifdef EAP_SERVER_PEAP
if (ret == 0)
ret = eap_server_peap_register();
#endif /* EAP_SERVER_PEAP */
#ifdef EAP_SERVER_TLV
if (ret == 0)
ret = eap_server_tlv_register();
#endif /* EAP_SERVER_TLV */
#ifdef EAP_SERVER_GTC
if (ret == 0)
ret = eap_server_gtc_register();
#endif /* EAP_SERVER_GTC */
#ifdef EAP_SERVER_TTLS
if (ret == 0)
ret = eap_server_ttls_register();
#endif /* EAP_SERVER_TTLS */
#ifdef EAP_SERVER_SIM
if (ret == 0)
ret = eap_server_sim_register();
#endif /* EAP_SERVER_SIM */
#ifdef EAP_SERVER_AKA
if (ret == 0)
ret = eap_server_aka_register();
#endif /* EAP_SERVER_AKA */
#ifdef EAP_SERVER_AKA_PRIME
if (ret == 0)
ret = eap_server_aka_prime_register();
#endif /* EAP_SERVER_AKA_PRIME */
#ifdef EAP_SERVER_PAX
if (ret == 0)
ret = eap_server_pax_register();
#endif /* EAP_SERVER_PAX */
#ifdef EAP_SERVER_PSK
if (ret == 0)
ret = eap_server_psk_register();
#endif /* EAP_SERVER_PSK */
#ifdef EAP_SERVER_SAKE
if (ret == 0)
ret = eap_server_sake_register();
#endif /* EAP_SERVER_SAKE */
#ifdef EAP_SERVER_GPSK
if (ret == 0)
ret = eap_server_gpsk_register();
#endif /* EAP_SERVER_GPSK */
#ifdef EAP_SERVER_VENDOR_TEST
if (ret == 0)
ret = eap_server_vendor_test_register();
#endif /* EAP_SERVER_VENDOR_TEST */
#ifdef EAP_SERVER_FAST
if (ret == 0)
ret = eap_server_fast_register();
#endif /* EAP_SERVER_FAST */
#ifdef EAP_SERVER_TEAP
if (ret == 0)
ret = eap_server_teap_register();
#endif /* EAP_SERVER_TEAP */
#ifdef EAP_SERVER_WSC
if (ret == 0)
ret = eap_server_wsc_register();
#endif /* EAP_SERVER_WSC */
#ifdef EAP_SERVER_IKEV2
if (ret == 0)
ret = eap_server_ikev2_register();
#endif /* EAP_SERVER_IKEV2 */
#ifdef EAP_SERVER_TNC
if (ret == 0)
ret = eap_server_tnc_register();
#endif /* EAP_SERVER_TNC */
#ifdef EAP_SERVER_PWD
if (ret == 0)
ret = eap_server_pwd_register();
#endif /* EAP_SERVER_PWD */
return ret;
}

View File

@ -0,0 +1,392 @@
Automatic regression and interoperability testing of wpa_supplicant's
IEEE 802.1X/EAPOL authentication
Test program:
- Linked some parts of IEEE 802.1X Authenticator implementation from
hostapd (RADIUS client and RADIUS processing, EAP<->RADIUS
encapsulation/decapsulation) into wpa_supplicant.
- Replaced wpa_supplicant.c and wpa.c with test code that trigger
IEEE 802.1X authentication automatically without need for wireless
client card or AP.
- For EAP methods that generate keying material, the key derived by the
Supplicant is verified to match with the one received by the (now
integrated) Authenticator.
The full automated test suite can now be run in couple of seconds, but
I'm more than willing to add new RADIUS authentication servers to make
this take a bit more time.. ;-) As an extra bonus, this can also be
seen as automatic regression/interoperability testing for the RADIUS
server, too.
In order for me to be able to use a new authentication server, the
server need to be available from Internet (at least from one static IP
address) and I will need to get suitable user name/password pairs,
certificates, and private keys for testing use. Other alternative
would be to get an evaluation version of the server so that I can
install it on my own test setup. If you are interested in providing
either server access or evaluation version, please contact me
(j@w1.fi).
Test matrix
+) tested successfully
F) failed
-) server did not support
?) not tested
Cisco ACS ----------------------------------------------------------.
hostapd --------------------------------------------------------. |
Cisco Aironet 1200 AP (local RADIUS server) ----------------. | |
Periodik Labs Elektron ---------------------------------. | | |
Lucent NavisRadius ---------------------------------. | | | |
Interlink RAD-Series ---------------------------. | | | | |
Radiator -----------------------------------. | | | | | |
Meetinghouse Aegis ---------------------. | | | | | | |
Funk Steel-Belted ------------------. | | | | | | | |
Funk Odyssey -------------------. | | | | | | | | |
Microsoft IAS --------------. | | | | | | | | | |
FreeRADIUS -------------. | | | | | | | | | | |
| | | | | | | | | | | |
EAP-MD5 + - - + + + + + - - + +
EAP-GTC + - - ? + + + + - - + -
EAP-OTP - - - - - + - - - - - -
EAP-MSCHAPv2 + - - + + + + + - - + -
EAP-TLS + + + + + + + + - - + +
EAP-PEAPv0/MSCHAPv2 + + + + + + + + + - + +
EAP-PEAPv0/GTC + - + - + + + + - - + +
EAP-PEAPv0/OTP - - - - - + - - - - - -
EAP-PEAPv0/MD5 + - - + + + + + - - + -
EAP-PEAPv0/TLS + + - + + + F + - - + +
EAP-PEAPv0/SIM - - - - - - - - - - + -
EAP-PEAPv0/AKA - - - - - - - - - - + -
EAP-PEAPv0/PSK - - - - - - - - - - + -
EAP-PEAPv0/PAX - - - - - - - - - - + -
EAP-PEAPv0/SAKE - - - - - - - - - - + -
EAP-PEAPv0/GPSK - - - - - - - - - - + -
EAP-PEAPv1/MSCHAPv2 - - + + + +1 + +5 +8 - + +
EAP-PEAPv1/GTC - - + + + +1 + +5 +8 - + +
EAP-PEAPv1/OTP - - - - - +1 - - - - - -
EAP-PEAPv1/MD5 - - - + + +1 + +5 - - + -
EAP-PEAPv1/TLS - - - + + +1 F +5 - - + +
EAP-PEAPv1/SIM - - - - - - - - - - + -
EAP-PEAPv1/AKA - - - - - - - - - - + -
EAP-PEAPv1/PSK - - - - - - - - - - + -
EAP-PEAPv1/PAX - - - - - - - - - - + -
EAP-PEAPv1/SAKE - - - - - - - - - - + -
EAP-PEAPv1/GPSK - - - - - - - - - - + -
EAP-TTLS/CHAP + - +2 + + + + + + - + -
EAP-TTLS/MSCHAP + - + + + + + + + - + -
EAP-TTLS/MSCHAPv2 + - + + + + + + + - + -
EAP-TTLS/PAP + - + + + + + + + - + -
EAP-TTLS/EAP-MD5 + - +2 + + + + + + - + -
EAP-TTLS/EAP-GTC + - +2 ? + + + + - - + -
EAP-TTLS/EAP-OTP - - - - - + - - - - - -
EAP-TTLS/EAP-MSCHAPv2 + - +2 + + + + + + - + -
EAP-TTLS/EAP-TLS + - +2 + F + + + - - + -
EAP-TTLS/EAP-SIM - - - - - - - - - - + -
EAP-TTLS/EAP-AKA - - - - - - - - - - + -
EAP-TTLS/EAP-PSK - - - - - - - - - - + -
EAP-TTLS/EAP-PAX - - - - - - - - - - + -
EAP-TTLS/EAP-SAKE - - - - - - - - - - + -
EAP-TTLS/EAP-GPSK - - - - - - - - - - + -
EAP-TTLS + TNC - - - - - + - - - - + -
EAP-SIM + - - ? - + - ? - - + -
EAP-AKA - - - - - + - - - - + -
EAP-AKA' - - - - - - - - - - + -
EAP-PSK +7 - - - - + - - - - + -
EAP-PAX - - - - - + - - - - + -
EAP-SAKE - - - - - - - - - - + -
EAP-GPSK - - - - - - - - - - + -
EAP-FAST/MSCHAPv2(prov) - - - + - + - - - + + +
EAP-FAST/GTC(auth) - - - + - + - - - + + +
EAP-FAST/MSCHAPv2(aprov)- - - - - + - - - - + +
EAP-FAST/GTC(aprov) - - - - - + - - - - + +
EAP-FAST/MD5(aprov) - - - - - + - - - - + -
EAP-FAST/TLS(aprov) - - - - - - - - - - + +
EAP-FAST/SIM(aprov) - - - - - - - - - - + -
EAP-FAST/AKA(aprov) - - - - - - - - - - + -
EAP-FAST/MSCHAPv2(auth) - - - - - + - - - - + +
EAP-FAST/MD5(auth) - - - - - + - - - - + -
EAP-FAST/TLS(auth) - - - - - - - - - - + +
EAP-FAST/SIM(auth) - - - - - - - - - - + -
EAP-FAST/AKA(auth) - - - - - - - - - - + -
EAP-FAST + TNC - - - - - - - - - - + -
LEAP + - + + + + F +6 - + - +
EAP-TNC +9 - - - - + - - - - + -
EAP-IKEv2 +10 - - - - - - - - - + -
1) PEAPv1 required new label, "client PEAP encryption" instead of "client EAP
encryption", during key derivation (requires phase1="peaplabel=1" in the
network configuration in wpa_supplicant.conf)
2) used FreeRADIUS as inner auth server
5) PEAPv1 required termination of negotiation on tunneled EAP-Success and new
label in key deriviation
(phase1="peap_outer_success=0 peaplabel=1") (in "IETF Draft 5" mode)
6) Authenticator simulator required patching for handling Access-Accept within
negotiation (for the first EAP-Success of LEAP)
7) tested only with an older (incompatible) draft of EAP-PSK; FreeRADIUS does
not support the current EAP-PSK (RFC) specification
8) PEAPv1 used non-standard version negotiation (client had to force v1 even
though server reported v0 as the highest supported version)
9) only EAP-TTLS/EAP-TNC tested, i.e., test did not include proper sequence of
client authentication followed by TNC inside the tunnel
10) worked only with special compatibility code to match the IKEv2 server
implementation
Automated tests:
FreeRADIUS (2.0-beta/CVS snapshot)
- EAP-MD5-Challenge
- EAP-GTC
- EAP-MSCHAPv2
- EAP-TLS
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / GTC
- EAP-PEAPv0 / MD5-Challenge
- EAP-PEAPv0 / TLS
- EAP-TTLS / EAP-MD5-Challenge
- EAP-TTLS / EAP-GTC
- EAP-TTLS / EAP-MSCHAPv2
- EAP-TTLS / EAP-TLS
- EAP-TTLS / CHAP
- EAP-TTLS / PAP
- EAP-TTLS / MSCHAP
- EAP-TTLS / MSCHAPv2
- EAP-TTLS / EAP-TNC (partial support; no authentication sequence)
- EAP-SIM
- LEAP
Microsoft Windows Server 2003 / IAS
- EAP-TLS
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / TLS
- EAP-MD5
* IAS does not seem to support other EAP methods
Funk Odyssey 2.01.00.653
- EAP-TLS
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / GTC
- EAP-PEAPv1 / MSCHAPv2
- EAP-PEAPv1 / GTC
Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption"
- EAP-TTLS / CHAP (using FreeRADIUS as inner auth srv)
- EAP-TTLS / MSCHAP
- EAP-TTLS / MSCHAPv2
- EAP-TTLS / PAP
- EAP-TTLS / EAP-MD5-Challenge (using FreeRADIUS as inner auth srv)
- EAP-TTLS / EAP-GTC (using FreeRADIUS as inner auth srv)
- EAP-TTLS / EAP-MSCHAPv2 (using FreeRADIUS as inner auth srv)
- EAP-TTLS / EAP-TLS (using FreeRADIUS as inner auth srv)
* not supported in Odyssey:
- EAP-MD5-Challenge
- EAP-GTC
- EAP-MSCHAPv2
- EAP-PEAP / MD5-Challenge
- EAP-PEAP / TLS
Funk Steel-Belted Radius Enterprise Edition v4.71.739
- EAP-MD5-Challenge
- EAP-MSCHAPv2
- EAP-TLS
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / MD5
- EAP-PEAPv0 / TLS
- EAP-PEAPv1 / MSCHAPv2
- EAP-PEAPv1 / MD5
- EAP-PEAPv1 / GTC
- EAP-PEAPv1 / TLS
Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption"
- EAP-TTLS / CHAP
- EAP-TTLS / MSCHAP
- EAP-TTLS / MSCHAPv2
- EAP-TTLS / PAP
- EAP-TTLS / EAP-MD5-Challenge
- EAP-TTLS / EAP-MSCHAPv2
- EAP-TTLS / EAP-TLS
Meetinghouse Aegis 1.1.4
- EAP-MD5-Challenge
- EAP-GTC
- EAP-MSCHAPv2
- EAP-TLS
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / TLS
- EAP-PEAPv0 / GTC
- EAP-PEAPv0 / MD5-Challenge
- EAP-PEAPv1 / MSCHAPv2
- EAP-PEAPv1 / TLS
- EAP-PEAPv1 / GTC
- EAP-PEAPv1 / MD5-Challenge
Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption"
- EAP-TTLS / CHAP
- EAP-TTLS / MSCHAP
- EAP-TTLS / MSCHAPv2
- EAP-TTLS / PAP
- EAP-TTLS / EAP-MD5-Challenge
- EAP-TTLS / EAP-GTC
- EAP-TTLS / EAP-MSCHAPv2
* did not work
- EAP-TTLS / EAP-TLS
(Server rejects authentication without any reason in debug log. It
looks like the inner TLS negotiation starts properly and the last
packet from Supplicant looks like the one sent in the Phase 1. The
server generates a valid looking reply in the same way as in Phase
1, but then ends up sending Access-Reject. Maybe an issue with TTLS
fragmentation in the Aegis server(?) The packet seems to include
1328 bytes of EAP-Message and this may go beyond the fragmentation
limit with AVP encapsulation and TLS tunneling. Note: EAP-PEAP/TLS
did work, so this issue seems to be with something TTLS specific.)
Radiator 3.17.1 (eval, with all patches up to and including 2007-05-25)
- EAP-MD5-Challenge
- EAP-GTC
- EAP-OTP
- EAP-MSCHAPv2
- EAP-TLS
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / GTC
- EAP-PEAPv0 / OTP
- EAP-PEAPv0 / MD5-Challenge
- EAP-PEAPv0 / TLS
Note: Needed to use unknown identity in outer auth and some times the server
seems to get confused and fails to send proper Phase 2 data.
- EAP-PEAPv1 / MSCHAPv2
- EAP-PEAPv1 / GTC
- EAP-PEAPv1 / OTP
- EAP-PEAPv1 / MD5-Challenge
- EAP-PEAPv1 / TLS
Note: This has some additional requirements for EAPTLS_MaxFragmentSize.
Using 1300 for outer auth and 500 for inner auth seemed to work.
Note: Needed to use unknown identity in outer auth and some times the server
seems to get confused and fails to send proper Phase 2 data.
- EAP-TTLS / CHAP
- EAP-TTLS / MSCHAP
- EAP-TTLS / MSCHAPv2
- EAP-TTLS / PAP
- EAP-TTLS / EAP-MD5-Challenge
- EAP-TTLS / EAP-GTC
- EAP-TTLS / EAP-OTP
- EAP-TTLS / EAP-MSCHAPv2
- EAP-TTLS / EAP-TLS
Note: This has some additional requirements for EAPTLS_MaxFragmentSize.
Using 1300 for outer auth and 500 for inner auth seemed to work.
- EAP-SIM
- EAP-AKA
- EAP-PSK
- EAP-PAX
- EAP-TNC
Interlink Networks RAD-Series 6.1.2.7
- EAP-MD5-Challenge
- EAP-GTC
- EAP-MSCHAPv2
- EAP-TLS
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / GTC
- EAP-PEAPv0 / MD5-Challenge
- EAP-PEAPv1 / MSCHAPv2
- EAP-PEAPv1 / GTC
- EAP-PEAPv1 / MD5-Challenge
Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption"
- EAP-TTLS / CHAP
- EAP-TTLS / MSCHAP
- EAP-TTLS / MSCHAPv2
- EAP-TTLS / PAP
- EAP-TTLS / EAP-MD5-Challenge
- EAP-TTLS / EAP-GTC
- EAP-TTLS / EAP-MSCHAPv2
- EAP-TTLS / EAP-TLS
* did not work
- EAP-PEAPv0 / TLS
- EAP-PEAPv1 / TLS
(Failed to decrypt Phase 2 data)
Lucent NavisRadius 4.4.0
- EAP-MD5-Challenge
- EAP-GTC
- EAP-MSCHAPv2
- EAP-TLS
- EAP-PEAPv0 / MD5-Challenge
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / GTC
- EAP-PEAPv0 / TLS
- EAP-PEAPv1 / MD5-Challenge
- EAP-PEAPv1 / MSCHAPv2
- EAP-PEAPv1 / GTC
- EAP-PEAPv1 / TLS
"IETF Draft 5" mode requires phase1="peap_outer_success=0 peaplabel=1"
'Cisco ACU 5.05' mode works without phase1 configuration
- EAP-TTLS / CHAP
- EAP-TTLS / MSCHAP
- EAP-TTLS / MSCHAPv2
- EAP-TTLS / PAP
- EAP-TTLS / EAP-MD5-Challenge
- EAP-TTLS / EAP-MSCHAPv2
- EAP-TTLS / EAP-GTC
- EAP-TTLS / EAP-TLS
Note: user certificate from NavisRadius had private key in a format
that wpa_supplicant could not use. Converting this to PKCS#12 and then
back to PEM allowed wpa_supplicant to use the key.
hostapd v0.3.3
- EAP-MD5-Challenge
- EAP-GTC
- EAP-MSCHAPv2
- EAP-TLS
- EAP-PEAPv0 / MSCHAPv2
- EAP-PEAPv0 / GTC
- EAP-PEAPv0 / MD5-Challenge
- EAP-PEAPv1 / MSCHAPv2
- EAP-PEAPv1 / GTC
- EAP-PEAPv1 / MD5-Challenge
- EAP-TTLS / CHAP
- EAP-TTLS / MSCHAP
- EAP-TTLS / MSCHAPv2
- EAP-TTLS / PAP
- EAP-TTLS / EAP-MD5-Challenge
- EAP-TTLS / EAP-GTC
- EAP-TTLS / EAP-MSCHAPv2
- EAP-SIM
- EAP-PAX
PEAPv1:
Funk Odyssey 2.01.00.653:
- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE
keys with outer EAP-Success message after this
- uses label "client EAP encryption"
- (peap_outer_success 1 and 2 work)
Funk Steel-Belted Radius Enterprise Edition v4.71.739
- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE
keys with outer EAP-Success message after this
- uses label "client EAP encryption"
- (peap_outer_success 1 and 2 work)
Radiator 3.9:
- uses TLV Success and Reply, sends MPPE keys with outer EAP-Success message
after this
- uses label "client PEAP encryption"
Lucent NavisRadius 4.4.0 (in "IETF Draft 5" mode):
- sends tunneled EAP-Success with MPPE keys and expects the authentication to
terminate at this point (gets somewhat confused with reply to this)
- uses label "client PEAP encryption"
- phase1="peap_outer_success=0 peaplabel=1"
Lucent NavisRadius 4.4.0 (in "Cisco ACU 5.05" mode):
- sends tunneled EAP-Success with MPPE keys and expects to receive TLS ACK
as a reply
- uses label "client EAP encryption"
Meetinghouse Aegis 1.1.4
- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE
keys with outer EAP-Success message after this
- uses label "client EAP encryption"
- peap_outer_success 1 and 2 work

1555
wpa_supplicant/eapol_test.c Normal file

File diff suppressed because it is too large Load Diff

159
wpa_supplicant/eapol_test.py Executable file
View File

@ -0,0 +1,159 @@
#!/usr/bin/env python2
#
# eapol_test controller
# Copyright (c) 2015, Jouni Malinen <j@w1.fi>
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
import argparse
import logging
import os
import Queue
import sys
import threading
logger = logging.getLogger()
dir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
sys.path.append(os.path.join(dir, '..', 'wpaspy'))
import wpaspy
wpas_ctrl = '/tmp/eapol_test'
class eapol_test:
def __init__(self, ifname):
self.ifname = ifname
self.ctrl = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
if "PONG" not in self.ctrl.request("PING"):
raise Exception("Failed to connect to eapol_test (%s)" % ifname)
self.mon = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
self.mon.attach()
def add_network(self):
id = self.request("ADD_NETWORK")
if "FAIL" in id:
raise Exception("ADD_NETWORK failed")
return int(id)
def remove_network(self, id):
id = self.request("REMOVE_NETWORK " + str(id))
if "FAIL" in id:
raise Exception("REMOVE_NETWORK failed")
return None
def set_network(self, id, field, value):
res = self.request("SET_NETWORK " + str(id) + " " + field + " " + value)
if "FAIL" in res:
raise Exception("SET_NETWORK failed")
return None
def set_network_quoted(self, id, field, value):
res = self.request("SET_NETWORK " + str(id) + " " + field + ' "' + value + '"')
if "FAIL" in res:
raise Exception("SET_NETWORK failed")
return None
def request(self, cmd, timeout=10):
return self.ctrl.request(cmd, timeout=timeout)
def wait_event(self, events, timeout=10):
start = os.times()[4]
while True:
while self.mon.pending():
ev = self.mon.recv()
logger.debug(self.ifname + ": " + ev)
for event in events:
if event in ev:
return ev
now = os.times()[4]
remaining = start + timeout - now
if remaining <= 0:
break
if not self.mon.pending(timeout=remaining):
break
return None
def run(ifname, count, no_fast_reauth, res, conf):
et = eapol_test(ifname)
et.request("AP_SCAN 0")
if no_fast_reauth:
et.request("SET fast_reauth 0")
else:
et.request("SET fast_reauth 1")
id = et.add_network()
if len(conf):
for item in conf:
et.set_network(id, item, conf[item])
else:
et.set_network(id, "key_mgmt", "IEEE8021X")
et.set_network(id, "eapol_flags", "0")
et.set_network(id, "eap", "TLS")
et.set_network_quoted(id, "identity", "user")
et.set_network_quoted(id, "ca_cert", 'ca.pem')
et.set_network_quoted(id, "client_cert", 'client.pem')
et.set_network_quoted(id, "private_key", 'client.key')
et.set_network_quoted(id, "private_key_passwd", 'whatever')
et.set_network(id, "disabled", "0")
fail = False
for i in range(count):
et.request("REASSOCIATE")
ev = et.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-EAP-FAILURE"])
if ev is None or "CTRL-EVENT-CONNECTED" not in ev:
fail = True
break
et.remove_network(id)
if fail:
res.put("FAIL (%d OK)" % i)
else:
res.put("PASS %d" % (i + 1))
def main():
parser = argparse.ArgumentParser(description='eapol_test controller')
parser.add_argument('--ctrl', help='control interface directory')
parser.add_argument('--num', help='number of processes')
parser.add_argument('--iter', help='number of iterations')
parser.add_argument('--no-fast-reauth', action='store_true',
dest='no_fast_reauth',
help='disable TLS session resumption')
parser.add_argument('--conf', help='file of network conf items')
args = parser.parse_args()
num = int(args.num)
iter = int(args.iter)
if args.ctrl:
global wpas_ctrl
wpas_ctrl = args.ctrl
conf = {}
if args.conf:
f = open(args.conf, "r")
for line in f:
confitem = line.split("=")
if len(confitem) == 2:
conf[confitem[0].strip()] = confitem[1].strip()
f.close()
t = {}
res = {}
for i in range(num):
res[i] = Queue.Queue()
t[i] = threading.Thread(target=run, args=(str(i), iter,
args.no_fast_reauth, res[i],
conf))
for i in range(num):
t[i].start()
for i in range(num):
t[i].join()
try:
results = res[i].get(False)
except:
results = "N/A"
print("%d: %s" % (i, results))
if __name__ == "__main__":
main()

5783
wpa_supplicant/events.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
#!/bin/sh
# /etc/pm/sleep.d/60_wpa_supplicant
# Action script to notify wpa_supplicant of pm-action events.
PATH=/sbin:/usr/sbin:/bin:/usr/bin
WPACLI=wpa_cli
case "$1" in
suspend|hibernate)
$WPACLI suspend
;;
resume|thaw)
$WPACLI resume
;;
esac
exit 0

View File

@ -0,0 +1,66 @@
#!/usr/bin/python
from __future__ import print_function
import dbus
import sys
import time
import gobject
from dbus.mainloop.glib import DBusGMainLoop
WPAS_DBUS_SERVICE = "fi.w1.wpa_supplicant1"
WPAS_DBUS_INTERFACE = "fi.w1.wpa_supplicant1"
WPAS_DBUS_OPATH = "/fi/w1/wpa_supplicant1"
WPAS_DBUS_INTERFACES_INTERFACE = "fi.w1.wpa_supplicant1.Interface"
def usage():
print("Usage: %s <ifname>" % sys.argv[0])
print("Press Ctrl-C to stop")
def ProbeRequest(args):
if 'addr' in args:
print('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['addr']),
end=' ')
if 'dst' in args:
print('-> %.2x:%.2x:%.2x:%.2x:%.2x:%.2x' % tuple(args['dst']),
end=' ')
if 'bssid' in args:
print('(bssid %.2x:%.2x:%.2x:%.2x:%.2x:%.2x)' % tuple(args['dst']),
end=' ')
if 'signal' in args:
print('signal:%d' % args['signal'], end=' ')
if 'ies' in args:
print('have IEs (%d bytes)' % len(args['ies']), end=' ')
print('')
if __name__ == "__main__":
global bus
global wpas_obj
global if_obj
global p2p_iface
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
wpas_obj = bus.get_object(WPAS_DBUS_SERVICE, WPAS_DBUS_OPATH)
# Print list of i/f if no one is specified
if (len(sys.argv) < 2) :
usage()
sys.exit(0)
wpas = dbus.Interface(wpas_obj, WPAS_DBUS_INTERFACE)
ifname = sys.argv[1]
path = wpas.GetInterface(ifname)
if_obj = bus.get_object(WPAS_DBUS_SERVICE, path)
iface = dbus.Interface(if_obj, WPAS_DBUS_INTERFACES_INTERFACE)
bus.add_signal_receiver(ProbeRequest,
dbus_interface=WPAS_DBUS_INTERFACES_INTERFACE,
signal_name="ProbeRequest")
iface.SubscribeProbeReq()
gobject.MainLoop().run()

1186
wpa_supplicant/examples/dpp-nfc.py Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
#!/usr/bin/python
#
# Example Android logcat to wpa_supplicant wrapper for QR Code scans
# Copyright (c) 2017, Qualcomm Atheros, Inc.
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
import os
import sys
import argparse
import logging
import qrcode
scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy'))
import wpaspy
wpas_ctrl = '/var/run/wpa_supplicant'
def wpas_connect():
ifaces = []
if os.path.isdir(wpas_ctrl):
try:
ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
except OSError as error:
print("Could not find wpa_supplicant: ", error)
return None
if len(ifaces) < 1:
print("No wpa_supplicant control interface found")
return None
for ctrl in ifaces:
try:
wpas = wpaspy.Ctrl(ctrl)
return wpas
except Exception as e:
pass
return None
def dpp_logcat():
for line in iter(sys.stdin.readline, ''):
if "ResultHandler: Launching intent: Intent" not in line:
continue
if "act=android.intent.action.VIEW" not in line:
continue
uri = None
for val in line.split(' '):
if val.startswith('dat='):
uri = val.split('=', 1)[1]
break
if not uri:
continue
if not uri.startswith('DPP:'):
continue
print("Found DPP bootstrap info URI:")
print(uri)
wpas = wpas_connect()
if not wpas:
print("Could not connect to wpa_supplicant")
print('')
continue
res = wpas.request("DPP_QR_CODE " + uri);
try:
id = int(res)
except ValueError:
print("QR Code URI rejected")
continue
print("QR Code URI accepted - ID=%d" % id)
print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
del wpas
def dpp_display(curve):
wpas = wpas_connect()
if not wpas:
print("Could not connect to wpa_supplicant")
return
res = wpas.request("STATUS")
addr = None
for line in res.splitlines():
if line.startswith("address="):
addr = line.split('=')[1]
break
cmd = "DPP_BOOTSTRAP_GEN type=qrcode"
cmd += " chan=81/1"
if addr:
cmd += " mac=" + addr.replace(':','')
if curve:
cmd += " curve=" + curve
res = wpas.request(cmd)
try:
id = int(res)
except ValueError:
print("Failed to generate bootstrap info URI")
return
print("Bootstrap information - ID=%d" % id)
print(wpas.request("DPP_BOOTSTRAP_INFO %d" % id))
uri = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id)
print(uri)
print("ID=%d" % id)
qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_M,
border=3)
qr.add_data(uri, optimize=5)
qr.print_ascii(tty=True)
print("ID=%d" % id)
del wpas
def main():
parser = argparse.ArgumentParser(description='Android logcat to wpa_supplicant integration for DPP QR Code operations')
parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO,
action='store_const', dest='loglevel',
help='verbose debug output')
parser.add_argument('--curve', '-c',
help='set a specific curve (P-256, P-384, P-521, BP-256R1, BP-384R1, BP-512R1) for key generation')
parser.add_argument('command', choices=['logcat',
'display'],
nargs='?')
args = parser.parse_args()
logging.basicConfig(level=args.loglevel)
if args.command == "logcat":
dpp_logcat()
elif args.command == "display":
dpp_display(args.curve)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,13 @@
# IEEE 802.1X with dynamic WEP keys using EAP-PEAP/MSCHAPv2
ctrl_interface=/var/run/wpa_supplicant
network={
ssid="example 802.1x network"
key_mgmt=IEEE8021X
eap=PEAP
phase2="auth=MSCHAPV2"
identity="user name"
password="password"
ca_cert="/etc/cert/ca.pem"
}

View File

@ -0,0 +1,41 @@
# EAP-TLS using private key and certificates via OpenSSL PKCS#11 engine and
# openCryptoki (e.g., with TPM token)
# This example uses following PKCS#11 objects:
# $ pkcs11-tool --module /usr/lib/opencryptoki/libopencryptoki.so -O -l
# Please enter User PIN:
# Private Key Object; RSA
# label: rsakey
# ID: 04
# Usage: decrypt, sign, unwrap
# Certificate Object, type = X.509 cert
# label: ca
# ID: 01
# Certificate Object, type = X.509 cert
# label: cert
# ID: 04
# Configure OpenSSL to load the PKCS#11 engine and openCryptoki module
pkcs11_engine_path=/usr/lib/engines/engine_pkcs11.so
pkcs11_module_path=/usr/lib/opencryptoki/libopencryptoki.so
network={
ssid="test network"
key_mgmt=WPA-EAP
eap=TLS
identity="User"
# use OpenSSL PKCS#11 engine for this network
engine=1
engine_id="pkcs11"
# select the private key and certificates based on ID (see pkcs11-tool
# output above)
key_id="4"
cert_id="4"
ca_cert_id="1"
# set the PIN code; leave this out to configure the PIN to be requested
# interactively when needed (e.g., via wpa_gui or wpa_cli)
pin="123456"
}

Some files were not shown because too many files have changed in this diff Show More