Merge commit 'af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5' into merge_work
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 85ac8c5..10f50d8 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -687,8 +687,10 @@
endif
ifdef NEED_AES_CBC
NEED_AES_DEC=y
+ifneq ($(CONFIG_TLS), openssl)
AESOBJS += src/crypto/aes-cbc.c
endif
+endif
ifdef NEED_AES_DEC
ifdef CONFIG_INTERNAL_AES
AESOBJS += src/crypto/aes-internal-dec.c
diff --git a/hostapd/Makefile b/hostapd/Makefile
index d718c15..3c7bd6f 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -227,6 +227,7 @@
OBJS += ../src/common/sae.o
NEED_ECC=y
NEED_DH_GROUPS=y
+NEED_AP_MLME=y
endif
ifdef CONFIG_WNM
@@ -683,8 +684,10 @@
endif
ifdef NEED_AES_CBC
NEED_AES_DEC=y
+ifneq ($(CONFIG_TLS), openssl)
AESOBJS += ../src/crypto/aes-cbc.o
endif
+endif
ifdef NEED_AES_DEC
ifdef CONFIG_INTERNAL_AES
AESOBJS += ../src/crypto/aes-internal-dec.o
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index cae9fd3..82b08f9 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -222,9 +222,15 @@
return 0;
if (os_strncmp(fname, "sqlite:", 7) == 0) {
+#ifdef CONFIG_SQLITE
os_free(conf->eap_user_sqlite);
conf->eap_user_sqlite = os_strdup(fname + 7);
return 0;
+#else /* CONFIG_SQLITE */
+ wpa_printf(MSG_ERROR,
+ "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build.");
+ return -1;
+#endif /* CONFIG_SQLITE */
}
f = fopen(fname, "r");
diff --git a/hostapd/hlr_auc_gw.c b/hostapd/hlr_auc_gw.c
index 42d59db..8afe457 100644
--- a/hostapd/hlr_auc_gw.c
+++ b/hostapd/hlr_auc_gw.c
@@ -87,6 +87,7 @@
u8 amf[2];
u8 sqn[6];
int set;
+ size_t res_len;
};
static struct milenage_parameters *milenage_db = NULL;
@@ -96,6 +97,7 @@
#define EAP_AKA_RAND_LEN 16
#define EAP_AKA_AUTN_LEN 16
#define EAP_AKA_AUTS_LEN 14
+#define EAP_AKA_RES_MIN_LEN 4
#define EAP_AKA_RES_MAX_LEN 16
#define EAP_AKA_IK_LEN 16
#define EAP_AKA_CK_LEN 16
@@ -124,7 +126,8 @@
" ki CHAR(32) NOT NULL,"
" opc CHAR(32) NOT NULL,"
" amf CHAR(4) NOT NULL,"
- " sqn CHAR(12) NOT NULL"
+ " sqn CHAR(12) NOT NULL,"
+ " res_len INTEGER"
");";
printf("Adding database table for milenage information\n");
@@ -190,6 +193,10 @@
printf("Invalid sqn value in database\n");
return -1;
}
+
+ if (os_strcmp(col[i], "res_len") == 0 && argv[i]) {
+ m->res_len = atoi(argv[i]);
+ }
}
return 0;
@@ -206,8 +213,7 @@
os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
"%llu", imsi);
os_snprintf(cmd, sizeof(cmd),
- "SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;",
- imsi);
+ "SELECT * FROM milenage WHERE imsi=%llu;", imsi);
if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
NULL) != SQLITE_OK)
return NULL;
@@ -424,7 +430,7 @@
while (fgets(buf, sizeof(buf), f)) {
line++;
- /* Parse IMSI Ki OPc AMF SQN */
+ /* Parse IMSI Ki OPc AMF SQN [RES_len] */
buf[sizeof(buf) - 1] = '\0';
if (buf[0] == '#')
continue;
@@ -515,7 +521,19 @@
ret = -1;
break;
}
- pos = pos2 + 1;
+
+ if (pos2) {
+ pos = pos2 + 1;
+ m->res_len = atoi(pos);
+ if (m->res_len &&
+ (m->res_len < EAP_AKA_RES_MIN_LEN ||
+ m->res_len > EAP_AKA_RES_MAX_LEN)) {
+ printf("%s:%d - Invalid RES_len (%s)\n",
+ fname, line, pos);
+ ret = -1;
+ break;
+ }
+ }
m->next = milenage_db;
milenage_db = m;
@@ -798,6 +816,10 @@
}
milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
autn, ik, ck, res, &res_len);
+ if (m->res_len >= EAP_AKA_RES_MIN_LEN &&
+ m->res_len <= EAP_AKA_RES_MAX_LEN &&
+ m->res_len < res_len)
+ res_len = m->res_len;
} else {
printf("Unknown IMSI: %s\n", imsi);
#ifdef AKA_USE_FIXED_TEST_VALUES
diff --git a/hostapd/hlr_auc_gw.milenage_db b/hostapd/hlr_auc_gw.milenage_db
index ecd06d7..c156a29 100644
--- a/hostapd/hlr_auc_gw.milenage_db
+++ b/hostapd/hlr_auc_gw.milenage_db
@@ -5,8 +5,10 @@
# authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but
# dummy values will need to be included in this file.
-# IMSI Ki OPc AMF SQN
+# IMSI Ki OPc AMF SQN [RES_len]
232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
+# Example using truncated 32-bit RES instead of 64-bit default
+232010000000001 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000 4
# These values are from Test Set 19 which has the AMF separation bit set to 1
# and as such, is suitable for EAP-AKA' test.
diff --git a/hs20/client/Makefile b/hs20/client/Makefile
index ca67b54..94cd5f1 100644
--- a/hs20/client/Makefile
+++ b/hs20/client/Makefile
@@ -67,7 +67,13 @@
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
LIBS += -lssl -lcrypto
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index de7f351..5cd823e 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -25,6 +25,8 @@
#include "crypto/sha256.h"
#include "osu_client.h"
+const char *spp_xsd_fname = "spp.xsd";
+
void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
{
@@ -547,8 +549,9 @@
wpa_printf(MSG_INFO, "SP FQDN: %s", fqdn);
if (!server_dnsname_suffix_match(ctx, fqdn)) {
- wpa_printf(MSG_INFO, "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values",
- fqdn);
+ wpa_printf(MSG_INFO,
+ "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values, count: %d",
+ fqdn, (int) ctx->server_dnsname_count);
write_result(ctx, "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values",
fqdn);
free(fqdn);
@@ -2094,10 +2097,14 @@
}
ctx->no_reconnect = 1;
- if (methods & 0x02)
+ if (methods & 0x02) {
+ wpa_printf(MSG_DEBUG, "Calling cmd_prov from osu_connect");
res = cmd_prov(ctx, url);
- else if (methods & 0x01)
+ } else if (methods & 0x01) {
+ wpa_printf(MSG_DEBUG,
+ "Calling cmd_oma_dm_prov from osu_connect");
res = cmd_oma_dm_prov(ctx, url);
+ }
wpa_printf(MSG_INFO, "Remove OSU network connection");
write_summary(ctx, "Remove OSU network connection");
@@ -2139,7 +2146,7 @@
snprintf(fname, sizeof(fname), "%s/osu-providers.txt", dir);
osu = parse_osu_providers(fname, &osu_count);
if (osu == NULL) {
- wpa_printf(MSG_INFO, "Could not any OSU providers from %s",
+ wpa_printf(MSG_INFO, "Could not find any OSU providers from %s",
fname);
write_result(ctx, "No OSU providers available");
return -1;
@@ -2290,12 +2297,19 @@
}
if (connect == 2) {
- if (last->methods & 0x02)
+ if (last->methods & 0x02) {
+ wpa_printf(MSG_DEBUG,
+ "Calling cmd_prov from cmd_osu_select");
ret = cmd_prov(ctx, last->url);
- else if (last->methods & 0x01)
+ } else if (last->methods & 0x01) {
+ wpa_printf(MSG_DEBUG,
+ "Calling cmd_oma_dm_prov from cmd_osu_select");
ret = cmd_oma_dm_prov(ctx, last->url);
- else
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "No supported OSU provisioning method");
ret = -1;
+ }
} else if (connect)
ret = osu_connect(ctx, last->bssid, last->osu_ssid,
last->url, last->methods,
@@ -2810,17 +2824,21 @@
char *name = ctx->icon_filename[j];
size_t name_len = os_strlen(name);
- wpa_printf(MSG_INFO, "Looking for icon file name '%s' match",
- name);
+ wpa_printf(MSG_INFO,
+ "[%i] Looking for icon file name '%s' match",
+ j, name);
for (i = 0; i < cert->num_logo; i++) {
struct http_logo *logo = &cert->logo[i];
size_t uri_len = os_strlen(logo->uri);
char *pos;
- wpa_printf(MSG_INFO, "Comparing to '%s' uri_len=%d name_len=%d",
- logo->uri, (int) uri_len, (int) name_len);
- if (uri_len < 1 + name_len)
+ wpa_printf(MSG_INFO,
+ "[%i] Comparing to '%s' uri_len=%d name_len=%d",
+ i, logo->uri, (int) uri_len, (int) name_len);
+ if (uri_len < 1 + name_len) {
+ wpa_printf(MSG_INFO, "URI Length is too short");
continue;
+ }
pos = &logo->uri[uri_len - name_len - 1];
if (*pos != '/')
continue;
@@ -2847,17 +2865,30 @@
for (i = 0; i < cert->num_logo; i++) {
struct http_logo *logo = &cert->logo[i];
- if (logo->hash_len != 32)
+ if (logo->hash_len != 32) {
+ wpa_printf(MSG_INFO,
+ "[%i][%i] Icon hash length invalid (should be 32): %d",
+ j, i, (int) logo->hash_len);
continue;
+ }
if (os_memcmp(logo->hash, ctx->icon_hash[j], 32) == 0) {
found = 1;
break;
}
+
+ wpa_printf(MSG_DEBUG,
+ "[%u][%u] Icon hash did not match", j, i);
+ wpa_hexdump_ascii(MSG_DEBUG, "logo->hash",
+ logo->hash, 32);
+ wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]",
+ ctx->icon_hash[j], 32);
}
if (!found) {
- wpa_printf(MSG_INFO, "No icon hash match found");
- write_result(ctx, "No icon hash match found");
+ wpa_printf(MSG_INFO,
+ "No icon hash match (by hash) found");
+ write_result(ctx,
+ "No icon hash match (by hash) found");
return -1;
}
}
@@ -2955,6 +2986,7 @@
" [-w<wpa_supplicant ctrl_iface dir>] "
"[-r<result file>] [-f<debug file>] \\\n"
" [-s<summary file>] \\\n"
+ " [-x<spp.xsd file name>] \\\n"
" <command> [arguments..]\n"
"commands:\n"
"- to_tnds <XML MO> <XML MO in TNDS format> [URN]\n"
@@ -2996,7 +3028,7 @@
return -1;
for (;;) {
- c = getopt(argc, argv, "df:hi:KNO:qr:s:S:tw:");
+ c = getopt(argc, argv, "df:hKNO:qr:s:S:tw:x:");
if (c < 0)
break;
switch (c) {
@@ -3034,6 +3066,9 @@
case 'w':
wpas_ctrl_path = optarg;
break;
+ case 'x':
+ spp_xsd_fname = optarg;
+ break;
case 'h':
default:
usage();
@@ -3108,6 +3143,7 @@
exit(0);
}
ctx.ca_fname = argv[optind + 2];
+ wpa_printf(MSG_DEBUG, "Calling cmd_prov from main");
cmd_prov(&ctx, argv[optind + 1]);
} else if (strcmp(argv[optind], "sim_prov") == 0) {
if (argc - optind < 2) {
diff --git a/hs20/client/spp_client.c b/hs20/client/spp_client.c
index 302a050..cc1a0bf 100644
--- a/hs20/client/spp_client.c
+++ b/hs20/client/spp_client.c
@@ -21,6 +21,8 @@
#include "osu_client.h"
+extern const char *spp_xsd_fname;
+
static int hs20_spp_update_response(struct hs20_osu_client *ctx,
const char *session_id,
const char *spp_status,
@@ -59,7 +61,7 @@
return -1;
}
- ret = xml_validate(xctx, node, "spp.xsd", &err);
+ ret = xml_validate(xctx, node, spp_xsd_fname, &err);
if (ret < 0) {
wpa_printf(MSG_INFO, "XML schema validation error(s)\n%s", err);
write_summary(ctx, "SPP XML schema validation failed");
@@ -952,7 +954,9 @@
return -1;
}
- wpa_printf(MSG_INFO, "Credential provisioning requested");
+ wpa_printf(MSG_INFO,
+ "Credential provisioning requested - URL: %s ca_fname: %s",
+ url, ctx->ca_fname ? ctx->ca_fname : "N/A");
os_free(ctx->server_url);
ctx->server_url = os_strdup(url);
diff --git a/hs20/server/ca/clean.sh b/hs20/server/ca/clean.sh
old mode 100644
new mode 100755
index c69a1f5..c72dcbd
--- a/hs20/server/ca/clean.sh
+++ b/hs20/server/ca/clean.sh
@@ -5,6 +5,9 @@
done
rm -f openssl.cnf.tmp
-rm -r demoCA
+if [ -d demoCA ]; then
+ rm -r demoCA
+fi
rm -f ca.pem logo.asn1 logo.der server.der ocsp-server-cache.der
+rm -f my-openssl.cnf my-openssl-root.cnf
#rm -r rootCA
diff --git a/hs20/server/ca/openssl-root.cnf b/hs20/server/ca/openssl-root.cnf
index 5b220fe..5bc50be 100644
--- a/hs20/server/ca/openssl-root.cnf
+++ b/hs20/server/ca/openssl-root.cnf
@@ -69,8 +69,8 @@
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
-input_password = whatever
-output_password = whatever
+input_password = @PASSWORD@
+output_password = @PASSWORD@
string_mask = utf8only
diff --git a/hs20/server/ca/openssl.cnf b/hs20/server/ca/openssl.cnf
index a939f08..6141013 100644
--- a/hs20/server/ca/openssl.cnf
+++ b/hs20/server/ca/openssl.cnf
@@ -80,8 +80,8 @@
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
-input_password = whatever
-output_password = whatever
+input_password = @PASSWORD@
+output_password = @PASSWORD@
string_mask = utf8only
@@ -95,7 +95,7 @@
localityName_default = Tuusula
0.organizationName = Organization Name (eg, company)
-0.organizationName_default = w1.fi
+0.organizationName_default = @DOMAIN@
##organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
@@ -117,10 +117,10 @@
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, cRLSign, keyCertSign
-authorityInfoAccess = OCSP;URI:http://osu.w1.fi:8888/
+authorityInfoAccess = OCSP;URI:@OCSP_URI@
# For SP intermediate CA
#subjectAltName=critical,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:engExample OSU
-#nameConstraints=permitted;DNS:.w1.fi
+#nameConstraints=permitted;DNS:.@DOMAIN@
#1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn
[ v3_osu_server ]
@@ -150,16 +150,16 @@
#value2=SEQUENCE:HashAlgAndValueSHA1
[HashAlgAndValueSHA256]
hashAlg=SEQUENCE:sha256_alg
-hashValue=FORMAT:HEX,OCTETSTRING:4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d
+hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH256@
[HashAlgAndValueSHA1]
hashAlg=SEQUENCE:sha1_alg
-hashValue=FORMAT:HEX,OCTETSTRING:5e1d5085676eede6b02da14d31c523ec20ffba0b
+hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH1@
[sha256_alg]
algorithm=OID:sha256
[sha1_alg]
algorithm=OID:sha1
[URI]
-uri=IA5STRING:http://osu.w1.fi/w1fi_logo.png
+uri=IA5STRING:@LOGO_URI@
[LogotypeImageInfo]
# default value color(1), component optional
#type=IMP:0,INTEGER:1
@@ -184,7 +184,7 @@
basicConstraints=CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
-authorityInfoAccess = OCSP;URI:http://osu.w1.fi:8888/
+authorityInfoAccess = OCSP;URI:@OCSP_URI@
#@ALTNAME@
extendedKeyUsage = clientAuth
@@ -194,7 +194,7 @@
basicConstraints=critical, CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
-authorityInfoAccess = OCSP;URI:http://osu.w1.fi:8888/
+authorityInfoAccess = OCSP;URI:@OCSP_URI@
#@ALTNAME@
extendedKeyUsage = critical, serverAuth
keyUsage = critical, keyEncipherment
diff --git a/hs20/server/ca/setup.sh b/hs20/server/ca/setup.sh
old mode 100644
new mode 100755
index f61bf73..78abccc
--- a/hs20/server/ca/setup.sh
+++ b/hs20/server/ca/setup.sh
@@ -5,6 +5,67 @@
fi
export OPENSSL_CONF=$PWD/openssl.cnf
PASS=whatever
+if [ -z "$DOMAIN" ]; then
+ DOMAIN=w1.fi
+fi
+COMPANY=w1.fi
+OPER_ENG="engw1.fi TESTING USE"
+OPER_FI="finw1.fi TESTIKÄYTTÖ"
+CNR="Hotspot 2.0 Trust Root CA - 99"
+CNO="ocsp.$DOMAIN"
+CNV="osu-revoked.$DOMAIN"
+CNOC="osu-client.$DOMAIN"
+OSU_SERVER_HOSTNAME="osu.$DOMAIN"
+DEBUG=0
+OCSP_URI="http://$CNO:8888/"
+LOGO_URI="http://osu.w1.fi/w1fi_logo.png"
+LOGO_HASH256="4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d"
+LOGO_HASH1="5e1d5085676eede6b02da14d31c523ec20ffba0b"
+
+# Command line overrides
+USAGE=$( cat <<EOF
+Usage:\n
+# -c: Company name, used to generate Subject name CN for Intermediate CA\n
+# -C: Subject name CN of the Root CA ($CNR)\n
+# -D: Enable debugging (set -x, etc)\n
+# -g: Logo sha1 hash ($LOGO_HASH1)\n
+# -G: Logo sha256 hash ($LOGO_HASH256)\n
+# -h: Show this help message\n
+# -l: Logo URI ($LOGO_URI)\n
+# -m: Domain ($DOMAIN)\n
+# -o: Subject name CN for OSU-Client Server ($CNOC)\n
+# -O: Subject name CN for OCSP Server ($CNO)\n
+# -p: passphrase for private keys ($PASS)\n
+# -r: Operator-english ($OPER_ENG)\n
+# -R: Operator-finish ($OPER_FI)\n
+# -S: OSU Server name ($OSU_SERVER_HOSTNAME)\n
+# -u: OCSP-URI ($OCSP_URI)\n
+# -V: Subject name CN for OSU-Revoked Server ($CNV)\n
+EOF
+)
+
+while getopts "c:C:Dg:G:l:m:o:O:p:r:R:S:u:V:h" flag
+ do
+ case $flag in
+ c) COMPANY=$OPTARG;;
+ C) CNR=$OPTARG;;
+ D) DEBUG=1;;
+ g) LOGO_HASH1=$OPTARG;;
+ G) LOGO_HASH256=$OPTARG;;
+ h) echo -e $USAGE; exit 0;;
+ l) LOGO_URI=$OPTARG;;
+ m) DOMAIN=$OPTARG;;
+ o) CNOC=$OPTARG;;
+ O) CNO=$OPTARG;;
+ p) PASS=$OPTARG;;
+ r) OPER_ENG=$OPTARG;;
+ R) OPER_FI=$OPTARG;;
+ S) OSU_SERVER_HOSTNAME=$OPTARG;;
+ u) OCSP_URI=$OPTARG;;
+ V) CNV=$OPTARG;;
+ *) echo "Unknown flag: $flag"; echo -e $USAGE; exit 1;;
+ esac
+done
fail()
{
@@ -16,7 +77,25 @@
echo "---[ Root CA ]----------------------------------------------------------"
echo
-cat openssl-root.cnf | sed "s/#@CN@/commonName_default = Hotspot 2.0 Trust Root CA - 99/" > openssl.cnf.tmp
+if [ $DEBUG = 1 ]
+then
+ set -x
+fi
+
+# Set the passphrase and some other common config accordingly.
+cat openssl-root.cnf | sed "s/@PASSWORD@/$PASS/" \
+ > my-openssl-root.cnf
+
+cat openssl.cnf | sed "s/@PASSWORD@/$PASS/" |
+sed "s,@OCSP_URI@,$OCSP_URI," |
+sed "s,@LOGO_URI@,$LOGO_URI," |
+sed "s,@LOGO_HASH1@,$LOGO_HASH1," |
+sed "s,@LOGO_HASH256@,$LOGO_HASH256," |
+sed "s/@DOMAIN@/$DOMAIN/" \
+ > my-openssl.cnf
+
+
+cat my-openssl-root.cnf | sed "s/#@CN@/commonName_default = $CNR/" > openssl.cnf.tmp
mkdir -p rootCA/certs rootCA/crl rootCA/newcerts rootCA/private
touch rootCA/index.txt
if [ -e rootCA/private/cakey.pem ]; then
@@ -26,6 +105,8 @@
$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:4096 -keyout rootCA/private/cakey.pem -out rootCA/careq.pem || fail "Failed to generate Root CA private key"
echo " * Sign Root CA certificate"
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out rootCA/cacert.pem -days 10957 -batch -keyfile rootCA/private/cakey.pem -passin pass:$PASS -selfsign -extensions v3_ca -outdir rootCA/newcerts -infiles rootCA/careq.pem || fail "Failed to sign Root CA certificate"
+ $OPENSSL x509 -in rootCA/cacert.pem -out rootCA/cacert.der -outform DER || fail "Failed to create rootCA DER"
+ sha256sum rootCA/cacert.der > rootCA/cacert.fingerprint || fail "Failed to create rootCA fingerprint"
fi
if [ ! -e rootCA/crlnumber ]; then
echo 00 > rootCA/crlnumber
@@ -35,7 +116,7 @@
echo "---[ Intermediate CA ]--------------------------------------------------"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = w1.fi Hotspot 2.0 Intermediate CA/" > openssl.cnf.tmp
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $COMPANY Hotspot 2.0 Intermediate CA/" > openssl.cnf.tmp
mkdir -p demoCA/certs demoCA/crl demoCA/newcerts demoCA/private
touch demoCA/index.txt
if [ -e demoCA/private/cakey.pem ]; then
@@ -47,6 +128,8 @@
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out demoCA/cacert.pem -days 3652 -batch -keyfile rootCA/private/cakey.pem -cert rootCA/cacert.pem -passin pass:$PASS -extensions v3_ca -infiles demoCA/careq.pem || fail "Failed to sign Intermediate CA certificate"
# horrible from security view point, but for testing purposes since OCSP responder does not seem to support -passin
openssl rsa -in demoCA/private/cakey.pem -out demoCA/private/cakey-plain.pem -passin pass:$PASS
+ $OPENSSL x509 -in demoCA/cacert.pem -out demoCA/cacert.der -outform DER || fail "Failed to create demoCA DER."
+ sha256sum demoCA/cacert.der > demoCA/cacert.fingerprint || fail "Failed to create demoCA fingerprint"
fi
if [ ! -e demoCA/crlnumber ]; then
echo 00 > demoCA/crlnumber
@@ -56,45 +139,46 @@
echo "OCSP responder"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = ocsp.w1.fi/" > openssl.cnf.tmp
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNO/" > openssl.cnf.tmp
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out ocsp.csr -keyout ocsp.key -extensions v3_OCSP
-$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -keyfile demoCA/private/cakey.pem -passin pass:$PASS -in ocsp.csr -out ocsp.pem -days 730 -extensions v3_OCSP
+$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -keyfile demoCA/private/cakey.pem -passin pass:$PASS -in ocsp.csr -out ocsp.pem -days 730 -extensions v3_OCSP || fail "Could not generate ocsp.pem"
echo
echo "---[ Server - to be revoked ] ------------------------------------------"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = osu-revoked.w1.fi/" > openssl.cnf.tmp
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNV/" > openssl.cnf.tmp
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-revoked.csr -keyout server-revoked.key
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-revoked.csr -out server-revoked.pem -key $PASS -days 730 -extensions ext_server
$OPENSSL ca -revoke server-revoked.pem -key $PASS
echo
echo "---[ Server - with client ext key use ] ---------------------------------"
+echo "---[ Only used for negative-testing for OSU-client implementation ] -----"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = osu-client.w1.fi/" > openssl.cnf.tmp
-$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-client.csr -keyout server-client.key
-$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-client.csr -out server-client.pem -key $PASS -days 730 -extensions ext_client
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNOC/" > openssl.cnf.tmp
+$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-client.csr -keyout server-client.key || fail "Could not create server-client.key"
+$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-client.csr -out server-client.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create server-client.pem"
echo
echo "---[ User ]-------------------------------------------------------------"
echo
-cat openssl.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp
-$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out user.csr -keyout user.key
-$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in user.csr -out user.pem -key $PASS -days 730 -extensions ext_client
+cat my-openssl.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp
+$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out user.csr -keyout user.key || fail "Could not create user.key"
+$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in user.csr -out user.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create user.pem"
echo
echo "---[ Server ]-----------------------------------------------------------"
echo
-ALT="DNS:osu.w1.fi"
-ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:engw1.fi TESTING USE"
-ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:finw1.fi TESTIKÄYTTÖ"
+ALT="DNS:$OSU_SERVER_HOSTNAME"
+ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_ENG"
+ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_FI"
-cat openssl.cnf |
- sed "s/#@CN@/commonName_default = osu.w1.fi/" |
+cat my-openssl.cnf |
+ sed "s/#@CN@/commonName_default = $OSU_SERVER_HOSTNAME/" |
sed "s/^##organizationalUnitName/organizationalUnitName/" |
sed "s/#@OU@/organizationalUnitName_default = Hotspot 2.0 Online Sign Up Server/" |
sed "s/#@ALTNAME@/subjectAltName=critical,$ALT/" \
@@ -113,7 +197,7 @@
echo "---[ CRL ]---------------------------------------------------------------"
echo
-$OPENSSL ca -config $PWD/openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS
+$OPENSSL ca -config $PWD/my-openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS
echo
echo "---[ Verify ]------------------------------------------------------------"
diff --git a/hs20/server/hs20-osu-server.txt b/hs20/server/hs20-osu-server.txt
index 80985f7..001d6f2 100644
--- a/hs20/server/hs20-osu-server.txt
+++ b/hs20/server/hs20-osu-server.txt
@@ -100,6 +100,21 @@
# the examples as-is for initial testing).
cp -r www /home/user/hs20-server
+# Build local keys and certs
+cd ca
+# Display help options.
+./setup.sh -h
+
+# Remove old keys, fill in appropriate values, and generate your keys.
+# For instance:
+./clean.sh
+rm -fr rootCA"
+old_hostname=myserver.local
+./setup.sh -C "Hotspot 2.0 Trust Root CA - CT" -d $old_hostname \
+ -I "Hotspot 2.0 Intermediate CA - CT" -o $old_hostname-osu-client \
+ -O $old_hostname-oscp -p lanforge -S $old_hostname \
+ -V $old_hostname-osu-revoked \
+ -m local -u http://$old_hostname:8888/
# Configure subscription policies
mkdir -p /home/user/hs20-server/spp/policy
@@ -156,6 +171,50 @@
./hostapd -B as-sql.conf
+OSEN RADIUS server configuration notes
+
+The OSEN RADIUS server config file should have the 'ocsp_stapling_response'
+configuration in it. For example:
+
+# hostapd-radius config for the radius used by the OSEN AP
+interface=eth0#0
+driver=none
+logger_syslog=-1
+logger_syslog_level=2
+logger_stdout=-1
+logger_stdout_level=2
+ctrl_interface=/var/run/hostapd
+ctrl_interface_group=0
+eap_server=1
+eap_user_file=/home/user/hs20-server/AS/hostapd-osen.eap_user
+server_id=ben-ota-2-osen
+radius_server_auth_port=1811
+radius_server_clients=/home/user/hs20-server/AS/hostap.radius_clients
+
+ca_cert=/home/user/hs20-server/ca/ca.pem
+server_cert=/home/user/hs20-server/ca/server.pem
+private_key=/home/user/hs20-server/ca/server.key
+private_key_passwd=whatever
+
+ocsp_stapling_response=/home/user/hs20-server/ca/ocsp-server-cache.der
+
+The /home/user/hs20-server/AS/hostapd-osen.eap_user file should look
+similar to this, and should coorelate with the osu_nai entry in
+the non-OSEN VAP config file. For instance:
+
+# cat hostapd-osen.eap_user
+# For OSEN authentication (Hotspot 2.0 Release 2)
+"osen@w1.fi" WFA-UNAUTH-TLS
+
+
+# Run OCSP server:
+cd /home/user/hs20-server/ca
+./ocsp-responder.sh&
+
+# Update cache (This should be run periodically)
+./ocsp-update-cache.sh
+
+
Configure web server
--------------------
@@ -172,6 +231,8 @@
</Directory>
Update SSL configuration to use the OSU server certificate/key.
+They keys and certs are called 'server.key' and 'server.pem' from
+ca/setup.sh.
Enable default-ssl site and restart Apache2:
sudo a2ensite default-ssl
diff --git a/hs20/server/spp_server.c b/hs20/server/spp_server.c
index 8a2abf1..33e3fa1 100644
--- a/hs20/server/spp_server.c
+++ b/hs20/server/spp_server.c
@@ -2196,7 +2196,9 @@
session_id = xml_node_get_attr_value_ns(ctx->xml, node,
SPP_NS_URI,
"sessionID");
- debug_print(ctx, 1, "SPP message failed validation");
+ debug_print(ctx, 1,
+ "SPP message failed validation, xsd file: %s xml-error: %s",
+ fname, xml_err);
hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
"SPP message failed validation", node);
hs20_eventlog(ctx, auth_user, auth_realm, session_id,
diff --git a/hs20/server/www/signup.php b/hs20/server/www/signup.php
index a626704..aeb2f68 100644
--- a/hs20/server/www/signup.php
+++ b/hs20/server/www/signup.php
@@ -17,7 +17,7 @@
$row = $db->query("SELECT realm FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
- die("Session not found");
+ die("Session not found for id: $id");
}
$realm = $row['realm'];
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index bd1778e..f10e1b7 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -55,10 +55,11 @@
{
const struct hostapd_eap_user *eap_user;
int i;
+ int rv = -1;
eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
if (eap_user == NULL)
- return -1;
+ goto out;
if (user == NULL)
return 0;
@@ -72,7 +73,7 @@
if (eap_user->password) {
user->password = os_malloc(eap_user->password_len);
if (user->password == NULL)
- return -1;
+ goto out;
os_memcpy(user->password, eap_user->password,
eap_user->password_len);
user->password_len = eap_user->password_len;
@@ -83,8 +84,13 @@
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
user->accept_attr = eap_user->accept_attr;
+ rv = 0;
- return 0;
+out:
+ if (rv)
+ wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
+
+ return rv;
}
diff --git a/src/ap/eap_user_db.c b/src/ap/eap_user_db.c
index 559d77f..082d0f5 100644
--- a/src/ap/eap_user_db.c
+++ b/src/ap/eap_user_db.c
@@ -138,8 +138,12 @@
char id_str[256], cmd[300];
size_t i;
- if (identity_len >= sizeof(id_str))
+ if (identity_len >= sizeof(id_str)) {
+ wpa_printf(MSG_DEBUG, "%s: identity len too big: %d >= %d",
+ __func__, (int) identity_len,
+ (int) (sizeof(id_str)));
return NULL;
+ }
os_memcpy(id_str, identity, identity_len);
id_str[identity_len] = '\0';
for (i = 0; i < identity_len; i++) {
@@ -182,7 +186,9 @@
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
SQLITE_OK) {
- wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL operation");
+ wpa_printf(MSG_DEBUG,
+ "DB: Failed to complete SQL operation: %s db: %s",
+ sqlite3_errmsg(db), hapd->conf->eap_user_sqlite);
} else if (hapd->tmp_eap_user.next)
user = &hapd->tmp_eap_user;
@@ -192,8 +198,10 @@
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
NULL) != SQLITE_OK) {
- wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL "
- "operation");
+ wpa_printf(MSG_DEBUG,
+ "DB: Failed to complete SQL operation: %s db: %s",
+ sqlite3_errmsg(db),
+ hapd->conf->eap_user_sqlite);
} else if (hapd->tmp_eap_user.next) {
user = &hapd->tmp_eap_user;
os_free(user->identity);
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 0f67ab8..ca7f22b 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -36,6 +36,11 @@
return -1;
}
+static inline int hostapd_acs_completed(struct hostapd_iface *iface, int err)
+{
+ return -1;
+}
+
static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
{
return -100;
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 4b0653d..9dad8e3 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -209,7 +209,7 @@
struct hostapd_iface *iface = hapd->iface;
struct ieee80211_2040_bss_coex_ie *bc_ie;
struct ieee80211_2040_intol_chan_report *ic_report;
- int is_ht_allowed = 1;
+ int is_ht40_allowed = 1;
int i;
const u8 *start = (const u8 *) mgmt;
const u8 *data = start + IEEE80211_HDRLEN + 2;
@@ -242,7 +242,7 @@
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"20 MHz BSS width request bit is set in BSS coexistence information field");
- is_ht_allowed = 0;
+ is_ht40_allowed = 0;
}
if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_40MHZ_INTOL) {
@@ -250,7 +250,7 @@
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"40 MHz intolerant bit is set in BSS coexistence information field");
- is_ht_allowed = 0;
+ is_ht40_allowed = 0;
}
if (start + len - data >= 3 &&
@@ -276,13 +276,13 @@
HOSTAPD_LEVEL_DEBUG,
"20_40_INTOLERANT channel %d reported",
chan);
- is_ht_allowed = 0;
+ is_ht40_allowed = 0;
}
}
- wpa_printf(MSG_DEBUG, "is_ht_allowed=%d num_sta_ht40_intolerant=%d",
- is_ht_allowed, iface->num_sta_ht40_intolerant);
+ wpa_printf(MSG_DEBUG, "is_ht40_allowed=%d num_sta_ht40_intolerant=%d",
+ is_ht40_allowed, iface->num_sta_ht40_intolerant);
- if (!is_ht_allowed &&
+ if (!is_ht40_allowed &&
(iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) {
if (iface->conf->secondary_channel) {
hostapd_logger(hapd, mgmt->sa,
@@ -312,10 +312,14 @@
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab, size_t ht_capab_len)
{
- /* Disable HT caps for STAs associated to no-HT BSSes. */
+ /*
+ * Disable HT caps for STAs associated to no-HT BSSes, or for stations
+ * that did not specify a valid WMM IE in the (Re)Association Request
+ * frame.
+ */
if (!ht_capab ||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities) ||
- hapd->conf->disable_11n) {
+ !(sta->flags & WLAN_STA_WMM) || hapd->conf->disable_11n) {
sta->flags &= ~WLAN_STA_HT;
os_free(sta->ht_capabilities);
sta->ht_capabilities = NULL;
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 79dc0f9..7e17ef4 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1926,10 +1926,11 @@
struct hostapd_data *hapd = ctx;
const struct hostapd_eap_user *eap_user;
int i;
+ int rv = -1;
eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2);
if (eap_user == NULL)
- return -1;
+ goto out;
os_memset(user, 0, sizeof(*user));
user->phase2 = phase2;
@@ -1941,7 +1942,7 @@
if (eap_user->password) {
user->password = os_malloc(eap_user->password_len);
if (user->password == NULL)
- return -1;
+ goto out;
os_memcpy(user->password, eap_user->password,
eap_user->password_len);
user->password_len = eap_user->password_len;
@@ -1951,8 +1952,13 @@
user->macacl = eap_user->macacl;
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
+ rv = 0;
- return 0;
+out:
+ if (rv)
+ wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
+
+ return rv;
}
diff --git a/src/common/defs.h b/src/common/defs.h
index b5f4f80..24f80ad 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -310,6 +310,7 @@
WPA_CTRL_REQ_EAP_OTP,
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
+ WPA_CTRL_REQ_PSK_PASSPHRASE,
NUM_WPA_CTRL_REQS
};
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 5534eab..0368904 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -486,6 +486,8 @@
return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
+ return WPA_KEY_MGMT_OSEN;
return 0;
}
@@ -520,7 +522,6 @@
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data)
{
- const struct rsn_ie_hdr *hdr;
const u8 *pos;
int left;
int i, count;
@@ -550,19 +551,30 @@
return -1;
}
- hdr = (const struct rsn_ie_hdr *) rsn_ie;
+ if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 &&
+ rsn_ie[1] == rsn_ie_len - 2 &&
+ WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) {
+ pos = rsn_ie + 6;
+ left = rsn_ie_len - 6;
- if (hdr->elem_id != WLAN_EID_RSN ||
- hdr->len != rsn_ie_len - 2 ||
- WPA_GET_LE16(hdr->version) != RSN_VERSION) {
- wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
- __func__);
- return -2;
+ data->proto = WPA_PROTO_OSEN;
+ } else {
+ const struct rsn_ie_hdr *hdr;
+
+ hdr = (const struct rsn_ie_hdr *) rsn_ie;
+
+ if (hdr->elem_id != WLAN_EID_RSN ||
+ hdr->len != rsn_ie_len - 2 ||
+ WPA_GET_LE16(hdr->version) != RSN_VERSION) {
+ wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
+ __func__);
+ return -2;
+ }
+
+ pos = (const u8 *) (hdr + 1);
+ left = rsn_ie_len - sizeof(*hdr);
}
- pos = (const u8 *) (hdr + 1);
- left = rsn_ie_len - sizeof(*hdr);
-
if (left >= RSN_SELECTOR_LEN) {
data->group_cipher = rsn_selector_to_bitfield(pos);
if (!wpa_cipher_valid_group(data->group_cipher)) {
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index f158ef4..9834b25 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -324,6 +324,56 @@
}
+int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+ EVP_CIPHER_CTX ctx;
+ int clen, len;
+ u8 buf[16];
+
+ EVP_CIPHER_CTX_init(&ctx);
+ if (EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
+ return -1;
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ clen = data_len;
+ if (EVP_EncryptUpdate(&ctx, data, &clen, data, data_len) != 1 ||
+ clen != (int) data_len)
+ return -1;
+
+ len = sizeof(buf);
+ if (EVP_EncryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
+ return -1;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ return 0;
+}
+
+
+int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+ EVP_CIPHER_CTX ctx;
+ int plen, len;
+ u8 buf[16];
+
+ EVP_CIPHER_CTX_init(&ctx);
+ if (EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
+ return -1;
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ plen = data_len;
+ if (EVP_DecryptUpdate(&ctx, data, &plen, data, data_len) != 1 ||
+ plen != (int) data_len)
+ return -1;
+
+ len = sizeof(buf);
+ if (EVP_DecryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
+ return -1;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ return 0;
+}
+
+
int crypto_mod_exp(const u8 *base, size_t base_len,
const u8 *power, size_t power_len,
const u8 *modulus, size_t modulus_len,
diff --git a/src/crypto/ms_funcs.c b/src/crypto/ms_funcs.c
index 49a5c1c..5f57656 100644
--- a/src/crypto/ms_funcs.c
+++ b/src/crypto/ms_funcs.c
@@ -78,9 +78,8 @@
* @challenge: 8-octet Challenge (OUT)
* Returns: 0 on success, -1 on failure
*/
-static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
- const u8 *username, size_t username_len,
- u8 *challenge)
+int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
+ const u8 *username, size_t username_len, u8 *challenge)
{
u8 hash[SHA1_MAC_LEN];
const unsigned char *addr[3];
diff --git a/src/crypto/ms_funcs.h b/src/crypto/ms_funcs.h
index bd9bfee..b5b5918 100644
--- a/src/crypto/ms_funcs.h
+++ b/src/crypto/ms_funcs.h
@@ -33,6 +33,8 @@
void challenge_response(const u8 *challenge, const u8 *password_hash,
u8 *response);
+int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
+ const u8 *username, size_t username_len, u8 *challenge);
int nt_password_hash(const u8 *password, size_t password_len,
u8 *password_hash);
int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash);
diff --git a/src/crypto/sha1-tlsprf.c b/src/crypto/sha1-tlsprf.c
index 0effd9b..f9bc0eb 100644
--- a/src/crypto/sha1-tlsprf.c
+++ b/src/crypto/sha1-tlsprf.c
@@ -95,5 +95,10 @@
SHA1_pos++;
}
+ os_memset(A_MD5, 0, MD5_MAC_LEN);
+ os_memset(P_MD5, 0, MD5_MAC_LEN);
+ os_memset(A_SHA1, 0, SHA1_MAC_LEN);
+ os_memset(P_SHA1, 0, SHA1_MAC_LEN);
+
return 0;
}
diff --git a/src/crypto/sha1-tprf.c b/src/crypto/sha1-tprf.c
index a529494..562510f 100644
--- a/src/crypto/sha1-tprf.c
+++ b/src/crypto/sha1-tprf.c
@@ -66,5 +66,7 @@
len[0] = SHA1_MAC_LEN;
}
+ os_memset(hash, 0, SHA1_MAC_LEN);
+
return 0;
}
diff --git a/src/crypto/sha256-kdf.c b/src/crypto/sha256-kdf.c
index d8a1beb..e7509ce 100644
--- a/src/crypto/sha256-kdf.c
+++ b/src/crypto/sha256-kdf.c
@@ -61,6 +61,7 @@
if (iter == 255) {
os_memset(out, 0, outlen);
+ os_memset(T, 0, SHA256_MAC_LEN);
return -1;
}
iter++;
@@ -68,9 +69,11 @@
if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0)
{
os_memset(out, 0, outlen);
+ os_memset(T, 0, SHA256_MAC_LEN);
return -1;
}
}
+ os_memset(T, 0, SHA256_MAC_LEN);
return 0;
}
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 9ae95a6..f9e2e10 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -12,8 +12,6 @@
struct tls_connection;
struct tls_keys {
- const u8 *master_key; /* TLS master secret */
- size_t master_key_len;
const u8 *client_random;
size_t client_random_len;
const u8 *server_random;
@@ -308,10 +306,10 @@
int verify_peer);
/**
- * tls_connection_get_keys - Get master key and random data from TLS connection
+ * tls_connection_get_keys - Get random data from TLS connection
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
- * @keys: Structure of key/random data (filled on success)
+ * @keys: Structure of client/server random data (filled on success)
* Returns: 0 on success, -1 on failure
*/
int __must_check tls_connection_get_keys(void *tls_ctx,
@@ -325,6 +323,7 @@
* @label: Label (e.g., description of the key) for PRF
* @server_random_first: seed is 0 = client_random|server_random,
* 1 = server_random|client_random
+ * @skip_keyblock: Skip TLS key block from the beginning of PRF output
* @out: Buffer for output data from TLS-PRF
* @out_len: Length of the output buffer
* Returns: 0 on success, -1 on failure
@@ -342,6 +341,7 @@
struct tls_connection *conn,
const char *label,
int server_random_first,
+ int skip_keyblock,
u8 *out, size_t out_len);
/**
@@ -528,16 +528,6 @@
struct tls_connection *conn);
/**
- * tls_connection_get_keyblock_size - Get TLS key_block size
- * @tls_ctx: TLS context data from tls_init()
- * @conn: Connection context data from tls_connection_init()
- * Returns: Size of the key_block for the negotiated cipher suite or -1 on
- * failure
- */
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn);
-
-/**
* tls_capabilities - Get supported TLS capabilities
* @tls_ctx: TLS context data from tls_init()
* Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*)
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index 65db6fc..c7f6464 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -747,9 +747,9 @@
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
- u8 *out, size_t out_len)
+ int skip_keyblock, u8 *out, size_t out_len)
{
- if (conn == NULL || conn->session == NULL)
+ if (conn == NULL || conn->session == NULL || skip_keyblock)
return -1;
return gnutls_prf(conn->session, os_strlen(label), label,
@@ -1476,14 +1476,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
- /* TODO */
- return -1;
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index 0c955da..afd4695 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -192,26 +192,31 @@
if (params->subject_match) {
wpa_printf(MSG_INFO, "TLS: subject_match not supported");
+ tlsv1_cred_free(cred);
return -1;
}
if (params->altsubject_match) {
wpa_printf(MSG_INFO, "TLS: altsubject_match not supported");
+ tlsv1_cred_free(cred);
return -1;
}
if (params->suffix_match) {
wpa_printf(MSG_INFO, "TLS: suffix_match not supported");
+ tlsv1_cred_free(cred);
return -1;
}
if (params->domain_match) {
wpa_printf(MSG_INFO, "TLS: domain_match not supported");
+ tlsv1_cred_free(cred);
return -1;
}
if (params->openssl_ciphers) {
- wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
+ wpa_printf(MSG_INFO, "TLS: openssl_ciphers not supported");
+ tlsv1_cred_free(cred);
return -1;
}
@@ -348,25 +353,57 @@
}
-int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
- const char *label, int server_random_first,
- u8 *out, size_t out_len)
+static int tls_get_keyblock_size(struct tls_connection *conn)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
+ if (conn->client)
+ return tlsv1_client_get_keyblock_size(conn->client);
+#endif /* CONFIG_TLS_INTERNAL_CLIENT */
+#ifdef CONFIG_TLS_INTERNAL_SERVER
+ if (conn->server)
+ return tlsv1_server_get_keyblock_size(conn->server);
+#endif /* CONFIG_TLS_INTERNAL_SERVER */
+ return -1;
+}
+
+
+int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+ const char *label, int server_random_first,
+ int skip_keyblock, u8 *out, size_t out_len)
+{
+ int ret = -1, skip = 0;
+ u8 *tmp_out = NULL;
+ u8 *_out = out;
+
+ if (skip_keyblock) {
+ skip = tls_get_keyblock_size(conn);
+ if (skip < 0)
+ return -1;
+ tmp_out = os_malloc(skip + out_len);
+ if (!tmp_out)
+ return -1;
+ _out = tmp_out;
+ }
+
+#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client) {
- return tlsv1_client_prf(conn->client, label,
- server_random_first,
- out, out_len);
+ ret = tlsv1_client_prf(conn->client, label,
+ server_random_first,
+ _out, out_len);
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server) {
- return tlsv1_server_prf(conn->server, label,
- server_random_first,
- out, out_len);
+ ret = tlsv1_server_prf(conn->server, label,
+ server_random_first,
+ _out, out_len);
}
#endif /* CONFIG_TLS_INTERNAL_SERVER */
- return -1;
+ if (ret == 0 && skip_keyblock)
+ os_memcpy(out, _out + skip, out_len);
+ bin_clear_free(tmp_out, skip);
+
+ return ret;
}
@@ -637,21 +674,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
-#ifdef CONFIG_TLS_INTERNAL_CLIENT
- if (conn->client)
- return tlsv1_client_get_keyblock_size(conn->client);
-#endif /* CONFIG_TLS_INTERNAL_CLIENT */
-#ifdef CONFIG_TLS_INTERNAL_SERVER
- if (conn->server)
- return tlsv1_server_get_keyblock_size(conn->server);
-#endif /* CONFIG_TLS_INTERNAL_SERVER */
- return -1;
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c
index a6d210a..1b1ba56 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -87,7 +87,7 @@
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
- u8 *out, size_t out_len)
+ int skip_keyblock, u8 *out, size_t out_len)
{
return -1;
}
@@ -181,13 +181,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
- return -1;
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 52db8fc..935add5 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -26,6 +26,7 @@
#include "common.h"
#include "crypto.h"
+#include "sha1.h"
#include "tls.h"
#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
@@ -2632,8 +2633,6 @@
return -1;
os_memset(keys, 0, sizeof(*keys));
- keys->master_key = ssl->session->master_key;
- keys->master_key_len = ssl->session->master_key_length;
keys->client_random = ssl->s3->client_random;
keys->client_random_len = SSL3_RANDOM_SIZE;
keys->server_random = ssl->s3->server_random;
@@ -2644,16 +2643,122 @@
}
+static int openssl_get_keyblock_size(SSL *ssl)
+{
+ const EVP_CIPHER *c;
+ const EVP_MD *h;
+ int md_size;
+
+ if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
+ ssl->read_hash == NULL)
+ return -1;
+
+ c = ssl->enc_read_ctx->cipher;
+#if OPENSSL_VERSION_NUMBER >= 0x00909000L
+ h = EVP_MD_CTX_md(ssl->read_hash);
+#else
+ h = conn->ssl->read_hash;
+#endif
+ if (h)
+ md_size = EVP_MD_size(h);
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ else if (ssl->s3)
+ md_size = ssl->s3->tmp.new_mac_secret_size;
+#endif
+ else
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
+ "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
+ EVP_CIPHER_iv_length(c));
+ return 2 * (EVP_CIPHER_key_length(c) +
+ md_size +
+ EVP_CIPHER_iv_length(c));
+}
+
+
+static int openssl_tls_prf(void *tls_ctx, struct tls_connection *conn,
+ const char *label, int server_random_first,
+ int skip_keyblock, u8 *out, size_t out_len)
+{
+#ifdef CONFIG_FIPS
+ wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS "
+ "mode");
+ return -1;
+#else /* CONFIG_FIPS */
+ SSL *ssl;
+ u8 *rnd;
+ int ret = -1;
+ int skip = 0;
+ u8 *tmp_out = NULL;
+ u8 *_out = out;
+
+ /*
+ * TLS library did not support key generation, so get the needed TLS
+ * session parameters and use an internal implementation of TLS PRF to
+ * derive the key.
+ */
+
+ if (conn == NULL)
+ return -1;
+ ssl = conn->ssl;
+ if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL ||
+ ssl->s3->client_random == NULL || ssl->s3->server_random == NULL ||
+ ssl->session->master_key == NULL)
+ return -1;
+
+ if (skip_keyblock) {
+ skip = openssl_get_keyblock_size(ssl);
+ if (skip < 0)
+ return -1;
+ tmp_out = os_malloc(skip + out_len);
+ if (!tmp_out)
+ return -1;
+ _out = tmp_out;
+ }
+
+ rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
+ if (rnd == NULL)
+ return -1;
+ if (server_random_first) {
+ os_memcpy(rnd, ssl->s3->server_random, SSL3_RANDOM_SIZE);
+ os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->client_random,
+ SSL3_RANDOM_SIZE);
+ } else {
+ os_memcpy(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE);
+ }
+
+ /* TODO: TLSv1.2 may need another PRF. This could use something closer
+ * to SSL_export_keying_material() design. */
+ if (tls_prf_sha1_md5(ssl->session->master_key,
+ ssl->session->master_key_length,
+ label, rnd, 2 * SSL3_RANDOM_SIZE,
+ _out, skip + out_len) == 0)
+ ret = 0;
+ os_free(rnd);
+ if (ret == 0 && skip_keyblock)
+ os_memcpy(out, _out + skip, out_len);
+ bin_clear_free(tmp_out, skip);
+
+ return ret;
+#endif /* CONFIG_FIPS */
+}
+
+
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
- u8 *out, size_t out_len)
+ int skip_keyblock, u8 *out, size_t out_len)
{
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
SSL *ssl;
if (conn == NULL)
return -1;
- if (server_random_first)
- return -1;
+ if (server_random_first || skip_keyblock)
+ return openssl_tls_prf(tls_ctx, conn, label,
+ server_random_first, skip_keyblock,
+ out, out_len);
ssl = conn->ssl;
if (SSL_export_keying_material(ssl, out, out_len, label,
os_strlen(label), NULL, 0, 0) == 1) {
@@ -2661,7 +2766,8 @@
return 0;
}
#endif
- return -1;
+ return openssl_tls_prf(tls_ctx, conn, label, server_random_first,
+ skip_keyblock, out, out_len);
}
@@ -3514,43 +3620,6 @@
}
-int tls_connection_get_keyblock_size(void *tls_ctx,
- struct tls_connection *conn)
-{
- const EVP_CIPHER *c;
- const EVP_MD *h;
- int md_size;
-
- if (conn == NULL || conn->ssl == NULL ||
- conn->ssl->enc_read_ctx == NULL ||
- conn->ssl->enc_read_ctx->cipher == NULL ||
- conn->ssl->read_hash == NULL)
- return -1;
-
- c = conn->ssl->enc_read_ctx->cipher;
-#if OPENSSL_VERSION_NUMBER >= 0x00909000L
- h = EVP_MD_CTX_md(conn->ssl->read_hash);
-#else
- h = conn->ssl->read_hash;
-#endif
- if (h)
- md_size = EVP_MD_size(h);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- else if (conn->ssl->s3)
- md_size = conn->ssl->s3->tmp.new_mac_secret_size;
-#endif
- else
- return -1;
-
- wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
- "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
- EVP_CIPHER_iv_length(c));
- return 2 * (EVP_CIPHER_key_length(c) +
- md_size +
- EVP_CIPHER_iv_length(c));
-}
-
-
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index a1581b8..22e1184 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -1,6 +1,6 @@
/*
* Driver interaction with generic Linux Wireless Extensions
- * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <net/if_arp.h>
+#include <dirent.h>
#include "linux_wext.h"
#include "common.h"
@@ -874,6 +875,105 @@
}
+static int wext_hostap_ifname(struct wpa_driver_wext_data *drv,
+ const char *ifname)
+{
+ char buf[200], *res;
+ int type;
+ FILE *f;
+
+ if (strcmp(ifname, ".") == 0 || strcmp(ifname, "..") == 0)
+ return -1;
+
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/net/%s/type",
+ drv->ifname, ifname);
+
+ f = fopen(buf, "r");
+ if (!f)
+ return -1;
+ res = fgets(buf, sizeof(buf), f);
+ fclose(f);
+
+ type = res ? atoi(res) : -1;
+ wpa_printf(MSG_DEBUG, "WEXT: hostap ifname %s type %d", ifname, type);
+
+ if (type == ARPHRD_IEEE80211) {
+ wpa_printf(MSG_DEBUG,
+ "WEXT: Found hostap driver wifi# interface (%s)",
+ ifname);
+ wpa_driver_wext_alternative_ifindex(drv, ifname);
+ return 0;
+ }
+ return -1;
+}
+
+
+static int wext_add_hostap(struct wpa_driver_wext_data *drv)
+{
+ char buf[200];
+ int n;
+ struct dirent **names;
+ int ret = -1;
+
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/net", drv->ifname);
+ n = scandir(buf, &names, NULL, alphasort);
+ if (n < 0)
+ return -1;
+
+ while (n--) {
+ if (ret < 0 && wext_hostap_ifname(drv, names[n]->d_name) == 0)
+ ret = 0;
+ free(names[n]);
+ }
+ free(names);
+
+ return ret;
+}
+
+
+static void wext_check_hostap(struct wpa_driver_wext_data *drv)
+{
+ char buf[200], *pos;
+ ssize_t res;
+
+ /*
+ * Host AP driver may use both wlan# and wifi# interface in wireless
+ * events. Since some of the versions included WE-18 support, let's add
+ * the alternative ifindex also from driver_wext.c for the time being.
+ * This may be removed at some point once it is believed that old
+ * versions of the driver are not in use anymore. However, it looks like
+ * the wifi# interface is still used in the current kernel tree, so it
+ * may not really be possible to remove this before the Host AP driver
+ * gets removed from the kernel.
+ */
+
+ /* First, try to see if driver information is available from sysfs */
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver",
+ drv->ifname);
+ res = readlink(buf, buf, sizeof(buf) - 1);
+ if (res > 0) {
+ buf[res] = '\0';
+ pos = strrchr(buf, '/');
+ if (pos)
+ pos++;
+ else
+ pos = buf;
+ wpa_printf(MSG_DEBUG, "WEXT: Driver: %s", pos);
+ if (os_strncmp(pos, "hostap", 6) == 0 &&
+ wext_add_hostap(drv) == 0)
+ return;
+ }
+
+ /* Second, use the old design with hardcoded ifname */
+ if (os_strncmp(drv->ifname, "wlan", 4) == 0) {
+ char ifname2[IFNAMSIZ + 1];
+ os_strlcpy(ifname2, drv->ifname, sizeof(ifname2));
+ os_memcpy(ifname2, "wifi", 4);
+ wpa_driver_wext_alternative_ifindex(drv, ifname2);
+ }
+}
+
+
static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
{
int send_rfkill_event = 0;
@@ -914,20 +1014,7 @@
drv->ifindex = if_nametoindex(drv->ifname);
- if (os_strncmp(drv->ifname, "wlan", 4) == 0) {
- /*
- * Host AP driver may use both wlan# and wifi# interface in
- * wireless events. Since some of the versions included WE-18
- * support, let's add the alternative ifindex also from
- * driver_wext.c for the time being. This may be removed at
- * some point once it is believed that old versions of the
- * driver are not in use anymore.
- */
- char ifname2[IFNAMSIZ + 1];
- os_strlcpy(ifname2, drv->ifname, sizeof(ifname2));
- os_memcpy(ifname2, "wifi", 4);
- wpa_driver_wext_alternative_ifindex(drv, ifname2);
- }
+ wext_check_hostap(drv);
netlink_send_oper_ifla(drv->netlink, drv->ifindex,
1, IF_OPER_DORMANT);
diff --git a/src/eap_common/eap_fast_common.c b/src/eap_common/eap_fast_common.c
index fceb1b0..151cc78 100644
--- a/src/eap_common/eap_fast_common.c
+++ b/src/eap_common/eap_fast_common.c
@@ -96,49 +96,18 @@
u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
const char *label, size_t len)
{
- struct tls_keys keys;
- u8 *rnd = NULL, *out;
- int block_size;
+ u8 *out;
- block_size = tls_connection_get_keyblock_size(ssl_ctx, conn);
- if (block_size < 0)
- return NULL;
-
- out = os_malloc(block_size + len);
+ out = os_malloc(len);
if (out == NULL)
return NULL;
- if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len)
- == 0) {
- os_memmove(out, out + block_size, len);
- return out;
+ if (tls_connection_prf(ssl_ctx, conn, label, 1, 1, out, len)) {
+ os_free(out);
+ return NULL;
}
- if (tls_connection_get_keys(ssl_ctx, conn, &keys))
- goto fail;
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- if (rnd == NULL)
- goto fail;
-
- os_memcpy(rnd, keys.server_random, keys.server_random_len);
- os_memcpy(rnd + keys.server_random_len, keys.client_random,
- keys.client_random_len);
-
- wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
- "expansion", keys.master_key, keys.master_key_len);
- if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
- label, rnd, keys.client_random_len +
- keys.server_random_len, out, block_size + len))
- goto fail;
- os_free(rnd);
- os_memmove(out, out + block_size, len);
return out;
-
-fail:
- os_free(rnd);
- os_free(out);
- return NULL;
}
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index 631c363..4d27623 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -86,9 +86,10 @@
* on the password and identities.
*/
int compute_password_element(EAP_PWD_group *grp, u16 num,
- u8 *password, int password_len,
- u8 *id_server, int id_server_len,
- u8 *id_peer, int id_peer_len, u8 *token)
+ const u8 *password, size_t password_len,
+ const u8 *id_server, size_t id_server_len,
+ const u8 *id_peer, size_t id_peer_len,
+ const u8 *token)
{
BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
struct crypto_hash *hash;
@@ -283,10 +284,10 @@
}
-int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
- BIGNUM *peer_scalar, BIGNUM *server_scalar,
- u8 *confirm_peer, u8 *confirm_server,
- u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id)
+int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, const BIGNUM *k,
+ const BIGNUM *peer_scalar, const BIGNUM *server_scalar,
+ const u8 *confirm_peer, const u8 *confirm_server,
+ const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id)
{
struct crypto_hash *hash;
u8 mk[SHA256_MAC_LEN], *cruft;
@@ -306,7 +307,7 @@
os_free(cruft);
return -1;
}
- eap_pwd_h_update(hash, (u8 *) ciphersuite, sizeof(u32));
+ eap_pwd_h_update(hash, (const u8 *) ciphersuite, sizeof(u32));
offset = BN_num_bytes(grp->order) - BN_num_bytes(peer_scalar);
os_memset(cruft, 0, BN_num_bytes(grp->prime));
BN_bn2bin(peer_scalar, cruft + offset);
diff --git a/src/eap_common/eap_pwd_common.h b/src/eap_common/eap_pwd_common.h
index c54c441..a0d717e 100644
--- a/src/eap_common/eap_pwd_common.h
+++ b/src/eap_common/eap_pwd_common.h
@@ -56,10 +56,15 @@
} STRUCT_PACKED;
/* common routines */
-int compute_password_element(EAP_PWD_group *, u16, u8 *, int, u8 *, int, u8 *,
- int, u8 *);
-int compute_keys(EAP_PWD_group *, BN_CTX *, BIGNUM *, BIGNUM *, BIGNUM *,
- u8 *, u8 *, u32 *, u8 *, u8 *, u8 *);
+int compute_password_element(EAP_PWD_group *grp, u16 num,
+ const u8 *password, size_t password_len,
+ const u8 *id_server, size_t id_server_len,
+ const u8 *id_peer, size_t id_peer_len,
+ const u8 *token);
+int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, const BIGNUM *k,
+ const BIGNUM *peer_scalar, const BIGNUM *server_scalar,
+ const u8 *confirm_peer, const u8 *confirm_server,
+ const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id);
struct crypto_hash * eap_pwd_h_init(void);
void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len);
void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest);
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 35433f3..fc4af95 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -2400,7 +2400,7 @@
u32 eap_get_phase2_type(const char *name, int *vendor)
{
int v;
- u8 type = eap_peer_get_type(name, &v);
+ u32 type = eap_peer_get_type(name, &v);
if (eap_allowed_phase2_type(v, type)) {
*vendor = v;
return type;
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 059bbee..f2b0926 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "crypto/sha256.h"
+#include "crypto/ms_funcs.h"
#include "eap_peer/eap_i.h"
#include "eap_common/eap_pwd_common.h"
@@ -25,6 +26,7 @@
size_t id_server_len;
u8 *password;
size_t password_len;
+ int password_hash;
u16 group_num;
EAP_PWD_group *grp;
@@ -86,8 +88,9 @@
const u8 *identity, *password;
size_t identity_len, password_len;
int fragment_size;
+ int pwhash;
- password = eap_get_config_password(sm, &password_len);
+ password = eap_get_config_password2(sm, &password_len, &pwhash);
if (password == NULL) {
wpa_printf(MSG_INFO, "EAP-PWD: No password configured!");
return NULL;
@@ -129,6 +132,7 @@
}
os_memcpy(data->password, password, password_len);
data->password_len = password_len;
+ data->password_hash = pwhash;
data->out_frag_pos = data->in_frag_pos = 0;
data->inbuf = data->outbuf = NULL;
@@ -216,6 +220,10 @@
const u8 *payload, size_t payload_len)
{
struct eap_pwd_id *id;
+ const u8 *password;
+ size_t password_len;
+ u8 pwhashhash[16];
+ int res;
if (data->state != PWD_ID_Req) {
ret->ignore = TRUE;
@@ -231,6 +239,9 @@
id = (struct eap_pwd_id *) payload;
data->group_num = be_to_host16(id->group_num);
+ wpa_printf(MSG_DEBUG,
+ "EAP-PWD: Server EAP-pwd-ID proposal: group=%u random=%u prf=%u prep=%u",
+ data->group_num, id->random_function, id->prf, id->prep);
if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) ||
(id->prf != EAP_PWD_DEFAULT_PRF)) {
ret->ignore = TRUE;
@@ -238,6 +249,22 @@
return;
}
+ if (id->prep != EAP_PWD_PREP_NONE &&
+ id->prep != EAP_PWD_PREP_MS) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-PWD: Unsupported password pre-processing technique (Prep=%u)",
+ id->prep);
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ if (id->prep == EAP_PWD_PREP_NONE && data->password_hash) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-PWD: Unhashed password not available");
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
wpa_printf(MSG_DEBUG, "EAP-PWD (peer): using group %d",
data->group_num);
@@ -260,12 +287,39 @@
return;
}
+ if (id->prep == EAP_PWD_PREP_MS) {
+ if (data->password_hash) {
+ res = hash_nt_password_hash(data->password, pwhashhash);
+ } else {
+ u8 pwhash[16];
+
+ res = nt_password_hash(data->password,
+ data->password_len, pwhash);
+ if (res == 0)
+ res = hash_nt_password_hash(pwhash, pwhashhash);
+ os_memset(pwhash, 0, sizeof(pwhash));
+ }
+
+ if (res) {
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ password = pwhashhash;
+ password_len = sizeof(pwhashhash);
+ } else {
+ password = data->password;
+ password_len = data->password_len;
+ }
+
/* compute PWE */
- if (compute_password_element(data->grp, data->group_num,
- data->password, data->password_len,
- data->id_server, data->id_server_len,
- data->id_peer, data->id_peer_len,
- id->token)) {
+ res = compute_password_element(data->grp, data->group_num,
+ password, password_len,
+ data->id_server, data->id_server_len,
+ data->id_peer, data->id_peer_len,
+ id->token);
+ os_memset(pwhashhash, 0, sizeof(pwhashhash));
+ if (res) {
wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE");
eap_pwd_state(data, FAILURE);
return;
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 8710781..15c1bac 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -313,53 +313,19 @@
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len)
{
-#ifndef CONFIG_FIPS
- struct tls_keys keys;
-#endif /* CONFIG_FIPS */
- u8 *rnd = NULL, *out;
+ u8 *out;
out = os_malloc(len);
if (out == NULL)
return NULL;
- /* First, try to use TLS library function for PRF, if available. */
- if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)
- == 0)
- return out;
+ if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, 0,
+ out, len)) {
+ os_free(out);
+ return NULL;
+ }
-#ifndef CONFIG_FIPS
- /*
- * TLS library did not support key generation, so get the needed TLS
- * session parameters and use an internal implementation of TLS PRF to
- * derive the key.
- */
- if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys))
- goto fail;
-
- if (keys.client_random == NULL || keys.server_random == NULL ||
- keys.master_key == NULL)
- goto fail;
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- if (rnd == NULL)
- goto fail;
- os_memcpy(rnd, keys.client_random, keys.client_random_len);
- os_memcpy(rnd + keys.client_random_len, keys.server_random,
- keys.server_random_len);
-
- if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
- label, rnd, keys.client_random_len +
- keys.server_random_len, out, len))
- goto fail;
-
- os_free(rnd);
return out;
-
-fail:
-#endif /* CONFIG_FIPS */
- os_free(out);
- os_free(rnd);
- return NULL;
}
@@ -1032,7 +998,7 @@
{
char *start, *pos, *buf;
struct eap_method_type *methods = NULL, *_methods;
- u8 method;
+ u32 method;
size_t num_methods = 0, prefix_len;
if (config == NULL || config->phase2 == NULL)
diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h
index 9de6cb6..b825e18 100644
--- a/src/eap_server/eap.h
+++ b/src/eap_server/eap.h
@@ -149,5 +149,8 @@
const u8 * eap_get_identity(struct eap_sm *sm, size_t *len);
struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm);
void eap_server_clear_identity(struct eap_sm *sm);
+void eap_server_mschap_rx_callback(struct eap_sm *sm, const char *source,
+ const u8 *username, size_t username_len,
+ const u8 *challenge, const u8 *response);
#endif /* EAP_H */
diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c
index bd919e5..693debe 100644
--- a/src/eap_server/eap_server.c
+++ b/src/eap_server/eap_server.c
@@ -1979,3 +1979,25 @@
os_free(sm->identity);
sm->identity = NULL;
}
+
+
+#ifdef CONFIG_TESTING_OPTIONS
+void eap_server_mschap_rx_callback(struct eap_sm *sm, const char *source,
+ const u8 *username, size_t username_len,
+ const u8 *challenge, const u8 *response)
+{
+ char hex_challenge[30], hex_response[90], user[100];
+
+ /* Print out Challenge and Response in format supported by asleap. */
+ if (username)
+ printf_encode(user, sizeof(user), username, username_len);
+ else
+ user[0] = '\0';
+ wpa_snprintf_hex_sep(hex_challenge, sizeof(hex_challenge),
+ challenge, sizeof(challenge), ':');
+ wpa_snprintf_hex_sep(hex_response, sizeof(hex_response), response, 24,
+ ':');
+ wpa_printf(MSG_DEBUG, "[%s/user=%s] asleap -C %s -R %s",
+ source, user, hex_challenge, hex_response);
+}
+#endif /* CONFIG_TESTING_OPTIONS */
diff --git a/src/eap_server/eap_server_mschapv2.c b/src/eap_server/eap_server_mschapv2.c
index 05848d2..98d74e0 100644
--- a/src/eap_server/eap_server_mschapv2.c
+++ b/src/eap_server/eap_server_mschapv2.c
@@ -360,6 +360,19 @@
}
}
+#ifdef CONFIG_TESTING_OPTIONS
+ {
+ u8 challenge[8];
+
+ if (challenge_hash(peer_challenge, data->auth_challenge,
+ username, username_len, challenge) == 0) {
+ eap_server_mschap_rx_callback(sm, "EAP-MSCHAPV2",
+ username, username_len,
+ challenge, nt_response);
+ }
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
if (username_len != user_len ||
os_memcmp(username, user, username_len) != 0) {
wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names");
diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c
index faa0fd2..3848f30 100644
--- a/src/eap_server/eap_server_peap.c
+++ b/src/eap_server/eap_server_peap.c
@@ -539,15 +539,14 @@
static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
- EapType eap_type)
+ int vendor, EapType eap_type)
{
if (data->phase2_priv && data->phase2_method) {
data->phase2_method->reset(sm, data->phase2_priv);
data->phase2_method = NULL;
data->phase2_priv = NULL;
}
- data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
- eap_type);
+ data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
if (!data->phase2_method)
return -1;
@@ -737,7 +736,7 @@
const u8 *soh_tlv = NULL;
size_t soh_tlv_len = 0;
int tlv_type, mandatory, tlv_len, vtlv_len;
- u8 next_type;
+ u32 next_type;
u32 vendor_id;
pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
@@ -852,8 +851,9 @@
eap_peap_state(data, PHASE2_METHOD);
next_type = sm->user->methods[0].method;
sm->user_eap_method_index = 1;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
- eap_peap_phase2_init(sm, data, next_type);
+ wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type %d",
+ sm->user->methods[0].vendor, next_type);
+ eap_peap_phase2_init(sm, data, sm->user->methods[0].vendor, next_type);
}
#endif /* EAP_SERVER_TNC */
@@ -862,7 +862,8 @@
struct eap_peap_data *data,
struct wpabuf *in_data)
{
- u8 next_type = EAP_TYPE_NONE;
+ int next_vendor = EAP_VENDOR_IETF;
+ u32 next_type = EAP_TYPE_NONE;
const struct eap_hdr *hdr;
const u8 *pos;
size_t left;
@@ -894,17 +895,23 @@
"allowed types", pos + 1, left - 1);
eap_sm_process_nak(sm, pos + 1, left - 1);
if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
- sm->user->methods[sm->user_eap_method_index].method !=
- EAP_TYPE_NONE) {
+ (sm->user->methods[sm->user_eap_method_index].vendor !=
+ EAP_VENDOR_IETF ||
+ sm->user->methods[sm->user_eap_method_index].method !=
+ EAP_TYPE_NONE)) {
+ next_vendor = sm->user->methods[
+ sm->user_eap_method_index].vendor;
next_type = sm->user->methods[
sm->user_eap_method_index++].method;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
- next_type);
+ wpa_printf(MSG_DEBUG,
+ "EAP-PEAP: try EAP vendor %d type 0x%x",
+ next_vendor, next_type);
} else {
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
}
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
return;
}
@@ -929,8 +936,9 @@
if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
return;
}
@@ -942,7 +950,8 @@
wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
"failed");
eap_peap_req_failure(sm, data);
- eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);
+ eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
+ EAP_TYPE_NONE);
return;
}
}
@@ -957,6 +966,7 @@
"database",
sm->identity, sm->identity_len);
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
}
@@ -967,18 +977,22 @@
eap_peap_state(data, PHASE2_SOH);
wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
"TNC (NAP SOH)");
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
}
#endif /* EAP_SERVER_TNC */
eap_peap_state(data, PHASE2_METHOD);
+ next_vendor = sm->user->methods[0].vendor;
next_type = sm->user->methods[0].method;
sm->user_eap_method_index = 1;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
+ wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type 0x%x",
+ next_vendor, next_type);
break;
case PHASE2_METHOD:
eap_peap_req_success(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
case FAILURE:
@@ -989,7 +1003,7 @@
break;
}
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
}
@@ -1133,7 +1147,8 @@
break;
case PHASE2_START:
eap_peap_state(data, PHASE2_ID);
- eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
+ eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
+ EAP_TYPE_IDENTITY);
break;
case PHASE1_ID2:
case PHASE2_ID:
diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
index 943af0d..66bd5d2 100644
--- a/src/eap_server/eap_server_pwd.c
+++ b/src/eap_server/eap_server_pwd.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "crypto/sha256.h"
+#include "crypto/ms_funcs.h"
#include "eap_server/eap_i.h"
#include "eap_common/eap_pwd_common.h"
@@ -24,6 +25,7 @@
size_t id_server_len;
u8 *password;
size_t password_len;
+ int password_hash;
u32 token;
u16 group_num;
EAP_PWD_group *grp;
@@ -112,6 +114,7 @@
}
data->password_len = sm->user->password_len;
os_memcpy(data->password, sm->user->password, data->password_len);
+ data->password_hash = sm->user->password_hash;
data->bnctx = BN_CTX_new();
if (data->bnctx == NULL) {
@@ -181,7 +184,8 @@
wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC);
wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF);
wpabuf_put_data(data->outbuf, &data->token, sizeof(data->token));
- wpabuf_put_u8(data->outbuf, EAP_PWD_PREP_NONE);
+ wpabuf_put_u8(data->outbuf, data->password_hash ? EAP_PWD_PREP_MS :
+ EAP_PWD_PREP_NONE);
wpabuf_put_data(data->outbuf, data->id_server, data->id_server_len);
}
@@ -579,6 +583,10 @@
const u8 *payload, size_t payload_len)
{
struct eap_pwd_id *id;
+ const u8 *password;
+ size_t password_len;
+ u8 pwhashhash[16];
+ int res;
if (payload_len < sizeof(struct eap_pwd_id)) {
wpa_printf(MSG_INFO, "EAP-pwd: Invalid ID response");
@@ -610,11 +618,25 @@
"group");
return;
}
- if (compute_password_element(data->grp, data->group_num,
- data->password, data->password_len,
- data->id_server, data->id_server_len,
- data->id_peer, data->id_peer_len,
- (u8 *) &data->token)) {
+
+ if (data->password_hash) {
+ res = hash_nt_password_hash(data->password, pwhashhash);
+ if (res)
+ return;
+ password = pwhashhash;
+ password_len = sizeof(pwhashhash);
+ } else {
+ password = data->password;
+ password_len = data->password_len;
+ }
+
+ res = compute_password_element(data->grp, data->group_num,
+ password, password_len,
+ data->id_server, data->id_server_len,
+ data->id_peer, data->id_peer_len,
+ (u8 *) &data->token);
+ os_memset(pwhashhash, 0, sizeof(pwhashhash));
+ if (res) {
wpa_printf(MSG_INFO, "EAP-PWD (server): unable to compute "
"PWE");
return;
diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c
index 56916c4..23498c9 100644
--- a/src/eap_server/eap_server_tls_common.c
+++ b/src/eap_server/eap_server_tls_common.c
@@ -100,43 +100,19 @@
u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
char *label, size_t len)
{
- struct tls_keys keys;
- u8 *rnd = NULL, *out;
+ u8 *out;
out = os_malloc(len);
if (out == NULL)
return NULL;
- if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
- 0)
- return out;
+ if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, 0,
+ out, len)) {
+ os_free(out);
+ return NULL;
+ }
- if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
- goto fail;
-
- if (keys.client_random == NULL || keys.server_random == NULL ||
- keys.master_key == NULL)
- goto fail;
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- if (rnd == NULL)
- goto fail;
- os_memcpy(rnd, keys.client_random, keys.client_random_len);
- os_memcpy(rnd + keys.client_random_len, keys.server_random,
- keys.server_random_len);
-
- if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
- label, rnd, keys.client_random_len +
- keys.server_random_len, out, len))
- goto fail;
-
- os_free(rnd);
return out;
-
-fail:
- os_free(out);
- os_free(rnd);
- return NULL;
}
diff --git a/src/eap_server/eap_server_ttls.c b/src/eap_server/eap_server_ttls.c
index 12a31b0..31c67e8 100644
--- a/src/eap_server/eap_server_ttls.c
+++ b/src/eap_server/eap_server_ttls.c
@@ -618,6 +618,12 @@
return;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ eap_server_mschap_rx_callback(sm, "TTLS-MSCHAP",
+ sm->identity, sm->identity_len,
+ challenge, response + 2 + 24);
+#endif /* CONFIG_TESTING_OPTIONS */
+
if (os_memcmp_const(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN)
!= 0 ||
response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) {
@@ -740,6 +746,18 @@
}
rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8;
+#ifdef CONFIG_TESTING_OPTIONS
+ {
+ u8 challenge2[8];
+
+ if (challenge_hash(peer_challenge, auth_challenge,
+ username, username_len, challenge2) == 0) {
+ eap_server_mschap_rx_callback(sm, "TTLS-MSCHAPV2",
+ username, username_len,
+ challenge2, rx_resp);
+ }
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
if (os_memcmp_const(nt_response, rx_resp, 24) == 0) {
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct "
"NT-Response");
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index 85a485e..3f881cf 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -2035,6 +2035,12 @@
sess->remediation = user->remediation;
sess->macacl = user->macacl;
}
+
+ if (ret) {
+ RADIUS_DEBUG("%s: User-Name not found from user database",
+ __func__);
+ }
+
return ret;
}
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index cb334df..0d96216 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -30,6 +30,9 @@
{
if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN)
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
+ if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
+ wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
+ return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
else
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
}
diff --git a/src/tls/tlsv1_client.c b/src/tls/tlsv1_client.c
index facdd65..533286c 100644
--- a/src/tls/tlsv1_client.c
+++ b/src/tls/tlsv1_client.c
@@ -731,8 +731,6 @@
if (conn->state != SERVER_HELLO) {
keys->server_random = conn->server_random;
keys->server_random_len = TLS_RANDOM_LEN;
- keys->master_key = conn->master_secret;
- keys->master_key_len = TLS_MASTER_SECRET_LEN;
}
return 0;
diff --git a/src/tls/tlsv1_server.c b/src/tls/tlsv1_server.c
index 93ae488..4df756f 100644
--- a/src/tls/tlsv1_server.c
+++ b/src/tls/tlsv1_server.c
@@ -627,8 +627,6 @@
if (conn->state != SERVER_HELLO) {
keys->server_random = conn->server_random;
keys->server_random_len = TLS_RANDOM_LEN;
- keys->master_key = conn->master_secret;
- keys->master_key_len = TLS_MASTER_SECRET_LEN;
}
return 0;
diff --git a/src/utils/common.c b/src/utils/common.c
index 5fd795f..0bdc38d 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -277,6 +277,31 @@
return ret;
}
+
+int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len,
+ char sep)
+{
+ size_t i;
+ char *pos = buf, *end = buf + buf_size;
+ int ret;
+
+ if (buf_size == 0)
+ return 0;
+
+ for (i = 0; i < len; i++) {
+ ret = os_snprintf(pos, end - pos, "%02x%c",
+ data[i], sep);
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return pos - buf;
+ }
+ pos += ret;
+ }
+ pos[-1] = '\0';
+ return pos - buf;
+}
+
+
static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
size_t len, int uppercase)
{
diff --git a/src/utils/common.h b/src/utils/common.h
index 576e8e7..a0eda4a 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -480,6 +480,8 @@
void inc_byte_array(u8 *counter, size_t len);
void wpa_get_ntp_timestamp(u8 *buf);
int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...);
+int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len,
+ char sep);
int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len);
int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
size_t len);
diff --git a/src/utils/http_curl.c b/src/utils/http_curl.c
index b38cf79..653eb54 100644
--- a/src/utils/http_curl.c
+++ b/src/utils/http_curl.c
@@ -855,8 +855,10 @@
struct http_cert hcert;
int ret;
- if (ctx->cert_cb == NULL)
+ if (ctx->cert_cb == NULL) {
+ wpa_printf(MSG_DEBUG, "%s: no cert_cb configured", __func__);
return 0;
+ }
if (0) {
BIO *out;
@@ -950,7 +952,8 @@
ssl_ctx = ssl->ctx;
ctx = SSL_CTX_get_app_data(ssl_ctx);
- wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify");
+ wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify, preverify_ok: %d",
+ preverify_ok);
err = X509_STORE_CTX_get_error(x509_ctx);
err_str = X509_verify_cert_error_string(err);
@@ -1249,9 +1252,14 @@
const char *client_key)
{
CURL *curl;
+#ifdef EAP_TLS_OPENSSL
+ const char *extra = " tls=openssl";
+#else /* EAP_TLS_OPENSSL */
+ const char *extra = "";
+#endif /* EAP_TLS_OPENSSL */
wpa_printf(MSG_DEBUG, "Start HTTP client: address=%s ca_fname=%s "
- "username=%s", address, ca_fname, username);
+ "username=%s%s", address, ca_fname, username, extra);
curl = curl_easy_init();
if (curl == NULL)
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index ee40d30..621851b 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -40,6 +40,9 @@
L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/system/wpa_supplicant\"
+# Use Android specific directory for wpa_cli command completion history
+L_CFLAGS += -DCONFIG_WPA_CLI_HISTORY_DIR=\"/data/misc/wifi\"
+
# To force sizeof(enum) = 4
ifeq ($(TARGET_ARCH),arm)
L_CFLAGS += -mabi=aapcs-linux
@@ -1141,8 +1144,10 @@
endif
ifdef NEED_AES_CBC
NEED_AES_ENC=y
+ifneq ($(CONFIG_TLS), openssl)
AESOBJS += src/crypto/aes-cbc.c
endif
+endif
ifdef NEED_AES_ENC
ifdef CONFIG_INTERNAL_AES
AESOBJS += src/crypto/aes-internal-enc.c
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index d086eeb..af2d924 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -317,6 +317,10 @@
NEED_GAS=y
endif
+ifdef CONFIG_NO_ROAMING
+CFLAGS += -DCONFIG_NO_ROAMING
+endif
+
include ../src/drivers/drivers.mak
ifdef CONFIG_AP
OBJS_d += $(DRV_BOTH_OBJS)
@@ -1162,8 +1166,10 @@
endif
ifdef NEED_AES_CBC
NEED_AES_ENC=y
+ifneq ($(CONFIG_TLS), openssl)
AESOBJS += ../src/crypto/aes-cbc.o
endif
+endif
ifdef NEED_AES_ENC
ifdef CONFIG_INTERNAL_AES
AESOBJS += ../src/crypto/aes-internal-enc.o
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a01a910..c690542 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1816,6 +1816,7 @@
{ FUNC(bssid_blacklist) },
{ FUNC(bssid_whitelist) },
{ FUNC_KEY(psk) },
+ { INT(mem_only_psk) },
{ FUNC(proto) },
{ FUNC(key_mgmt) },
{ INT(bg_scan_period) },
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 3d3a6e4..781f5e5 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -501,7 +501,12 @@
static void write_psk(FILE *f, struct wpa_ssid *ssid)
{
- char *value = wpa_config_get(ssid, "psk");
+ char *value;
+
+ if (ssid->mem_only_psk)
+ return;
+
+ value = wpa_config_get(ssid, "psk");
if (value == NULL)
return;
fprintf(f, "\tpsk=%s\n", value);
@@ -673,6 +678,7 @@
write_str(f, "bssid_blacklist", ssid);
write_str(f, "bssid_whitelist", ssid);
write_psk(f, ssid);
+ INT(mem_only_psk);
write_proto(f, ssid);
write_key_mgmt(f, ssid);
INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 7c826cf..23a37cc 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -181,6 +181,14 @@
char *ext_psk;
/**
+ * mem_only_psk - Whether to keep PSK/passphrase only in memory
+ *
+ * 0 = allow psk/passphrase to be stored to the configuration file
+ * 1 = do not store psk/passphrase to the configuration file
+ */
+ int mem_only_psk;
+
+ /**
* pairwise_cipher - Bitfield of allowed pairwise ciphers, WPA_CIPHER_*
*/
int pairwise_cipher;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 53d2d01..377b9ed 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -2366,6 +2366,14 @@
}
#endif /* CONFIG_SUITEB192 */
+ if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
+ ret = os_snprintf(pos, end - pos, "%sOSEN",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+
pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
@@ -2433,7 +2441,7 @@
{
char *pos, *end;
int ret;
- const u8 *ie, *ie2, *p2p, *mesh;
+ const u8 *ie, *ie2, *osen_ie, *p2p, *mesh;
mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
@@ -2460,8 +2468,12 @@
pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
ie2, 2 + ie2[1]);
}
+ osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+ if (osen_ie)
+ pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
+ osen_ie, 2 + osen_ie[1]);
pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
- if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
+ if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
ret = os_snprintf(pos, end - pos, "[WEP]");
if (os_snprintf_error(end - pos, ret))
return -1;
@@ -3937,7 +3949,7 @@
size_t i;
int ret;
char *pos, *end;
- const u8 *ie, *ie2;
+ const u8 *ie, *ie2, *osen_ie;
pos = buf;
end = buf + buflen;
@@ -4054,8 +4066,13 @@
if (ie2)
pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
2 + ie2[1]);
+ osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+ if (osen_ie)
+ pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
+ osen_ie, 2 + osen_ie[1]);
pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
- if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
+ if (!ie && !ie2 && !osen_ie &&
+ (bss->caps & IEEE80211_CAP_PRIVACY)) {
ret = os_snprintf(pos, end - pos, "[WEP]");
if (os_snprintf_error(end - pos, ret))
return 0;
@@ -8504,11 +8521,14 @@
char *cmd)
{
struct wpa_interface iface;
- char *pos;
+ char *pos, *extra;
+ struct wpa_supplicant *wpa_s;
+ unsigned int create_iface = 0;
+ u8 mac_addr[ETH_ALEN];
/*
* <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
- * TAB<bridge_ifname>
+ * TAB<bridge_ifname>[TAB<create>]
*/
wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
@@ -8568,12 +8588,47 @@
iface.bridge_ifname = NULL;
if (pos == NULL)
break;
+
+ extra = pos;
+ pos = os_strchr(pos, '\t');
+ if (pos)
+ *pos++ = '\0';
+ if (os_strcmp(extra, "create") == 0)
+ create_iface = 1;
+ else
+ return -1;
} while (0);
- if (wpa_supplicant_get_iface(global, iface.ifname))
- return -1;
+ if (create_iface) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
+ iface.ifname);
+ if (!global->ifaces)
+ return -1;
+ if (wpa_drv_if_add(global->ifaces, WPA_IF_STATION, iface.ifname,
+ NULL, NULL, NULL, mac_addr, NULL) < 0) {
+ wpa_printf(MSG_ERROR,
+ "CTRL_IFACE interface creation failed");
+ return -1;
+ }
- return wpa_supplicant_add_iface(global, &iface, NULL) ? 0 : -1;
+ wpa_printf(MSG_DEBUG,
+ "CTRL_IFACE interface '%s' created with MAC addr: "
+ MACSTR, iface.ifname, MAC2STR(mac_addr));
+ }
+
+ if (wpa_supplicant_get_iface(global, iface.ifname))
+ goto fail;
+
+ wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
+ if (!wpa_s)
+ goto fail;
+ wpa_s->added_vif = create_iface;
+ return 0;
+
+fail:
+ if (create_iface)
+ wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
+ return -1;
}
@@ -8581,13 +8636,22 @@
char *cmd)
{
struct wpa_supplicant *wpa_s;
+ int ret;
+ unsigned int delete_iface;
wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
wpa_s = wpa_supplicant_get_iface(global, cmd);
if (wpa_s == NULL)
return -1;
- return wpa_supplicant_remove_iface(global, wpa_s, 0);
+ delete_iface = wpa_s->added_vif;
+ ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
+ if (!ret && delete_iface) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
+ cmd);
+ ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
+ }
+ return ret;
}
diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index fe91236..5f7b49d 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -16,6 +16,7 @@
<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>
@@ -52,6 +53,14 @@
</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
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 6ed2549..fc70035 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1085,14 +1085,13 @@
struct wpa_bss *selected = NULL;
int prio;
struct wpa_ssid *next_ssid = NULL;
+ struct wpa_ssid *ssid;
if (wpa_s->last_scan_res == NULL ||
wpa_s->last_scan_res_used == 0)
return NULL; /* no scan results from last update */
if (wpa_s->next_ssid) {
- struct wpa_ssid *ssid;
-
/* check that next_ssid is still valid */
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
if (ssid == wpa_s->next_ssid)
@@ -1128,6 +1127,27 @@
break;
}
+ ssid = *selected_ssid;
+ if (selected && ssid && ssid->mem_only_psk && !ssid->psk_set &&
+ !ssid->passphrase && !ssid->ext_psk) {
+ const char *field_name, *txt = NULL;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "PSK/passphrase not yet available for the selected network");
+
+ wpas_notify_network_request(wpa_s, ssid,
+ WPA_CTRL_REQ_PSK_PASSPHRASE, NULL);
+
+ field_name = wpa_supplicant_ctrl_req_to_string(
+ WPA_CTRL_REQ_PSK_PASSPHRASE, NULL, &txt);
+ if (field_name == NULL)
+ return NULL;
+
+ wpas_send_ctrl_req(wpa_s, ssid, field_name, txt);
+
+ selected = NULL;
+ }
+
return selected;
}
@@ -1266,7 +1286,9 @@
struct wpa_ssid *ssid)
{
struct wpa_bss *current_bss = NULL;
+#ifndef CONFIG_NO_ROAMING
int min_diff;
+#endif /* CONFIG_NO_ROAMING */
if (wpa_s->reassociate)
return 1; /* explicit request to reassociate */
@@ -3146,6 +3168,7 @@
union wpa_event_data *data)
{
struct wpa_supplicant *wpa_s = ctx;
+ int resched;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
event != EVENT_INTERFACE_ENABLED &&
@@ -3712,6 +3735,7 @@
case EVENT_SCHED_SCAN_STOPPED:
wpa_s->pno = 0;
wpa_s->sched_scanning = 0;
+ resched = wpa_s->scanning;
wpa_supplicant_notify_scanning(wpa_s, 0);
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
@@ -3726,6 +3750,8 @@
} else if (wpa_s->pno_sched_pending) {
wpa_s->pno_sched_pending = 0;
wpas_start_pno(wpa_s);
+ } else if (resched) {
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
}
break;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index bb61808..4c71ef4 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -5504,18 +5504,26 @@
(freq > 0 && !freq_included(channels, freq)))
freq = 0;
}
- } else {
+ } else if (ssid->mode == WPAS_MODE_INFRA) {
freq = neg_freq;
- if (freq < 0 ||
- (freq > 0 && !freq_included(channels, freq)))
- freq = 0;
- }
+ if (freq <= 0 || !freq_included(channels, freq)) {
+ struct os_reltime now;
+ struct wpa_bss *bss =
+ wpa_bss_get_p2p_dev_addr(wpa_s, ssid->bssid);
- if (ssid->mode == WPAS_MODE_INFRA)
+ os_get_reltime(&now);
+ if (bss &&
+ !os_reltime_expired(&now, &bss->last_update, 5) &&
+ freq_included(channels, bss->freq))
+ freq = bss->freq;
+ else
+ freq = 0;
+ }
+
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq);
-
- if (ssid->mode != WPAS_MODE_P2P_GO)
+ } else {
return -1;
+ }
if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, vht, channels))
return -1;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 2b40bbf..5fe4618 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -92,6 +92,7 @@
static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
+static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */
static void print_help(const char *cmd);
@@ -99,6 +100,7 @@
static void wpa_cli_close_connection(void);
static char * wpa_cli_get_default_ifname(void);
static char ** wpa_list_cmd_list(void);
+static void update_networks(struct wpa_ctrl *ctrl);
static void usage(void)
@@ -168,11 +170,12 @@
#ifdef CONFIG_P2P
-static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
+static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
+ int separator)
{
const char *end;
char *buf;
- end = os_strchr(txt, ' ');
+ end = os_strchr(txt, separator);
if (end == NULL)
end = txt + os_strlen(txt);
buf = dup_binstr(txt, end - txt);
@@ -213,14 +216,16 @@
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
return cli_txt_list_add(txt_list, buf);
}
+#endif /* CONFIG_P2P */
-static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
+static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
+ int separator)
{
const char *end;
char *buf;
int ret;
- end = os_strchr(txt, ' ');
+ end = os_strchr(txt, separator);
if (end == NULL)
end = txt + os_strlen(txt);
buf = dup_binstr(txt, end - txt);
@@ -230,7 +235,6 @@
os_free(buf);
return ret;
}
-#endif /* CONFIG_P2P */
static char ** cli_txt_list_array(struct dl_list *txt_list)
@@ -1451,14 +1455,18 @@
static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return wpa_ctrl_command(ctrl, "ADD_NETWORK");
+ int res = wpa_ctrl_command(ctrl, "ADD_NETWORK");
+ update_networks(ctrl);
+ return res;
}
static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
+ int res = wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
+ update_networks(ctrl);
+ return res;
}
@@ -1519,6 +1527,105 @@
}
+static const char *network_fields[] = {
+ "ssid", "scan_ssid", "bssid", "bssid_blacklist",
+ "bssid_whitelist", "psk", "proto", "key_mgmt",
+ "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
+ "freq_list",
+#ifdef IEEE8021X_EAPOL
+ "eap", "identity", "anonymous_identity", "password", "ca_cert",
+ "ca_path", "client_cert", "private_key", "private_key_passwd",
+ "dh_file", "subject_match", "altsubject_match",
+ "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
+ "client_cert2", "private_key2", "private_key2_passwd",
+ "dh_file2", "subject_match2", "altsubject_match2",
+ "domain_suffix_match2", "domain_match2", "phase1", "phase2",
+ "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
+ "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",
+ "engine", "engine2", "eapol_flags", "sim_num",
+ "openssl_ciphers", "erp",
+#endif /* IEEE8021X_EAPOL */
+ "wep_key0", "wep_key1", "wep_key2", "wep_key3",
+ "wep_tx_keyidx", "priority",
+#ifdef IEEE8021X_EAPOL
+ "eap_workaround", "pac_file", "fragment_size", "ocsp",
+#endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_MESH
+ "mode", "no_auto_peer",
+#else /* CONFIG_MESH */
+ "mode",
+#endif /* CONFIG_MESH */
+ "proactive_key_caching", "disabled", "id_str",
+#ifdef CONFIG_IEEE80211W
+ "ieee80211w",
+#endif /* CONFIG_IEEE80211W */
+ "peerkey", "mixed_cell", "frequency", "fixed_freq",
+#ifdef CONFIG_MESH
+ "mesh_basic_rates", "dot11MeshMaxRetries",
+ "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
+ "dot11MeshHoldingTimeout",
+#endif /* CONFIG_MESH */
+ "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
+#ifdef CONFIG_P2P
+ "go_p2p_dev_addr", "p2p_client_list", "psk_list",
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_HT_OVERRIDES
+ "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
+ "ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
+ "ampdu_density", "ht_mcs",
+#endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+ "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
+ "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4",
+ "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7",
+ "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2",
+ "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5",
+ "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8",
+#endif /* CONFIG_VHT_OVERRIDES */
+ "ap_max_inactivity", "dtim_period", "beacon_int",
+#ifdef CONFIG_MACSEC
+ "macsec_policy",
+#endif /* CONFIG_MACSEC */
+#ifdef CONFIG_HS20
+ "update_identifier",
+#endif /* CONFIG_HS20 */
+ "mac_addr"
+};
+
+
+static char ** wpa_cli_complete_network(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ int i, num_fields = ARRAY_SIZE(network_fields);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&networks);
+ break;
+ case 2:
+ res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(network_fields[i]);
+ if (res[i] == NULL)
+ break;
+ }
+ }
+ return res;
+}
+
+
+static char ** wpa_cli_complete_network_id(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ if (arg == 1)
+ return cli_txt_list_array(&networks);
+ return NULL;
+}
+
+
static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1537,6 +1644,31 @@
}
+static char ** wpa_cli_complete_dup_network(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ int i, num_fields = ARRAY_SIZE(network_fields);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ case 2:
+ res = cli_txt_list_array(&networks);
+ break;
+ case 3:
+ res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(network_fields[i]);
+ if (res[i] == NULL)
+ break;
+ }
+ }
+ return res;
+}
+
+
static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1711,20 +1843,20 @@
printf("Invalid INTERFACE_ADD command: needs at least one "
"argument (interface name)\n"
"All arguments: ifname confname driver ctrl_interface "
- "driver_param bridge_name\n");
+ "driver_param bridge_name [create]\n");
return -1;
}
/*
* INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
- * <driver_param>TAB<bridge_name>
+ * <driver_param>TAB<bridge_name>[TAB<create>]
*/
res = os_snprintf(cmd, sizeof(cmd),
- "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
+ "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s",
argv[0],
argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
- argc > 5 ? argv[5] : "");
+ argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "");
if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
@@ -2776,29 +2908,33 @@
{ "list_networks", wpa_cli_cmd_list_networks, NULL,
cli_cmd_flag_none,
"= list configured networks" },
- { "select_network", wpa_cli_cmd_select_network, NULL,
+ { "select_network", wpa_cli_cmd_select_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = select a network (disable others)" },
- { "enable_network", wpa_cli_cmd_enable_network, NULL,
+ { "enable_network", wpa_cli_cmd_enable_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = enable a network" },
- { "disable_network", wpa_cli_cmd_disable_network, NULL,
+ { "disable_network", wpa_cli_cmd_disable_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = disable a network" },
{ "add_network", wpa_cli_cmd_add_network, NULL,
cli_cmd_flag_none,
"= add a network" },
- { "remove_network", wpa_cli_cmd_remove_network, NULL,
+ { "remove_network", wpa_cli_cmd_remove_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = remove a network" },
- { "set_network", wpa_cli_cmd_set_network, NULL,
+ { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
cli_cmd_flag_sensitive,
"<network id> <variable> <value> = set network variables (shows\n"
" list of variables when run without arguments)" },
- { "get_network", wpa_cli_cmd_get_network, NULL,
+ { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
cli_cmd_flag_none,
"<network id> <variable> = get network variables" },
- { "dup_network", wpa_cli_cmd_dup_network, NULL,
+ { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
cli_cmd_flag_none,
"<src network id> <dst network id> <variable> = duplicate network variables"
},
@@ -2840,7 +2976,7 @@
{ "get_capability", wpa_cli_cmd_get_capability, NULL,
cli_cmd_flag_none,
"<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
- "= get capabilies" },
+ "= get capabilities" },
{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
cli_cmd_flag_none,
"= force wpa_supplicant to re-read its configuration file" },
@@ -3614,7 +3750,7 @@
s = os_strchr(start, ' ');
if (s == NULL)
return;
- cli_txt_list_add_word(&p2p_groups, s + 1);
+ cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
return;
}
@@ -3622,7 +3758,7 @@
s = os_strchr(start, ' ');
if (s == NULL)
return;
- cli_txt_list_del_word(&p2p_groups, s + 1);
+ cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
return;
}
#endif /* CONFIG_P2P */
@@ -3781,7 +3917,11 @@
ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
+#ifdef CONFIG_WPA_CLI_HISTORY_DIR
+ home = CONFIG_WPA_CLI_HISTORY_DIR;
+#else /* CONFIG_WPA_CLI_HISTORY_DIR */
home = getenv("HOME");
+#endif /* CONFIG_WPA_CLI_HISTORY_DIR */
if (home) {
const char *fname = ".wpa_cli_history";
int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
@@ -3864,6 +4004,38 @@
}
+static void update_networks(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ char *cmd = "LIST_NETWORKS";
+ char *pos, *end;
+ int header = 1;
+
+ cli_txt_list_flush(&networks);
+
+ if (ctrl == NULL)
+ return;
+ ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+ if (ret < 0)
+ return;
+ buf[len] = '\0';
+
+ pos = buf;
+ while (pos) {
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ if (!header)
+ cli_txt_list_add_word(&networks, pos, '\t');
+ header = 0;
+ pos = end + 1;
+ }
+}
+
+
static void try_connection(void *eloop_ctx, void *timeout_ctx)
{
if (ctrl_conn)
@@ -3884,6 +4056,7 @@
}
update_bssid_list(ctrl_conn);
+ update_networks(ctrl_conn);
if (warning_displayed)
printf("Connection established.\n");
@@ -3905,6 +4078,7 @@
cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses);
cli_txt_list_flush(&ifnames);
+ cli_txt_list_flush(&networks);
if (edit_started)
edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
os_free(hfile);
diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
index bc6fa7f..408e387 100644
--- a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
+++ b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
@@ -135,6 +135,7 @@
monitor_conn = NULL;
msgNotifier = NULL;
ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
+ signalMeterInterval = 0;
parse_argv();
@@ -161,6 +162,10 @@
timer->setSingleShot(FALSE);
timer->start(1000);
+ signalMeterTimer = new QTimer(this);
+ signalMeterTimer->setInterval(signalMeterInterval);
+ connect(signalMeterTimer, SIGNAL(timeout()), SLOT(signalMeterUpdate()));
+
if (openCtrlConnection(ctrl_iface) < 0) {
debug("Failed to open control connection to "
"wpa_supplicant.");
@@ -234,7 +239,7 @@
{
int c;
for (;;) {
- c = getopt(qApp->argc(), qApp->argv(), "i:p:tq");
+ c = getopt(qApp->argc(), qApp->argv(), "i:m:p:tq");
if (c < 0)
break;
switch (c) {
@@ -242,6 +247,9 @@
free(ctrl_iface);
ctrl_iface = strdup(optarg);
break;
+ case 'm':
+ signalMeterInterval = atoi(optarg) * 1000;
+ break;
case 'p':
free(ctrl_iface_dir);
ctrl_iface_dir = strdup(optarg);
@@ -496,6 +504,8 @@
textBssid->clear();
textIpAddress->clear();
updateTrayToolTip(tr("no status information"));
+ updateTrayIcon(TrayIconOffline);
+ signalMeterTimer->stop();
#ifdef CONFIG_NATIVE_WINDOWS
static bool first = true;
@@ -544,6 +554,11 @@
ssid_updated = true;
textSsid->setText(pos);
updateTrayToolTip(pos + tr(" (associated)"));
+ if (!signalMeterInterval) {
+ /* if signal meter is not enabled show
+ * full signal strength */
+ updateTrayIcon(TrayIconSignalExcellent);
+ }
} else if (strcmp(start, "ip_address") == 0) {
ipaddr_updated = true;
textIpAddress->setText(pos);
@@ -587,6 +602,23 @@
} else
textEncryption->clear();
+ if (signalMeterInterval) {
+ /*
+ * Handle signal meter service. When network is not associated,
+ * deactivate timer, otherwise keep it going. Tray icon has to
+ * be initialized here, because of the initial delay of the
+ * timer.
+ */
+ if (ssid_updated) {
+ if (!signalMeterTimer->isActive()) {
+ updateTrayIcon(TrayIconConnected);
+ signalMeterTimer->start();
+ }
+ } else {
+ signalMeterTimer->stop();
+ }
+ }
+
if (!status_updated)
textStatus->clear();
if (!auth_updated)
@@ -594,6 +626,7 @@
if (!ssid_updated) {
textSsid->clear();
updateTrayToolTip(tr("(not-associated)"));
+ updateTrayIcon(TrayIconOffline);
}
if (!bssid_updated)
textBssid->clear();
@@ -828,6 +861,53 @@
}
+void WpaGui::signalMeterUpdate()
+{
+ char reply[128];
+ size_t reply_len = sizeof(reply);
+ char *rssi;
+ int rssi_value;
+
+ ctrlRequest("SIGNAL_POLL", reply, &reply_len);
+
+ /* In order to eliminate signal strength fluctuations, try
+ * to obtain averaged RSSI value in the first place. */
+ if ((rssi = strstr(reply, "AVG_RSSI=")) != NULL)
+ rssi_value = atoi(&rssi[sizeof("AVG_RSSI")]);
+ else if ((rssi = strstr(reply, "RSSI=")) != NULL)
+ rssi_value = atoi(&rssi[sizeof("RSSI")]);
+ else {
+ debug("Failed to get RSSI value");
+ updateTrayIcon(TrayIconSignalNone);
+ return;
+ }
+
+ debug("RSSI value: %d", rssi_value);
+
+ /*
+ * NOTE: The code below assumes, that the unit of the value returned
+ * by the SIGNAL POLL request is dBm. It might not be true for all
+ * wpa_supplicant drivers.
+ */
+
+ /*
+ * Calibration is based on "various Internet sources". Nonetheless,
+ * it seems to be compatible with the Windows 8.1 strength meter -
+ * tested on Intel Centrino Advanced-N 6235.
+ */
+ if (rssi_value >= -60)
+ updateTrayIcon(TrayIconSignalExcellent);
+ else if (rssi_value >= -68)
+ updateTrayIcon(TrayIconSignalGood);
+ else if (rssi_value >= -76)
+ updateTrayIcon(TrayIconSignalOk);
+ else if (rssi_value >= -84)
+ updateTrayIcon(TrayIconSignalWeak);
+ else
+ updateTrayIcon(TrayIconSignalNone);
+}
+
+
static int str_match(const char *a, const char *b)
{
return strncmp(a, b, strlen(b)) == 0;
@@ -1278,10 +1358,7 @@
QApplication::setQuitOnLastWindowClosed(false);
tray_icon = new QSystemTrayIcon(this);
- if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
- tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
- else
- tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
+ updateTrayIcon(TrayIconOffline);
connect(tray_icon,
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
@@ -1421,6 +1498,59 @@
}
+void WpaGui::updateTrayIcon(TrayIconType type)
+{
+ if (!tray_icon || currentIconType == type)
+ return;
+
+ QIcon icon;
+ QIcon fallback_icon;
+
+ if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
+ fallback_icon = QIcon(":/icons/wpa_gui.svg");
+ else
+ fallback_icon = QIcon(":/icons/wpa_gui.png");
+
+ switch (type) {
+ case TrayIconOffline:
+ icon = QIcon::fromTheme("network-wireless-offline",
+ fallback_icon);
+ break;
+ case TrayIconAcquiring:
+ icon = QIcon::fromTheme("network-wireless-acquiring",
+ fallback_icon);
+ break;
+ case TrayIconConnected:
+ icon = QIcon::fromTheme("network-wireless-connected",
+ fallback_icon);
+ break;
+ case TrayIconSignalNone:
+ icon = QIcon::fromTheme("network-wireless-signal-none",
+ fallback_icon);
+ break;
+ case TrayIconSignalWeak:
+ icon = QIcon::fromTheme("network-wireless-signal-weak",
+ fallback_icon);
+ break;
+ case TrayIconSignalOk:
+ icon = QIcon::fromTheme("network-wireless-signal-ok",
+ fallback_icon);
+ break;
+ case TrayIconSignalGood:
+ icon = QIcon::fromTheme("network-wireless-signal-good",
+ fallback_icon);
+ break;
+ case TrayIconSignalExcellent:
+ icon = QIcon::fromTheme("network-wireless-signal-excellent",
+ fallback_icon);
+ break;
+ }
+
+ currentIconType = type;
+ tray_icon->setIcon(icon);
+}
+
+
void WpaGui::closeEvent(QCloseEvent *event)
{
if (eh) {
diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.h b/wpa_supplicant/wpa_gui-qt4/wpagui.h
index 026eacb..c0de67b 100644
--- a/wpa_supplicant/wpa_gui-qt4/wpagui.h
+++ b/wpa_supplicant/wpa_gui-qt4/wpagui.h
@@ -22,6 +22,18 @@
Q_OBJECT
public:
+
+ enum TrayIconType {
+ TrayIconOffline = 0,
+ TrayIconAcquiring,
+ TrayIconConnected,
+ TrayIconSignalNone,
+ TrayIconSignalWeak,
+ TrayIconSignalOk,
+ TrayIconSignalGood,
+ TrayIconSignalExcellent,
+ };
+
WpaGui(QApplication *app, QWidget *parent = 0, const char *name = 0,
Qt::WFlags fl = 0);
~WpaGui();
@@ -49,6 +61,7 @@
virtual void scan();
virtual void eventHistory();
virtual void ping();
+ virtual void signalMeterUpdate();
virtual void processMsg(char *msg);
virtual void processCtrlReq(const char *req);
virtual void receiveMsgs();
@@ -70,6 +83,7 @@
virtual void showTrayMessage(QSystemTrayIcon::MessageIcon type,
int sec, const QString &msg);
virtual void showTrayStatus();
+ virtual void updateTrayIcon(TrayIconType type);
virtual void updateTrayToolTip(const QString &msg);
virtual void wpsDialog();
virtual void peersDialog();
@@ -113,6 +127,7 @@
QAction *quitAction;
QMenu *tray_menu;
QSystemTrayIcon *tray_icon;
+ TrayIconType currentIconType;
QString wpaStateTranslate(char *state);
void createTrayIcon(bool);
bool ackTrayIcon;
@@ -127,6 +142,9 @@
void stopWpsRun(bool success);
+ QTimer *signalMeterTimer;
+ int signalMeterInterval;
+
#ifdef CONFIG_NATIVE_WINDOWS
QAction *fileStartServiceAction;
QAction *fileStopServiceAction;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6f5fbad..2ba9c38 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -731,6 +731,7 @@
ssid && ssid->id_str ? ssid->id_str : "");
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
wpas_clear_temp_disabled(wpa_s, ssid, 1);
+ wpa_blacklist_clear(wpa_s);
wpa_s->extra_blacklist_count = 0;
wpa_s->new_connection = 0;
wpa_drv_set_operstate(wpa_s, 1);
@@ -1239,7 +1240,12 @@
}
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
- wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
+ int psk_set = 0;
+
+ if (ssid->psk_set) {
+ wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
+ psk_set = 1;
+ }
#ifndef CONFIG_NO_PBKDF2
if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
ssid->passphrase) {
@@ -1249,6 +1255,7 @@
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ psk_set = 1;
os_memset(psk, 0, sizeof(psk));
}
#endif /* CONFIG_NO_PBKDF2 */
@@ -1286,6 +1293,7 @@
"external passphrase)",
psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ psk_set = 1;
os_memset(psk, 0, sizeof(psk));
} else
#endif /* CONFIG_NO_PBKDF2 */
@@ -1298,6 +1306,7 @@
return -1;
}
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ psk_set = 1;
os_memset(psk, 0, sizeof(psk));
} else {
wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
@@ -1311,6 +1320,12 @@
ext_password_free(pw);
}
#endif /* CONFIG_EXT_PASSWORD */
+
+ if (!psk_set) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "No PSK available for association");
+ return -1;
+ }
} else
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
@@ -4967,6 +4982,15 @@
str_clear_free(eap->external_sim_resp);
eap->external_sim_resp = os_strdup(value);
break;
+ case WPA_CTRL_REQ_PSK_PASSPHRASE:
+ if (wpa_config_set(ssid, "psk", value, 0) < 0)
+ return -1;
+ ssid->mem_only_psk = 1;
+ if (ssid->passphrase)
+ wpa_config_update_psk(ssid);
+ if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ break;
default:
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
return -1;
@@ -5014,7 +5038,8 @@
}
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
- (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
+ (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
+ !ssid->mem_only_psk)
return 1;
return 0;
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 8964b3f..eb7434a 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -740,6 +740,11 @@
# startup and reconfiguration time can be optimized by generating the PSK only
# only when the passphrase or SSID has actually changed.
#
+# mem_only_psk: Whether to keep PSK/passphrase only in memory
+# 0 = allow psk/passphrase to be stored to the configuration file
+# 1 = do not store psk/passphrase to the configuration file
+#mem_only_psk=0
+#
# eapol_flags: IEEE 802.1X/EAPOL options (bit field)
# Dynamic WEP key required for non-WPA mode
# bit0 (1): require dynamically generated unicast WEP key
@@ -969,7 +974,7 @@
# tls_disable_session_ticket=0 - allow TLS Session Ticket extension to be used
# Note: If not set, this is automatically set to 1 for EAP-TLS/PEAP/TTLS
# as a workaround for broken authentication server implementations unless
-# EAP workarounds are disabled with eap_workarounds=0.
+# EAP workarounds are disabled with eap_workaround=0.
# For EAP-FAST, this must be set to 0 (or left unconfigured for the
# default value to be used automatically).
# tls_disable_tlsv1_1=1 - disable use of TLSv1.1 (a workaround for AAA servers
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 0ec102f..2d517f1 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -648,6 +648,7 @@
unsigned int eap_expected_failure:1;
unsigned int reattach:1; /* reassociation to the same BSS requested */
unsigned int mac_addr_changed:1;
+ unsigned int added_vif:1;
struct os_reltime last_mac_addr_change;
int last_mac_addr_style;
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 1bb82ba..48a5d69 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -737,6 +737,8 @@
return WPA_CTRL_REQ_EAP_PASSPHRASE;
else if (os_strcmp(field, "SIM") == 0)
return WPA_CTRL_REQ_SIM;
+ else if (os_strcmp(field, "PSK_PASSPHRASE") == 0)
+ return WPA_CTRL_REQ_PSK_PASSPHRASE;
return WPA_CTRL_REQ_UNKNOWN;
}
@@ -776,6 +778,10 @@
case WPA_CTRL_REQ_SIM:
ret = "SIM";
break;
+ case WPA_CTRL_REQ_PSK_PASSPHRASE:
+ *txt = "PSK or passphrase";
+ ret = "PSK_PASSPHRASE";
+ break;
default:
break;
}
@@ -789,6 +795,35 @@
return ret;
}
+
+void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ const char *field_name, const char *txt)
+{
+ char *buf;
+ size_t buflen;
+ int len;
+
+ buflen = 100 + os_strlen(txt) + ssid->ssid_len;
+ buf = os_malloc(buflen);
+ if (buf == NULL)
+ return;
+ len = os_snprintf(buf, buflen, "%s-%d:%s needed for SSID ",
+ field_name, ssid->id, txt);
+ if (os_snprintf_error(buflen, len)) {
+ os_free(buf);
+ return;
+ }
+ if (ssid->ssid && buflen > len + ssid->ssid_len) {
+ os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
+ len += ssid->ssid_len;
+ buf[len] = '\0';
+ }
+ buf[buflen - 1] = '\0';
+ wpa_msg(wpa_s, MSG_INFO, WPA_CTRL_REQ "%s", buf);
+ os_free(buf);
+}
+
+
#ifdef IEEE8021X_EAPOL
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
static void wpa_supplicant_eap_param_needed(void *ctx,
@@ -798,9 +833,6 @@
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid = wpa_s->current_ssid;
const char *field_name, *txt = NULL;
- char *buf;
- size_t buflen;
- int len;
if (ssid == NULL)
return;
@@ -817,25 +849,7 @@
wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name);
- buflen = 100 + os_strlen(txt) + ssid->ssid_len;
- buf = os_malloc(buflen);
- if (buf == NULL)
- return;
- len = os_snprintf(buf, buflen,
- WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
- field_name, ssid->id, txt);
- if (os_snprintf_error(buflen, len)) {
- os_free(buf);
- return;
- }
- if (ssid->ssid && buflen > len + ssid->ssid_len) {
- os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
- len += ssid->ssid_len;
- buf[len] = '\0';
- }
- buf[buflen - 1] = '\0';
- wpa_msg(wpa_s, MSG_INFO, "%s", buf);
- os_free(buf);
+ wpas_send_ctrl_req(wpa_s, ssid, field_name, txt);
}
#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
#define wpa_supplicant_eap_param_needed NULL
diff --git a/wpa_supplicant/wpas_glue.h b/wpa_supplicant/wpas_glue.h
index 9808c22..5585e56 100644
--- a/wpa_supplicant/wpas_glue.h
+++ b/wpa_supplicant/wpas_glue.h
@@ -22,4 +22,7 @@
enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field);
+void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ const char *field_name, const char *txt);
+
#endif /* WPAS_GLUE_H */