diff --git a/contrib/wpa/CONTRIBUTIONS b/contrib/wpa/CONTRIBUTIONS index 1b4caf7ac811..b2064dc83443 100644 --- a/contrib/wpa/CONTRIBUTIONS +++ b/contrib/wpa/CONTRIBUTIONS @@ -143,7 +143,7 @@ The license terms used for hostap.git files Modified BSD license (no advertisement clause): -Copyright (c) 2002-2021, Jouni Malinen and contributors +Copyright (c) 2002-2022, Jouni Malinen and contributors All Rights Reserved. Redistribution and use in source and binary forms, with or without diff --git a/contrib/wpa/COPYING b/contrib/wpa/COPYING index 5d0115c9ca6f..7ca30301e28b 100644 --- a/contrib/wpa/COPYING +++ b/contrib/wpa/COPYING @@ -1,7 +1,7 @@ wpa_supplicant and hostapd -------------------------- -Copyright (c) 2002-2019, Jouni Malinen and contributors +Copyright (c) 2002-2022, Jouni Malinen and contributors All Rights Reserved. diff --git a/contrib/wpa/README b/contrib/wpa/README index a9f806967bf9..1470c4f23582 100644 --- a/contrib/wpa/README +++ b/contrib/wpa/README @@ -1,7 +1,7 @@ wpa_supplicant and hostapd -------------------------- -Copyright (c) 2002-2019, Jouni Malinen and contributors +Copyright (c) 2002-2022, Jouni Malinen and contributors All Rights Reserved. These programs are licensed under the BSD license (the one with diff --git a/contrib/wpa/hostapd/ChangeLog b/contrib/wpa/hostapd/ChangeLog index 34a8a081879d..279298e4d4d4 100644 --- a/contrib/wpa/hostapd/ChangeLog +++ b/contrib/wpa/hostapd/ChangeLog @@ -1,5 +1,48 @@ ChangeLog for hostapd +2022-01-16 - v2.10 + * SAE changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + - added option send SAE Confirm immediately (sae_config_immediate=1) + after SAE Commit + - added support for the hash-to-element mechanism (sae_pwe=1 or + sae_pwe=2) + - fixed PMKSA caching with OKC + - added support for SAE-PK + * EAP-pwd changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + * fixed WPS UPnP SUBSCRIBE handling of invalid operations + [https://w1.fi/security/2020-1/] + * fixed PMF disconnection protection bypass + [https://w1.fi/security/2019-7/] + * added support for using OpenSSL 3.0 + * fixed various issues in experimental support for EAP-TEAP server + * added configuration (max_auth_rounds, max_auth_rounds_short) to + increase the maximum number of EAP message exchanges (mainly to + support cases with very large certificates) for the EAP server + * added support for DPP release 2 (Wi-Fi Device Provisioning Protocol) + * extended HE (IEEE 802.11ax) support, including 6 GHz support + * removed obsolete IAPP functionality + * fixed EAP-FAST server with TLS GCM/CCM ciphers + * dropped support for libnl 1.1 + * added support for nl80211 control port for EAPOL frame TX/RX + * fixed OWE key derivation with groups 20 and 21; this breaks backwards + compatibility for these groups while the default group 19 remains + backwards compatible; owe_ptk_workaround=1 can be used to enabled a + a workaround for the group 20/21 backwards compatibility + * added support for Beacon protection + * added support for Extended Key ID for pairwise keys + * removed WEP support from the default build (CONFIG_WEP=y can be used + to enable it, if really needed) + * added a build option to remove TKIP support (CONFIG_NO_TKIP=y) + * added support for Transition Disable mechanism to allow the AP to + automatically disable transition mode to improve security + * added support for PASN + * added EAP-TLS server support for TLS 1.3 (disabled by default for now) + * a large number of other fixes, cleanup, and extensions + 2019-08-07 - v2.9 * SAE changes - disable use of groups using Brainpool curves diff --git a/contrib/wpa/hostapd/README b/contrib/wpa/hostapd/README index 1f30d7ea39fa..739c964d44d8 100644 --- a/contrib/wpa/hostapd/README +++ b/contrib/wpa/hostapd/README @@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP Authenticator and RADIUS authentication server ================================================================ -Copyright (c) 2002-2019, Jouni Malinen and contributors +Copyright (c) 2002-2022, Jouni Malinen and contributors All Rights Reserved. This program is licensed under the BSD license (the one with diff --git a/contrib/wpa/hostapd/hostapd_cli.c b/contrib/wpa/hostapd/hostapd_cli.c index 0e7fdd6bccfb..2609121116b5 100644 --- a/contrib/wpa/hostapd/hostapd_cli.c +++ b/contrib/wpa/hostapd/hostapd_cli.c @@ -1,6 +1,6 @@ /* * hostapd - command line interface for hostapd daemon - * Copyright (c) 2004-2019, Jouni Malinen + * Copyright (c) 2004-2022, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -21,7 +21,7 @@ static const char *const hostapd_cli_version = "hostapd_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2019, Jouni Malinen and contributors"; +"Copyright (c) 2004-2022, Jouni Malinen and contributors"; static struct wpa_ctrl *ctrl_conn; static int hostapd_cli_quit = 0; diff --git a/contrib/wpa/hostapd/main.c b/contrib/wpa/hostapd/main.c index 4f2d1f21659e..c9ec38d19f88 100644 --- a/contrib/wpa/hostapd/main.c +++ b/contrib/wpa/hostapd/main.c @@ -1,6 +1,6 @@ /* * hostapd / main() - * Copyright (c) 2002-2019, Jouni Malinen + * Copyright (c) 2002-2022, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -454,7 +454,7 @@ static void show_version(void) "hostapd v%s\n" "User space daemon for IEEE 802.11 AP management,\n" "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" - "Copyright (c) 2002-2019, Jouni Malinen " + "Copyright (c) 2002-2022, Jouni Malinen " "and contributors\n", VERSION_STR); } diff --git a/contrib/wpa/hs20/server/Makefile b/contrib/wpa/hs20/server/Makefile deleted file mode 100644 index 0cab6d6b010a..000000000000 --- a/contrib/wpa/hs20/server/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -ALL=hs20_spp_server - -include ../../src/build.rules - -CFLAGS += -I../../src -CFLAGS += -I../../src/utils -CFLAGS += -I../../src/crypto - -LIBS += -lsqlite3 - -# Using glibc < 2.17 requires -lrt for clock_gettime() -LIBS += -lrt - -ifndef CONFIG_NO_GITVER -# Add VERSION_STR postfix for builds from a git repository -ifeq ($(wildcard ../../.git),../../.git) -GITVER := $(shell git describe --dirty=+) -ifneq ($(GITVER),) -CFLAGS += -DGIT_VERSION_STR_POSTFIX=\"-$(GITVER)\" -endif -endif -endif - -OBJS=spp_server.o -OBJS += hs20_spp_server.o -OBJS += ../../src/utils/xml-utils.o -OBJS += ../../src/utils/base64.o -OBJS += ../../src/utils/common.o -OBJS += ../../src/utils/os_unix.o -OBJS += ../../src/utils/wpa_debug.o -OBJS += ../../src/crypto/md5-internal.o -CFLAGS += $(shell xml2-config --cflags) -LIBS += $(shell xml2-config --libs) -OBJS += ../../src/utils/xml_libxml2.o - -_OBJS_VAR := OBJS -include ../../src/objs.mk -hs20_spp_server: $(OBJS) - $(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS) - -clean: common-clean - rm -f core *~ diff --git a/contrib/wpa/hs20/server/ca/clean.sh b/contrib/wpa/hs20/server/ca/clean.sh deleted file mode 100755 index c72dcbda45e9..000000000000 --- a/contrib/wpa/hs20/server/ca/clean.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -for i in server-client server server-revoked user ocsp; do - rm -f $i.csr $i.key $i.pem -done - -rm -f openssl.cnf.tmp -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/contrib/wpa/hs20/server/ca/est-csrattrs.cnf b/contrib/wpa/hs20/server/ca/est-csrattrs.cnf deleted file mode 100644 index b50ea00d0b77..000000000000 --- a/contrib/wpa/hs20/server/ca/est-csrattrs.cnf +++ /dev/null @@ -1,17 +0,0 @@ -asn1 = SEQUENCE:attrs - -[attrs] -#oid1 = OID:challengePassword -attr1 = SEQUENCE:extreq -oid2 = OID:sha256WithRSAEncryption - -[extreq] -oid = OID:extensionRequest -vals = SET:extreqvals - -[extreqvals] - -oid1 = OID:macAddress -#oid2 = OID:imei -#oid3 = OID:meid -#oid4 = OID:DevId diff --git a/contrib/wpa/hs20/server/ca/est-csrattrs.sh b/contrib/wpa/hs20/server/ca/est-csrattrs.sh deleted file mode 100755 index 0b73a0408284..000000000000 --- a/contrib/wpa/hs20/server/ca/est-csrattrs.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -openssl asn1parse -genconf est-csrattrs.cnf -out est-csrattrs.der -oid hs20.oid -base64 est-csrattrs.der > est-attrs.b64 diff --git a/contrib/wpa/hs20/server/ca/hs20.oid b/contrib/wpa/hs20/server/ca/hs20.oid deleted file mode 100644 index a829ff29bf44..000000000000 --- a/contrib/wpa/hs20/server/ca/hs20.oid +++ /dev/null @@ -1,7 +0,0 @@ -1.3.6.1.1.1.1.22 macAddress -1.2.840.113549.1.9.14 extensionRequest -1.3.6.1.4.1.40808.1.1.1 id-wfa-hotspot-friendlyName -1.3.6.1.4.1.40808.1.1.2 id-kp-HS2.0Auth -1.3.6.1.4.1.40808.1.1.3 imei -1.3.6.1.4.1.40808.1.1.4 meid -1.3.6.1.4.1.40808.1.1.5 DevId diff --git a/contrib/wpa/hs20/server/ca/ocsp-req.sh b/contrib/wpa/hs20/server/ca/ocsp-req.sh deleted file mode 100755 index 931a20696d02..000000000000 --- a/contrib/wpa/hs20/server/ca/ocsp-req.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -for i in *.pem; do - echo "===[ $i ]===================" - openssl ocsp -text -CAfile ca.pem -verify_other demoCA/cacert.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/ - -# openssl ocsp -text -CAfile rootCA/cacert.pem -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/ - -# openssl ocsp -text -CAfile rootCA/cacert.pem -verify_other demoCA/cacert.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/ -# openssl ocsp -text -CAfile rootCA/cacert.pem -VAfile ca.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/ -done diff --git a/contrib/wpa/hs20/server/ca/ocsp-responder-ica.sh b/contrib/wpa/hs20/server/ca/ocsp-responder-ica.sh deleted file mode 100755 index 116c6e1c3d01..000000000000 --- a/contrib/wpa/hs20/server/ca/ocsp-responder-ica.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey-plain.pem -CA demoCA/cacert.pem -resp_no_certs -text diff --git a/contrib/wpa/hs20/server/ca/ocsp-responder.sh b/contrib/wpa/hs20/server/ca/ocsp-responder.sh deleted file mode 100755 index 620947d01af0..000000000000 --- a/contrib/wpa/hs20/server/ca/ocsp-responder.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text -ignore_err diff --git a/contrib/wpa/hs20/server/ca/ocsp-update-cache.sh b/contrib/wpa/hs20/server/ca/ocsp-update-cache.sh deleted file mode 100755 index f2b23250cadd..000000000000 --- a/contrib/wpa/hs20/server/ca/ocsp-update-cache.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# NOTE: You may need to replace 'localhost' with your OCSP server hostname. -openssl ocsp \ - -no_nonce \ - -CAfile ca.pem \ - -verify_other demoCA/cacert.pem \ - -issuer demoCA/cacert.pem \ - -cert server.pem \ - -url http://localhost:8888/ \ - -respout ocsp-server-cache.der diff --git a/contrib/wpa/hs20/server/ca/openssl-root.cnf b/contrib/wpa/hs20/server/ca/openssl-root.cnf deleted file mode 100644 index 5bc50be1dbc9..000000000000 --- a/contrib/wpa/hs20/server/ca/openssl-root.cnf +++ /dev/null @@ -1,125 +0,0 @@ -# OpenSSL configuration file for Hotspot 2.0 PKI (Root CA) - -HOME = . -RANDFILE = $ENV::HOME/.rnd -oid_section = new_oids - -[ new_oids ] - -#logotypeoid=1.3.6.1.5.5.7.1.12 - -#################################################################### -[ ca ] -default_ca = CA_default # The default ca section - -#################################################################### -[ CA_default ] - -dir = ./rootCA # Where everything is kept -certs = $dir/certs # Where the issued certs are kept -crl_dir = $dir/crl # Where the issued crl are kept -database = $dir/index.txt # database index file. -#unique_subject = no # Set to 'no' to allow creation of - # several certificates with same subject -new_certs_dir = $dir/newcerts # default place for new certs. - -certificate = $dir/cacert.pem # The CA certificate -serial = $dir/serial # The current serial number -crlnumber = $dir/crlnumber # the current crl number - # must be commented out to leave a V1 CRL -crl = $dir/crl.pem # The current CRL -private_key = $dir/private/cakey.pem# The private key -RANDFILE = $dir/private/.rand # private random number file - -x509_extensions = usr_cert # The extentions to add to the cert - -name_opt = ca_default # Subject Name options -cert_opt = ca_default # Certificate field options - -default_days = 365 # how long to certify for -default_crl_days= 30 # how long before next CRL -default_md = default # use public key default MD -preserve = no # keep passed DN ordering - -policy = policy_match - -# For the CA policy -[ policy_match ] -countryName = match -stateOrProvinceName = optional -organizationName = match -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -[ policy_anything ] -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -#################################################################### -[ req ] -default_bits = 2048 -default_keyfile = privkey.pem -distinguished_name = req_distinguished_name -attributes = req_attributes -x509_extensions = v3_ca # The extentions to add to the self signed cert - -input_password = @PASSWORD@ -output_password = @PASSWORD@ - -string_mask = utf8only - -[ req_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = US -countryName_min = 2 -countryName_max = 2 - -localityName = Locality Name (eg, city) -localityName_default = Tuusula - -0.organizationName = Organization Name (eg, company) -0.organizationName_default = WFA Hotspot 2.0 - -##organizationalUnitName = Organizational Unit Name (eg, section) -#organizationalUnitName_default = -#@OU@ - -commonName = Common Name (e.g. server FQDN or YOUR name) -#@CN@ -commonName_max = 64 - -emailAddress = Email Address -emailAddress_max = 64 - -[ req_attributes ] - -[ v3_req ] - -# Extensions to add to a certificate request -basicConstraints = CA:FALSE -keyUsage = nonRepudiation, digitalSignature, keyEncipherment -subjectAltName=DNS:example.com,DNS:another.example.com - -[ v3_ca ] - -# Hotspot 2.0 PKI requirements -subjectKeyIdentifier=hash -basicConstraints = critical,CA:true -keyUsage = critical, cRLSign, keyCertSign - -[ crl_ext ] - -# issuerAltName=issuer:copy -authorityKeyIdentifier=keyid:always - -[ v3_OCSP ] - -basicConstraints = CA:FALSE -keyUsage = nonRepudiation, digitalSignature, keyEncipherment -extendedKeyUsage = OCSPSigning diff --git a/contrib/wpa/hs20/server/ca/openssl.cnf b/contrib/wpa/hs20/server/ca/openssl.cnf deleted file mode 100644 index 61410138340f..000000000000 --- a/contrib/wpa/hs20/server/ca/openssl.cnf +++ /dev/null @@ -1,200 +0,0 @@ -# OpenSSL configuration file for Hotspot 2.0 PKI (Intermediate CA) - -HOME = . -RANDFILE = $ENV::HOME/.rnd -oid_section = new_oids - -[ new_oids ] - -#logotypeoid=1.3.6.1.5.5.7.1.12 - -#################################################################### -[ ca ] -default_ca = CA_default # The default ca section - -#################################################################### -[ CA_default ] - -dir = ./demoCA # Where everything is kept -certs = $dir/certs # Where the issued certs are kept -crl_dir = $dir/crl # Where the issued crl are kept -database = $dir/index.txt # database index file. -#unique_subject = no # Set to 'no' to allow creation of - # several certificates with same subject -new_certs_dir = $dir/newcerts # default place for new certs. - -certificate = $dir/cacert.pem # The CA certificate -serial = $dir/serial # The current serial number -crlnumber = $dir/crlnumber # the current crl number - # must be commented out to leave a V1 CRL -crl = $dir/crl.pem # The current CRL -private_key = $dir/private/cakey.pem# The private key -RANDFILE = $dir/private/.rand # private random number file - -x509_extensions = ext_client # The extentions to add to the cert - -name_opt = ca_default # Subject Name options -cert_opt = ca_default # Certificate field options - -# Extension copying option: use with caution. -copy_extensions = copy - -default_days = 365 # how long to certify for -default_crl_days= 30 # how long before next CRL -default_md = default # use public key default MD -preserve = no # keep passed DN ordering - -policy = policy_match - -# For the CA policy -[ policy_match ] -countryName = supplied -stateOrProvinceName = optional -organizationName = supplied -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -[ policy_osu_server ] -countryName = match -stateOrProvinceName = optional -organizationName = match -organizationalUnitName = supplied -commonName = supplied -emailAddress = optional - -[ policy_anything ] -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -#################################################################### -[ req ] -default_bits = 2048 -default_keyfile = privkey.pem -distinguished_name = req_distinguished_name -attributes = req_attributes -x509_extensions = v3_ca # The extentions to add to the self signed cert - -input_password = @PASSWORD@ -output_password = @PASSWORD@ - -string_mask = utf8only - -[ req_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = FI -countryName_min = 2 -countryName_max = 2 - -localityName = Locality Name (eg, city) -localityName_default = Tuusula - -0.organizationName = Organization Name (eg, company) -0.organizationName_default = @DOMAIN@ - -##organizationalUnitName = Organizational Unit Name (eg, section) -#organizationalUnitName_default = -#@OU@ - -commonName = Common Name (e.g. server FQDN or YOUR name) -#@CN@ -commonName_max = 64 - -emailAddress = Email Address -emailAddress_max = 64 - -[ req_attributes ] - -[ v3_ca ] - -# Hotspot 2.0 PKI requirements -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid:always,issuer -basicConstraints = critical, CA:true, pathlen:0 -keyUsage = critical, cRLSign, keyCertSign -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:.@DOMAIN@ -#1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn - -[ v3_osu_server ] - -basicConstraints = critical, CA:true, pathlen:0 -keyUsage = critical, keyEncipherment -#@ALTNAME@ - -#logotypeoid=ASN1:SEQUENCE:LogotypeExtn -1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn -[LogotypeExtn] -communityLogos=EXP:0,SEQUENCE:LogotypeInfo -[LogotypeInfo] -# note: implicit tag converted to explicit for CHOICE -direct=EXP:0,SEQUENCE:LogotypeData -[LogotypeData] -image=SEQUENCE:LogotypeImage -[LogotypeImage] -imageDetails=SEQUENCE:LogotypeDetails -imageInfo=SEQUENCE:LogotypeImageInfo -[LogotypeDetails] -mediaType=IA5STRING:image/png -logotypeHash=SEQUENCE:HashAlgAndValues -logotypeURI=SEQUENCE:URI -[HashAlgAndValues] -value1=SEQUENCE:HashAlgAndValueSHA256 -#value2=SEQUENCE:HashAlgAndValueSHA1 -[HashAlgAndValueSHA256] -hashAlg=SEQUENCE:sha256_alg -hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH256@ -[HashAlgAndValueSHA1] -hashAlg=SEQUENCE:sha1_alg -hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH1@ -[sha256_alg] -algorithm=OID:sha256 -[sha1_alg] -algorithm=OID:sha1 -[URI] -uri=IA5STRING:@LOGO_URI@ -[LogotypeImageInfo] -# default value color(1), component optional -#type=IMP:0,INTEGER:1 -fileSize=INTEGER:7549 -xSize=INTEGER:128 -ySize=INTEGER:80 -language=IMP:4,IA5STRING:zxx - -[ crl_ext ] - -# issuerAltName=issuer:copy -authorityKeyIdentifier=keyid:always - -[ v3_OCSP ] - -basicConstraints = CA:FALSE -keyUsage = nonRepudiation, digitalSignature, keyEncipherment -extendedKeyUsage = OCSPSigning - -[ ext_client ] - -basicConstraints=CA:FALSE -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid,issuer -authorityInfoAccess = OCSP;URI:@OCSP_URI@ -#@ALTNAME@ -extendedKeyUsage = clientAuth - -[ ext_server ] - -# Hotspot 2.0 PKI requirements -basicConstraints=critical, CA:FALSE -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid,issuer -authorityInfoAccess = OCSP;URI:@OCSP_URI@ -#@ALTNAME@ -extendedKeyUsage = critical, serverAuth -keyUsage = critical, keyEncipherment diff --git a/contrib/wpa/hs20/server/ca/setup.sh b/contrib/wpa/hs20/server/ca/setup.sh deleted file mode 100755 index 78abcccff455..000000000000 --- a/contrib/wpa/hs20/server/ca/setup.sh +++ /dev/null @@ -1,209 +0,0 @@ -#!/bin/sh - -if [ -z "$OPENSSL" ]; then - OPENSSL=openssl -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 < 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 - echo " * Use existing Root CA" -else - echo " * Generate Root CA private key" - $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 -fi - -echo -echo "---[ Intermediate CA ]--------------------------------------------------" -echo - -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 - echo " * Use existing Intermediate CA" -else - echo " * Generate Intermediate CA private key" - $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -keyout demoCA/private/cakey.pem -out demoCA/careq.pem || fail "Failed to generate Intermediate CA private key" - echo " * Sign Intermediate CA certificate" - $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 -fi - -echo -echo "OCSP responder" -echo - -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 || fail "Could not generate ocsp.pem" - -echo -echo "---[ Server - to be revoked ] ------------------------------------------" -echo - -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 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 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_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 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/" \ - > openssl.cnf.tmp -echo $OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server -$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server || fail "Failed to generate server request" -$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server.csr -out server.pem -key $PASS -days 730 -extensions ext_server -policy policy_osu_server || fail "Failed to sign server certificate" - -#dump logotype details for debugging -$OPENSSL x509 -in server.pem -out server.der -outform DER -openssl asn1parse -in server.der -inform DER | grep HEX | tail -1 | sed 's/.*://' | xxd -r -p > logo.der -openssl asn1parse -in logo.der -inform DER > logo.asn1 - - -echo -echo "---[ CRL ]---------------------------------------------------------------" -echo - -$OPENSSL ca -config $PWD/my-openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS - -echo -echo "---[ Verify ]------------------------------------------------------------" -echo - -$OPENSSL verify -CAfile rootCA/cacert.pem demoCA/cacert.pem -$OPENSSL verify -CAfile rootCA/cacert.pem -untrusted demoCA/cacert.pem *.pem - -cat rootCA/cacert.pem demoCA/cacert.pem > ca.pem diff --git a/contrib/wpa/hs20/server/ca/w1fi_logo.png b/contrib/wpa/hs20/server/ca/w1fi_logo.png deleted file mode 100644 index ac7c259fff2e..000000000000 Binary files a/contrib/wpa/hs20/server/ca/w1fi_logo.png and /dev/null differ diff --git a/contrib/wpa/hs20/server/hs20-osu-server.txt b/contrib/wpa/hs20/server/hs20-osu-server.txt deleted file mode 100644 index 22478ad9d2cb..000000000000 --- a/contrib/wpa/hs20/server/hs20-osu-server.txt +++ /dev/null @@ -1,262 +0,0 @@ -Hotspot 2.0 OSU server -====================== - -The information in this document is based on the assumption that Ubuntu -16.04 server (64-bit) distribution is used and the web server is -Apache2. Neither of these are requirements for the installation, but if -other combinations are used, the package names and configuration -parameters may need to be adjusted. - -NOTE: This implementation and the example configuration here is meant -only for testing purposes in a lab environment. This design is not -secure to be installed in a publicly available Internet server without -considerable amount of modification and review for security issues. - - -Build dependencies ------------------- - -Ubuntu 16.04 server -- default installation -- upgraded to latest package versions - sudo apt-get update - sudo apt-get upgrade - -Packages needed for running the service: - sudo apt-get install sqlite3 - sudo apt-get install apache2 - sudo apt-get install php-sqlite3 php-xml libapache2-mod-php - -Additional packages needed for building the components: - sudo apt-get install build-essential - sudo apt-get install libsqlite3-dev - sudo apt-get install libssl-dev - sudo apt-get install libxml2-dev - - -Installation location ---------------------- - -Select a location for the installation root directory. The example here -assumes /home/user/hs20-server to be used, but this can be changed by -editing couple of files as indicated below. - -sudo mkdir -p /home/user/hs20-server -sudo chown $USER /home/user/hs20-server -mkdir -p /home/user/hs20-server/spp -mkdir -p /home/user/hs20-server/AS - - -Build ------ - -# hostapd as RADIUS server -cd hostapd - -#example build configuration -cat > .config < /home/user/hs20-server/terms-and-conditions <Terms and conditions..

-EOF - -# 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" \ - -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 -cat > /home/user/hs20-server/spp/policy/default.xml < - - 30 - ClientInitiated - Unrestricted - https://policy-server.osu.example.com/hs20/spp.php - - -EOF - - -# Install Hotspot 2.0 SPP and OMA DM XML schema/DTD files - -# XML schema for SPP -# Copy the latest XML schema into /home/user/hs20-server/spp/spp.xsd - -# OMA DM Device Description Framework DTD -# Copy into /home/user/hs20-server/spp/dm_ddf-v1_2.dtd -# http://www.openmobilealliance.org/tech/DTD/dm_ddf-v1_2.dtd - - -# Configure RADIUS authentication service -# Note: Change the URL to match the setup -# Note: Install AAA server key/certificate and root CA in Key directory - -cat > /home/user/hs20-server/AS/as-sql.conf < /home/user/hs20-server/AS/as.radius_clients < - Options Indexes MultiViews FollowSymLinks - AllowOverride None - Require all granted - SSLOptions +StdEnvVars - - -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. - -To support subscription remediation using client certificates, set -"SSLVerifyClient optional" and configure the trust root CA(s) for the -client certificates with SSLCACertificateFile. - -Enable default-ssl site and restart Apache2: - sudo a2ensite default-ssl - sudo a2enmod ssl - sudo service apache2 restart - - -Management UI -------------- - -The sample PHP scripts include a management UI for testing -purposes. That is available at https:///hs20/users.php - - -AP configuration ----------------- - -APs can now be configured to use the OSU server as the RADIUS -authentication server. In addition, the OSU Provider List ANQP element -should be configured to use the SPP (SOAP+XML) option and with the -following Server URL: -https:///hs20/spp.php/signup?realm=example.com diff --git a/contrib/wpa/hs20/server/hs20_spp_server.c b/contrib/wpa/hs20/server/hs20_spp_server.c deleted file mode 100644 index 347c40a73d6a..000000000000 --- a/contrib/wpa/hs20/server/hs20_spp_server.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Hotspot 2.0 SPP server - standalone version - * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#include "common/version.h" -#include "xml-utils.h" -#include "spp_server.h" - - -static void write_timestamp(FILE *f) -{ - time_t t; - struct tm *tm; - - time(&t); - tm = localtime(&t); - - fprintf(f, "%04u-%02u-%02u %02u:%02u:%02u ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); -} - - -void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...) -{ - va_list ap; - - if (ctx->debug_log == NULL) - return; - - write_timestamp(ctx->debug_log); - va_start(ap, fmt); - vfprintf(ctx->debug_log, fmt, ap); - va_end(ap); - - fprintf(ctx->debug_log, "\n"); -} - - -void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node) -{ - char *str; - - if (ctx->debug_log == NULL) - return; - str = xml_node_to_str(ctx->xml, node); - if (str == NULL) - return; - - write_timestamp(ctx->debug_log); - fprintf(ctx->debug_log, "%s: '%s'\n", title, str); - os_free(str); -} - - -static int process(struct hs20_svc *ctx) -{ - int dmacc = 0; - xml_node_t *soap, *spp, *resp; - char *user, *realm, *post, *str; - - ctx->addr = getenv("HS20ADDR"); - if (ctx->addr) - debug_print(ctx, 1, "Connection from %s", ctx->addr); - ctx->test = getenv("HS20TEST"); - if (ctx->test) - debug_print(ctx, 1, "Requested test functionality: %s", - ctx->test); - - user = getenv("HS20USER"); - if (user && strlen(user) == 0) - user = NULL; - realm = getenv("HS20REALM"); - if (realm == NULL) { - debug_print(ctx, 1, "HS20REALM not set"); - return -1; - } - post = getenv("HS20POST"); - if (post == NULL) { - debug_print(ctx, 1, "HS20POST not set"); - return -1; - } - - ctx->imsi = getenv("HS20IMSI"); - if (ctx->imsi) - debug_print(ctx, 1, "IMSI %s", ctx->imsi); - - ctx->eap_method = getenv("HS20EAPMETHOD"); - if (ctx->eap_method) - debug_print(ctx, 1, "EAP method %s", ctx->eap_method); - - ctx->id_hash = getenv("HS20IDHASH"); - if (ctx->id_hash) - debug_print(ctx, 1, "ID-HASH %s", ctx->id_hash); - - soap = xml_node_from_buf(ctx->xml, post); - if (soap == NULL) { - debug_print(ctx, 1, "Could not parse SOAP data"); - return -1; - } - debug_dump_node(ctx, "Received SOAP message", soap); - spp = soap_get_body(ctx->xml, soap); - if (spp == NULL) { - debug_print(ctx, 1, "Could not get SPP message"); - xml_node_free(ctx->xml, soap); - return -1; - } - debug_dump_node(ctx, "Received SPP message", spp); - - resp = hs20_spp_server_process(ctx, spp, user, realm, dmacc); - xml_node_free(ctx->xml, soap); - if (resp == NULL && user == NULL) { - debug_print(ctx, 1, "Request HTTP authentication"); - return 2; /* Request authentication */ - } - if (resp == NULL) { - debug_print(ctx, 1, "No response"); - return -1; - } - - soap = soap_build_envelope(ctx->xml, resp); - if (soap == NULL) { - debug_print(ctx, 1, "SOAP envelope building failed"); - return -1; - } - str = xml_node_to_str(ctx->xml, soap); - xml_node_free(ctx->xml, soap); - if (str == NULL) { - debug_print(ctx, 1, "Could not get node string"); - return -1; - } - printf("%s", str); - free(str); - - return 0; -} - - -static void usage(void) -{ - printf("usage:\n" - "hs20_spp_server -r [-f]\n"); -} - - -int main(int argc, char *argv[]) -{ - struct hs20_svc ctx; - int ret; - - os_memset(&ctx, 0, sizeof(ctx)); - for (;;) { - int c = getopt(argc, argv, "f:r:v"); - if (c < 0) - break; - switch (c) { - case 'f': - if (ctx.debug_log) - break; - ctx.debug_log = fopen(optarg, "a"); - if (ctx.debug_log == NULL) { - printf("Could not write to %s\n", optarg); - return -1; - } - break; - case 'r': - ctx.root_dir = optarg; - break; - case 'v': - printf("hs20_spp_server v%s\n", VERSION_STR); - return 0; - default: - usage(); - return -1; - } - } - if (ctx.root_dir == NULL) { - usage(); - return -1; - } - ctx.xml = xml_node_init_ctx(&ctx, NULL); - if (ctx.xml == NULL) - return -1; - if (hs20_spp_server_init(&ctx) < 0) { - xml_node_deinit_ctx(ctx.xml); - return -1; - } - - ret = process(&ctx); - debug_print(&ctx, 1, "process() --> %d", ret); - - xml_node_deinit_ctx(ctx.xml); - hs20_spp_server_deinit(&ctx); - if (ctx.debug_log) - fclose(ctx.debug_log); - - return ret; -} diff --git a/contrib/wpa/hs20/server/spp_server.c b/contrib/wpa/hs20/server/spp_server.c deleted file mode 100644 index a50e9074f7b4..000000000000 --- a/contrib/wpa/hs20/server/spp_server.c +++ /dev/null @@ -1,2933 +0,0 @@ -/* - * Hotspot 2.0 SPP server - * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "base64.h" -#include "md5_i.h" -#include "xml-utils.h" -#include "spp_server.h" - - -#define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp" - -#define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0" -#define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0" -#define URN_OMA_DM_DMACC "urn:oma:mo:oma-dm-dmacc:1.0" -#define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0" - - -/* TODO: timeout to expire sessions */ - -enum hs20_session_operation { - NO_OPERATION, - UPDATE_PASSWORD, - CONTINUE_SUBSCRIPTION_REMEDIATION, - CONTINUE_POLICY_UPDATE, - USER_REMEDIATION, - SUBSCRIPTION_REGISTRATION, - POLICY_REMEDIATION, - POLICY_UPDATE, - FREE_REMEDIATION, - CLEAR_REMEDIATION, - CERT_REENROLL, -}; - - -static char * db_get_session_val(struct hs20_svc *ctx, const char *user, - const char *realm, const char *session_id, - const char *field); -static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, - const char *field); -static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user, - const char *realm, int use_dmacc); -static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx, - const char *session_id, - const char *user, - const char *realm, - int add_est_user); - - -static int db_add_session(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *sessionid, const char *pw, - const char *redirect_uri, - enum hs20_session_operation operation, - const u8 *mac_addr) -{ - char *sql; - int ret = 0; - char addr[20]; - - if (mac_addr) - snprintf(addr, sizeof(addr), MACSTR, MAC2STR(mac_addr)); - else - addr[0] = '\0'; - sql = sqlite3_mprintf("INSERT INTO sessions(timestamp,id,user,realm," - "operation,password,redirect_uri,mac_addr,test) " - "VALUES " - "(strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," - "%Q,%Q,%Q,%d,%Q,%Q,%Q,%Q)", - sessionid, user ? user : "", realm ? realm : "", - operation, pw ? pw : "", - redirect_uri ? redirect_uri : "", - addr, ctx->test); - if (sql == NULL) - return -1; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session entry into sqlite " - "database: %s", sqlite3_errmsg(ctx->db)); - ret = -1; - } - sqlite3_free(sql); - return ret; -} - - -static void db_update_session_password(struct hs20_svc *ctx, const char *user, - const char *realm, const char *sessionid, - const char *pw) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET password=%Q WHERE id=%Q AND " - "user=%Q AND realm=%Q", - pw, sessionid, user, realm); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update session password: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_update_session_machine_managed(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *sessionid, - const int pw_mm) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET machine_managed=%Q WHERE id=%Q AND user=%Q AND realm=%Q", - pw_mm ? "1" : "0", sessionid, user, realm); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, - "Failed to update session machine_managed: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_pps(struct hs20_svc *ctx, const char *user, - const char *realm, const char *sessionid, - xml_node_t *node) -{ - char *str; - char *sql; - - str = xml_node_to_str(ctx->xml, node); - if (str == NULL) - return; - sql = sqlite3_mprintf("UPDATE sessions SET pps=%Q WHERE id=%Q AND " - "user=%Q AND realm=%Q", - str, sessionid, user, realm); - free(str); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session pps: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_devinfo(struct hs20_svc *ctx, const char *sessionid, - xml_node_t *node) -{ - char *str; - char *sql; - - str = xml_node_to_str(ctx->xml, node); - if (str == NULL) - return; - sql = sqlite3_mprintf("UPDATE sessions SET devinfo=%Q WHERE id=%Q", - str, sessionid); - free(str); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session devinfo: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_devdetail(struct hs20_svc *ctx, - const char *sessionid, - xml_node_t *node) -{ - char *str; - char *sql; - - str = xml_node_to_str(ctx->xml, node); - if (str == NULL) - return; - sql = sqlite3_mprintf("UPDATE sessions SET devdetail=%Q WHERE id=%Q", - str, sessionid); - free(str); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session devdetail: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_dmacc(struct hs20_svc *ctx, const char *sessionid, - const char *username, const char *password) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET osu_user=%Q, osu_password=%Q WHERE id=%Q", - username, password, sessionid); - if (!sql) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session DMAcc: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_eap_method(struct hs20_svc *ctx, - const char *sessionid, - const char *method) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET eap_method=%Q WHERE id=%Q", - method, sessionid); - if (!sql) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session EAP method: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_id_hash(struct hs20_svc *ctx, const char *sessionid, - const char *id_hash) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET mobile_identifier_hash=%Q WHERE id=%Q", - id_hash, sessionid); - if (!sql) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session ID hash: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_remove_session(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *sessionid) -{ - char *sql; - - if (user == NULL || realm == NULL) { - sql = sqlite3_mprintf("DELETE FROM sessions WHERE " - "id=%Q", sessionid); - } else { - sql = sqlite3_mprintf("DELETE FROM sessions WHERE " - "user=%Q AND realm=%Q AND id=%Q", - user, realm, sessionid); - } - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to delete session entry from " - "sqlite database: %s", sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void hs20_eventlog(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *sessionid, const char *notes, - const char *dump) -{ - char *sql; - char *user_buf = NULL, *realm_buf = NULL; - - debug_print(ctx, 1, "eventlog: %s", notes); - - if (user == NULL) { - user_buf = db_get_session_val(ctx, NULL, NULL, sessionid, - "user"); - user = user_buf; - realm_buf = db_get_session_val(ctx, NULL, NULL, sessionid, - "realm"); - realm = realm_buf; - } - - sql = sqlite3_mprintf("INSERT INTO eventlog" - "(user,realm,sessionid,timestamp,notes,dump,addr)" - " VALUES (%Q,%Q,%Q," - "strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," - "%Q,%Q,%Q)", - user, realm, sessionid, notes, - dump ? dump : "", ctx->addr ? ctx->addr : ""); - free(user_buf); - free(realm_buf); - if (sql == NULL) - return; - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add eventlog entry into sqlite " - "database: %s", sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void hs20_eventlog_node(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *sessionid, const char *notes, - xml_node_t *node) -{ - char *str; - - if (node) - str = xml_node_to_str(ctx->xml, node); - else - str = NULL; - hs20_eventlog(ctx, user, realm, sessionid, notes, str); - free(str); -} - - -static void db_update_mo_str(struct hs20_svc *ctx, const char *user, - const char *realm, const char *name, - const char *str) -{ - char *sql; - if (user == NULL || realm == NULL || name == NULL) - return; - sql = sqlite3_mprintf("UPDATE users SET %s=%Q WHERE identity=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", - name, str, user, realm); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update user MO entry in sqlite " - "database: %s", sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_update_mo(struct hs20_svc *ctx, const char *user, - const char *realm, const char *name, xml_node_t *mo) -{ - char *str; - - str = xml_node_to_str(ctx->xml, mo); - if (str == NULL) - return; - - db_update_mo_str(ctx, user, realm, name, str); - free(str); -} - - -static void add_text_node(struct hs20_svc *ctx, xml_node_t *parent, - const char *name, const char *value) -{ - xml_node_create_text(ctx->xml, parent, NULL, name, value ? value : ""); -} - - -static void add_text_node_conf(struct hs20_svc *ctx, const char *realm, - xml_node_t *parent, const char *name, - const char *field) -{ - char *val; - val = db_get_osu_config_val(ctx, realm, field); - xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : ""); - os_free(val); -} - - -static void add_text_node_conf_corrupt(struct hs20_svc *ctx, const char *realm, - xml_node_t *parent, const char *name, - const char *field) -{ - char *val; - - val = db_get_osu_config_val(ctx, realm, field); - if (val) { - size_t len; - - len = os_strlen(val); - if (len > 0) { - if (val[len - 1] == '0') - val[len - 1] = '1'; - else - val[len - 1] = '0'; - } - } - xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : ""); - os_free(val); -} - - -static int new_password(char *buf, int buflen) -{ - int i; - - if (buflen < 1) - return -1; - buf[buflen - 1] = '\0'; - if (os_get_random((unsigned char *) buf, buflen - 1) < 0) - return -1; - - for (i = 0; i < buflen - 1; i++) { - unsigned char val = buf[i]; - val %= 2 * 26 + 10; - if (val < 26) - buf[i] = 'a' + val; - else if (val < 2 * 26) - buf[i] = 'A' + val - 26; - else - buf[i] = '0' + val - 2 * 26; - } - - return 0; -} - - -struct get_db_field_data { - const char *field; - char *value; -}; - - -static int get_db_field(void *ctx, int argc, char *argv[], char *col[]) -{ - struct get_db_field_data *data = ctx; - int i; - - for (i = 0; i < argc; i++) { - if (os_strcmp(col[i], data->field) == 0 && argv[i]) { - os_free(data->value); - data->value = os_strdup(argv[i]); - break; - } - } - - return 0; -} - - -static char * db_get_val(struct hs20_svc *ctx, const char *user, - const char *realm, const char *field, int dmacc) -{ - char *cmd; - struct get_db_field_data data; - - cmd = sqlite3_mprintf("SELECT %s FROM users WHERE %s=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", - field, dmacc ? "osu_user" : "identity", - user, realm); - if (cmd == NULL) - return NULL; - memset(&data, 0, sizeof(data)); - data.field = field; - if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) - { - debug_print(ctx, 1, "Could not find user '%s'", user); - sqlite3_free(cmd); - return NULL; - } - sqlite3_free(cmd); - - debug_print(ctx, 1, "DB: user='%s' realm='%s' field='%s' dmacc=%d --> " - "value='%s'", user, realm, field, dmacc, data.value); - - return data.value; -} - - -static int db_update_val(struct hs20_svc *ctx, const char *user, - const char *realm, const char *field, - const char *val, int dmacc) -{ - char *cmd; - int ret; - - cmd = sqlite3_mprintf("UPDATE users SET %s=%Q WHERE %s=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", - field, val, dmacc ? "osu_user" : "identity", user, - realm); - if (cmd == NULL) - return -1; - debug_print(ctx, 1, "DB: %s", cmd); - if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, - "Failed to update user in sqlite database: %s", - sqlite3_errmsg(ctx->db)); - ret = -1; - } else { - debug_print(ctx, 1, - "DB: user='%s' realm='%s' field='%s' set to '%s'", - user, realm, field, val); - ret = 0; - } - sqlite3_free(cmd); - - return ret; -} - - -static char * db_get_session_val(struct hs20_svc *ctx, const char *user, - const char *realm, const char *session_id, - const char *field) -{ - char *cmd; - struct get_db_field_data data; - - if (user == NULL || realm == NULL) { - cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE " - "id=%Q", field, session_id); - } else { - cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE " - "user=%Q AND realm=%Q AND id=%Q", - field, user, realm, session_id); - } - if (cmd == NULL) - return NULL; - debug_print(ctx, 1, "DB: %s", cmd); - memset(&data, 0, sizeof(data)); - data.field = field; - if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) - { - debug_print(ctx, 1, "DB: Could not find session %s: %s", - session_id, sqlite3_errmsg(ctx->db)); - sqlite3_free(cmd); - return NULL; - } - sqlite3_free(cmd); - - debug_print(ctx, 1, "DB: return '%s'", data.value); - return data.value; -} - - -static int update_password(struct hs20_svc *ctx, const char *user, - const char *realm, const char *pw, int dmacc) -{ - char *cmd; - - cmd = sqlite3_mprintf("UPDATE users SET password=%Q, " - "remediation='' " - "WHERE %s=%Q AND phase2=1", - pw, dmacc ? "osu_user" : "identity", - user); - if (cmd == NULL) - return -1; - debug_print(ctx, 1, "DB: %s", cmd); - if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update database for user '%s'", - user); - } - sqlite3_free(cmd); - - return 0; -} - - -static int clear_remediation(struct hs20_svc *ctx, const char *user, - const char *realm, int dmacc) -{ - char *cmd; - - cmd = sqlite3_mprintf("UPDATE users SET remediation='' WHERE %s=%Q", - dmacc ? "osu_user" : "identity", - user); - if (cmd == NULL) - return -1; - debug_print(ctx, 1, "DB: %s", cmd); - if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update database for user '%s'", - user); - } - sqlite3_free(cmd); - - return 0; -} - - -static int add_eap_ttls(struct hs20_svc *ctx, xml_node_t *parent) -{ - xml_node_t *node; - - node = xml_node_create(ctx->xml, parent, NULL, "EAPMethod"); - if (node == NULL) - return -1; - - add_text_node(ctx, node, "EAPType", "21"); - add_text_node(ctx, node, "InnerMethod", "MS-CHAP-V2"); - - return 0; -} - - -static xml_node_t * build_username_password(struct hs20_svc *ctx, - xml_node_t *parent, - const char *user, const char *pw) -{ - xml_node_t *node; - char *b64; - size_t len; - - node = xml_node_create(ctx->xml, parent, NULL, "UsernamePassword"); - if (node == NULL) - return NULL; - - add_text_node(ctx, node, "Username", user); - - b64 = base64_encode(pw, strlen(pw), NULL); - if (b64 == NULL) - return NULL; - len = os_strlen(b64); - if (len > 0 && b64[len - 1] == '\n') - b64[len - 1] = '\0'; - add_text_node(ctx, node, "Password", b64); - free(b64); - - return node; -} - - -static int add_username_password(struct hs20_svc *ctx, xml_node_t *cred, - const char *user, const char *pw, - int machine_managed) -{ - xml_node_t *node; - - node = build_username_password(ctx, cred, user, pw); - if (node == NULL) - return -1; - - add_text_node(ctx, node, "MachineManaged", - machine_managed ? "TRUE" : "FALSE"); - add_text_node(ctx, node, "SoftTokenApp", ""); - add_eap_ttls(ctx, node); - - return 0; -} - - -static void add_creation_date(struct hs20_svc *ctx, xml_node_t *cred) -{ - char str[30]; - time_t now; - struct tm tm; - - time(&now); - gmtime_r(&now, &tm); - snprintf(str, sizeof(str), "%04u-%02u-%02uT%02u:%02u:%02uZ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - xml_node_create_text(ctx->xml, cred, NULL, "CreationDate", str); -} - - -static xml_node_t * build_credential_pw(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *pw, int machine_managed) -{ - xml_node_t *cred; - - cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential"); - if (cred == NULL) { - debug_print(ctx, 1, "Failed to create Credential node"); - return NULL; - } - add_creation_date(ctx, cred); - if (add_username_password(ctx, cred, user, pw, machine_managed) < 0) { - xml_node_free(ctx->xml, cred); - return NULL; - } - add_text_node(ctx, cred, "Realm", realm); - - return cred; -} - - -static xml_node_t * build_credential(struct hs20_svc *ctx, - const char *user, const char *realm, - char *new_pw, size_t new_pw_len) -{ - if (new_password(new_pw, new_pw_len) < 0) - return NULL; - debug_print(ctx, 1, "Update password to '%s'", new_pw); - return build_credential_pw(ctx, user, realm, new_pw, 1); -} - - -static xml_node_t * build_credential_cert(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *cert_fingerprint) -{ - xml_node_t *cred, *cert; - - cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential"); - if (cred == NULL) { - debug_print(ctx, 1, "Failed to create Credential node"); - return NULL; - } - add_creation_date(ctx, cred); - cert = xml_node_create(ctx->xml, cred, NULL, "DigitalCertificate"); - add_text_node(ctx, cert, "CertificateType", "x509v3"); - add_text_node(ctx, cert, "CertSHA256Fingerprint", cert_fingerprint); - add_text_node(ctx, cred, "Realm", realm); - - return cred; -} - - -static xml_node_t * build_post_dev_data_response(struct hs20_svc *ctx, - xml_namespace_t **ret_ns, - const char *session_id, - const char *status, - const char *error_code) -{ - xml_node_t *spp_node = NULL; - xml_namespace_t *ns; - - spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, - "sppPostDevDataResponse"); - if (spp_node == NULL) - return NULL; - if (ret_ns) - *ret_ns = ns; - - xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); - xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); - xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status); - - if (error_code) { - xml_node_t *node; - node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); - if (node) - xml_node_add_attr(ctx->xml, node, NULL, "errorCode", - error_code); - } - - return spp_node; -} - - -static int add_update_node(struct hs20_svc *ctx, xml_node_t *spp_node, - xml_namespace_t *ns, const char *uri, - xml_node_t *upd_node) -{ - xml_node_t *node, *tnds; - char *str; - - tnds = mo_to_tnds(ctx->xml, upd_node, 0, NULL, NULL); - if (!tnds) - return -1; - - str = xml_node_to_str(ctx->xml, tnds); - xml_node_free(ctx->xml, tnds); - if (str == NULL) - return -1; - node = xml_node_create_text(ctx->xml, spp_node, ns, "updateNode", str); - free(str); - - xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", uri); - - return 0; -} - - -static xml_node_t * read_subrem_file(struct hs20_svc *ctx, - const char *subrem_id, - char *uri, size_t uri_size) -{ - char fname[200]; - char *buf, *buf2, *pos; - size_t len; - xml_node_t *node; - - os_snprintf(fname, sizeof(fname), "%s/spp/subrem/%s", - ctx->root_dir, subrem_id); - debug_print(ctx, 1, "Use subrem file %s", fname); - - buf = os_readfile(fname, &len); - if (!buf) - return NULL; - buf2 = os_realloc(buf, len + 1); - if (!buf2) { - os_free(buf); - return NULL; - } - buf = buf2; - buf[len] = '\0'; - - pos = os_strchr(buf, '\n'); - if (!pos) { - os_free(buf); - return NULL; - } - *pos++ = '\0'; - os_strlcpy(uri, buf, uri_size); - - node = xml_node_from_buf(ctx->xml, pos); - os_free(buf); - - return node; -} - - -static xml_node_t * build_sub_rem_resp(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id, - int machine_rem, int dmacc) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *cred; - char buf[400]; - char new_pw[33]; - char *status; - char *cert; - - cert = db_get_val(ctx, user, realm, "cert", dmacc); - if (cert && cert[0] == '\0') { - os_free(cert); - cert = NULL; - } - if (cert) { - char *subrem; - - /* No change needed in PPS MO unless specifically asked to */ - cred = NULL; - buf[0] = '\0'; - - subrem = db_get_val(ctx, user, realm, "subrem", dmacc); - if (subrem && subrem[0]) { - cred = read_subrem_file(ctx, subrem, buf, sizeof(buf)); - if (!cred) { - debug_print(ctx, 1, - "Could not create updateNode from subrem file"); - os_free(subrem); - os_free(cert); - return NULL; - } - } - os_free(subrem); - } else { - char *real_user = NULL; - char *pw; - - if (dmacc) { - real_user = db_get_val(ctx, user, realm, "identity", - dmacc); - if (!real_user) { - debug_print(ctx, 1, - "Could not find user identity for dmacc user '%s'", - user); - return NULL; - } - } - - pw = db_get_session_val(ctx, user, realm, session_id, - "password"); - if (pw && pw[0]) { - debug_print(ctx, 1, "New password from the user: '%s'", - pw); - snprintf(new_pw, sizeof(new_pw), "%s", pw); - free(pw); - cred = build_credential_pw(ctx, - real_user ? real_user : user, - realm, new_pw, 0); - } else { - cred = build_credential(ctx, - real_user ? real_user : user, - realm, new_pw, sizeof(new_pw)); - } - - free(real_user); - if (!cred) { - debug_print(ctx, 1, "Could not build credential"); - os_free(cert); - return NULL; - } - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", - realm); - } - - status = "Remediation complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) { - debug_print(ctx, 1, "Could not build sppPostDevDataResponse"); - os_free(cert); - return NULL; - } - - if ((cred && add_update_node(ctx, spp_node, ns, buf, cred) < 0) || - (!cred && !xml_node_create(ctx->xml, spp_node, ns, "noMOUpdate"))) { - debug_print(ctx, 1, "Could not add update node"); - xml_node_free(ctx->xml, spp_node); - os_free(cert); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - machine_rem ? "machine remediation" : - "user remediation", cred); - xml_node_free(ctx->xml, cred); - - if (cert) { - debug_print(ctx, 1, "Request DB remediation clearing on success notification (certificate credential)"); - db_add_session(ctx, user, realm, session_id, NULL, NULL, - CLEAR_REMEDIATION, NULL); - } else { - debug_print(ctx, 1, "Request DB password update on success " - "notification"); - db_add_session(ctx, user, realm, session_id, new_pw, NULL, - UPDATE_PASSWORD, NULL); - } - os_free(cert); - - return spp_node; -} - - -static xml_node_t * machine_remediation(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *session_id, int dmacc) -{ - return build_sub_rem_resp(ctx, user, realm, session_id, 1, dmacc); -} - - -static xml_node_t * cert_reenroll(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *session_id) -{ - db_add_session(ctx, user, realm, session_id, NULL, NULL, - CERT_REENROLL, NULL); - return spp_exec_get_certificate(ctx, session_id, user, realm, 0); -} - - -static xml_node_t * policy_remediation(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id, int dmacc) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *policy; - char buf[400]; - const char *status; - - hs20_eventlog(ctx, user, realm, session_id, - "requires policy remediation", NULL); - - db_add_session(ctx, user, realm, session_id, NULL, NULL, - POLICY_REMEDIATION, NULL); - - policy = build_policy(ctx, user, realm, dmacc); - if (!policy) { - return build_post_dev_data_response( - ctx, NULL, session_id, - "No update available at this time", NULL); - } - - status = "Remediation complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Policy", - realm); - - if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) { - xml_node_free(ctx->xml, spp_node); - xml_node_free(ctx->xml, policy); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "policy update (sub rem)", policy); - xml_node_free(ctx->xml, policy); - - return spp_node; -} - - -static xml_node_t * browser_remediation(struct hs20_svc *ctx, - const char *session_id, - const char *redirect_uri, - const char *uri) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *exec_node; - - if (redirect_uri == NULL) { - debug_print(ctx, 1, "Missing redirectURI attribute for user " - "remediation"); - return NULL; - } - debug_print(ctx, 1, "redirectURI %s", redirect_uri); - - spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", - NULL); - if (spp_node == NULL) - return NULL; - - exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); - xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI", - uri); - return spp_node; -} - - -static xml_node_t * user_remediation(struct hs20_svc *ctx, const char *user, - const char *realm, const char *session_id, - const char *redirect_uri) -{ - char uri[300], *val; - - hs20_eventlog(ctx, user, realm, session_id, - "requires user remediation", NULL); - val = db_get_osu_config_val(ctx, realm, "remediation_url"); - if (val == NULL) - return NULL; - - db_add_session(ctx, user, realm, session_id, NULL, redirect_uri, - USER_REMEDIATION, NULL); - - snprintf(uri, sizeof(uri), "%s%s", val, session_id); - os_free(val); - return browser_remediation(ctx, session_id, redirect_uri, uri); -} - - -static xml_node_t * free_remediation(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id, - const char *redirect_uri) -{ - char uri[300], *val; - - hs20_eventlog(ctx, user, realm, session_id, - "requires free/public account remediation", NULL); - val = db_get_osu_config_val(ctx, realm, "free_remediation_url"); - if (val == NULL) - return NULL; - - db_add_session(ctx, user, realm, session_id, NULL, redirect_uri, - FREE_REMEDIATION, NULL); - - snprintf(uri, sizeof(uri), "%s%s", val, session_id); - os_free(val); - return browser_remediation(ctx, session_id, redirect_uri, uri); -} - - -static xml_node_t * no_sub_rem(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id) -{ - const char *status; - - hs20_eventlog(ctx, user, realm, session_id, - "no subscription mediation available", NULL); - - status = "No update available at this time"; - return build_post_dev_data_response(ctx, NULL, session_id, status, - NULL); -} - - -static xml_node_t * hs20_subscription_remediation(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *session_id, - int dmacc, - const char *redirect_uri) -{ - char *type, *identity; - xml_node_t *ret; - char *free_account; - - identity = db_get_val(ctx, user, realm, "identity", dmacc); - if (identity == NULL || strlen(identity) == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "user not found in database for remediation", - NULL); - os_free(identity); - return build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", - "Not found"); - } - os_free(identity); - - free_account = db_get_osu_config_val(ctx, realm, "free_account"); - if (free_account && strcmp(free_account, user) == 0) { - free(free_account); - return no_sub_rem(ctx, user, realm, session_id); - } - free(free_account); - - type = db_get_val(ctx, user, realm, "remediation", dmacc); - if (type && strcmp(type, "free") != 0) { - char *val; - int shared = 0; - val = db_get_val(ctx, user, realm, "shared", dmacc); - if (val) - shared = atoi(val); - free(val); - if (shared) { - free(type); - return no_sub_rem(ctx, user, realm, session_id); - } - } - if (type && strcmp(type, "user") == 0) - ret = user_remediation(ctx, user, realm, session_id, - redirect_uri); - else if (type && strcmp(type, "free") == 0) - ret = free_remediation(ctx, user, realm, session_id, - redirect_uri); - else if (type && strcmp(type, "policy") == 0) - ret = policy_remediation(ctx, user, realm, session_id, dmacc); - else if (type && strcmp(type, "machine") == 0) - ret = machine_remediation(ctx, user, realm, session_id, dmacc); - else if (type && strcmp(type, "reenroll") == 0) - ret = cert_reenroll(ctx, user, realm, session_id); - else - ret = no_sub_rem(ctx, user, realm, session_id); - free(type); - - return ret; -} - - -static xml_node_t * read_policy_file(struct hs20_svc *ctx, - const char *policy_id) -{ - char fname[200]; - - snprintf(fname, sizeof(fname), "%s/spp/policy/%s.xml", - ctx->root_dir, policy_id); - debug_print(ctx, 1, "Use policy file %s", fname); - - return node_from_file(ctx->xml, fname); -} - - -static void update_policy_update_uri(struct hs20_svc *ctx, const char *realm, - xml_node_t *policy) -{ - xml_node_t *node; - char *url; - - node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate/URI"); - if (!node) - return; - - url = db_get_osu_config_val(ctx, realm, "policy_url"); - if (!url) - return; - xml_node_set_text(ctx->xml, node, url); - free(url); -} - - -static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user, - const char *realm, int use_dmacc) -{ - char *policy_id; - xml_node_t *policy, *node; - - policy_id = db_get_val(ctx, user, realm, "policy", use_dmacc); - if (policy_id == NULL || strlen(policy_id) == 0) { - free(policy_id); - policy_id = strdup("default"); - if (policy_id == NULL) - return NULL; - } - policy = read_policy_file(ctx, policy_id); - free(policy_id); - if (policy == NULL) - return NULL; - - update_policy_update_uri(ctx, realm, policy); - - node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate"); - if (node && use_dmacc) { - char *pw; - pw = db_get_val(ctx, user, realm, "osu_password", use_dmacc); - if (pw == NULL || - build_username_password(ctx, node, user, pw) == NULL) { - debug_print(ctx, 1, "Failed to add Policy/PolicyUpdate/" - "UsernamePassword"); - free(pw); - xml_node_free(ctx->xml, policy); - return NULL; - } - free(pw); - } - - return policy; -} - - -static xml_node_t * hs20_policy_update(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id, int dmacc) -{ - xml_namespace_t *ns; - xml_node_t *spp_node; - xml_node_t *policy; - char buf[400]; - const char *status; - char *identity; - - identity = db_get_val(ctx, user, realm, "identity", dmacc); - if (identity == NULL || strlen(identity) == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "user not found in database for policy update", - NULL); - os_free(identity); - return build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", - "Not found"); - } - os_free(identity); - - policy = build_policy(ctx, user, realm, dmacc); - if (!policy) { - return build_post_dev_data_response( - ctx, NULL, session_id, - "No update available at this time", NULL); - } - - db_add_session(ctx, user, realm, session_id, NULL, NULL, POLICY_UPDATE, - NULL); - - status = "Update complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Policy", - realm); - - if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) { - xml_node_free(ctx->xml, spp_node); - xml_node_free(ctx->xml, policy); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, "policy update", - policy); - xml_node_free(ctx->xml, policy); - - return spp_node; -} - - -static xml_node_t * spp_get_mo(struct hs20_svc *ctx, xml_node_t *node, - const char *urn, int *valid, char **ret_err) -{ - xml_node_t *child, *tnds, *mo; - const char *name; - char *mo_urn; - char *str; - char fname[200]; - - *valid = -1; - if (ret_err) - *ret_err = NULL; - - xml_node_for_each_child(ctx->xml, child, node) { - xml_node_for_each_check(ctx->xml, child); - name = xml_node_get_localname(ctx->xml, child); - if (strcmp(name, "moContainer") != 0) - continue; - mo_urn = xml_node_get_attr_value_ns(ctx->xml, child, SPP_NS_URI, - "moURN"); - if (strcasecmp(urn, mo_urn) == 0) { - xml_node_get_attr_value_free(ctx->xml, mo_urn); - break; - } - xml_node_get_attr_value_free(ctx->xml, mo_urn); - } - - if (child == NULL) - return NULL; - - debug_print(ctx, 1, "moContainer text for %s", urn); - debug_dump_node(ctx, "moContainer", child); - - str = xml_node_get_text(ctx->xml, child); - debug_print(ctx, 1, "moContainer payload: '%s'", str); - tnds = xml_node_from_buf(ctx->xml, str); - xml_node_get_text_free(ctx->xml, str); - if (tnds == NULL) { - debug_print(ctx, 1, "could not parse moContainer text"); - return NULL; - } - - snprintf(fname, sizeof(fname), "%s/spp/dm_ddf-v1_2.dtd", ctx->root_dir); - if (xml_validate_dtd(ctx->xml, tnds, fname, ret_err) == 0) - *valid = 1; - else if (ret_err && *ret_err && - os_strcmp(*ret_err, "No declaration for attribute xmlns of element MgmtTree\n") == 0) { - free(*ret_err); - debug_print(ctx, 1, "Ignore OMA-DM DDF DTD validation error for MgmtTree namespace declaration with xmlns attribute"); - *ret_err = NULL; - *valid = 1; - } else - *valid = 0; - - mo = tnds_to_mo(ctx->xml, tnds); - xml_node_free(ctx->xml, tnds); - if (mo == NULL) { - debug_print(ctx, 1, "invalid moContainer for %s", urn); - } - - return mo; -} - - -static xml_node_t * spp_exec_upload_mo(struct hs20_svc *ctx, - const char *session_id, const char *urn) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *node, *exec_node; - - spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", - NULL); - if (spp_node == NULL) - return NULL; - - exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); - - node = xml_node_create(ctx->xml, exec_node, ns, "uploadMO"); - xml_node_add_attr(ctx->xml, node, ns, "moURN", urn); - - return spp_node; -} - - -static xml_node_t * hs20_subscription_registration(struct hs20_svc *ctx, - const char *realm, - const char *session_id, - const char *redirect_uri, - const u8 *mac_addr) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *exec_node; - char uri[300], *val; - - if (db_add_session(ctx, NULL, realm, session_id, NULL, redirect_uri, - SUBSCRIPTION_REGISTRATION, mac_addr) < 0) - return NULL; - val = db_get_osu_config_val(ctx, realm, "signup_url"); - if (val == NULL) - return NULL; - - spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", - NULL); - if (spp_node == NULL) - return NULL; - - exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); - - snprintf(uri, sizeof(uri), "%s%s", val, session_id); - os_free(val); - xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI", - uri); - return spp_node; -} - - -static xml_node_t * hs20_user_input_remediation(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - return build_sub_rem_resp(ctx, user, realm, session_id, 0, dmacc); -} - - -static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, - const char *field) -{ - char *cmd; - struct get_db_field_data data; - - cmd = sqlite3_mprintf("SELECT value FROM osu_config WHERE realm=%Q AND " - "field=%Q", realm, field); - if (cmd == NULL) - return NULL; - debug_print(ctx, 1, "DB: %s", cmd); - memset(&data, 0, sizeof(data)); - data.field = "value"; - if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) - { - debug_print(ctx, 1, "DB: Could not find osu_config %s: %s", - realm, sqlite3_errmsg(ctx->db)); - sqlite3_free(cmd); - return NULL; - } - sqlite3_free(cmd); - - debug_print(ctx, 1, "DB: return '%s'", data.value); - return data.value; -} - - -static xml_node_t * build_pps(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *pw, const char *cert, - int machine_managed, const char *test, - const char *imsi, const char *dmacc_username, - const char *dmacc_password, - xml_node_t *policy_node) -{ - xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp, *p; - xml_node_t *cred, *eap, *userpw; - - pps = xml_node_create_root(ctx->xml, NULL, NULL, NULL, - "PerProviderSubscription"); - if (!pps) { - xml_node_free(ctx->xml, policy_node); - return NULL; - } - - add_text_node(ctx, pps, "UpdateIdentifier", "1"); - - c = xml_node_create(ctx->xml, pps, NULL, "Cred01"); - - add_text_node(ctx, c, "CredentialPriority", "1"); - - if (imsi) - goto skip_aaa_trust_root; - aaa = xml_node_create(ctx->xml, c, NULL, "AAAServerTrustRoot"); - aaa1 = xml_node_create(ctx->xml, aaa, NULL, "AAA1"); - add_text_node_conf(ctx, realm, aaa1, "CertURL", - "aaa_trust_root_cert_url"); - if (test && os_strcmp(test, "corrupt_aaa_hash") == 0) { - debug_print(ctx, 1, - "TEST: Corrupt PPS/Cred*/AAAServerTrustRoot/Root*/CertSHA256FingerPrint"); - add_text_node_conf_corrupt(ctx, realm, aaa1, - "CertSHA256Fingerprint", - "aaa_trust_root_cert_fingerprint"); - } else { - add_text_node_conf(ctx, realm, aaa1, "CertSHA256Fingerprint", - "aaa_trust_root_cert_fingerprint"); - } - - if (test && os_strcmp(test, "corrupt_polupd_hash") == 0) { - debug_print(ctx, 1, - "TEST: Corrupt PPS/Cred*/Policy/PolicyUpdate/Trustroot/CertSHA256FingerPrint"); - p = xml_node_create(ctx->xml, c, NULL, "Policy"); - upd = xml_node_create(ctx->xml, p, NULL, "PolicyUpdate"); - add_text_node(ctx, upd, "UpdateInterval", "30"); - add_text_node(ctx, upd, "UpdateMethod", "SPP-ClientInitiated"); - add_text_node(ctx, upd, "Restriction", "Unrestricted"); - add_text_node_conf(ctx, realm, upd, "URI", "policy_url"); - trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot"); - add_text_node_conf(ctx, realm, trust, "CertURL", - "policy_trust_root_cert_url"); - add_text_node_conf_corrupt(ctx, realm, trust, - "CertSHA256Fingerprint", - "policy_trust_root_cert_fingerprint"); - } -skip_aaa_trust_root: - - upd = xml_node_create(ctx->xml, c, NULL, "SubscriptionUpdate"); - add_text_node(ctx, upd, "UpdateInterval", "4294967295"); - add_text_node(ctx, upd, "UpdateMethod", "SPP-ClientInitiated"); - add_text_node(ctx, upd, "Restriction", "HomeSP"); - add_text_node_conf(ctx, realm, upd, "URI", "spp_http_auth_url"); - trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot"); - add_text_node_conf(ctx, realm, trust, "CertURL", "trust_root_cert_url"); - if (test && os_strcmp(test, "corrupt_subrem_hash") == 0) { - debug_print(ctx, 1, - "TEST: Corrupt PPS/Cred*/SubscriptionUpdate/Trustroot/CertSHA256FingerPrint"); - add_text_node_conf_corrupt(ctx, realm, trust, - "CertSHA256Fingerprint", - "trust_root_cert_fingerprint"); - } else { - add_text_node_conf(ctx, realm, trust, "CertSHA256Fingerprint", - "trust_root_cert_fingerprint"); - } - - if (dmacc_username && - !build_username_password(ctx, upd, dmacc_username, - dmacc_password)) { - xml_node_free(ctx->xml, pps); - xml_node_free(ctx->xml, policy_node); - return NULL; - } - - if (policy_node) - xml_node_add_child(ctx->xml, c, policy_node); - - homesp = xml_node_create(ctx->xml, c, NULL, "HomeSP"); - add_text_node_conf(ctx, realm, homesp, "FriendlyName", "friendly_name"); - add_text_node_conf(ctx, realm, homesp, "FQDN", "fqdn"); - - xml_node_create(ctx->xml, c, NULL, "SubscriptionParameters"); - - cred = xml_node_create(ctx->xml, c, NULL, "Credential"); - add_creation_date(ctx, cred); - if (imsi) { - xml_node_t *sim; - const char *type = "18"; /* default to EAP-SIM */ - - sim = xml_node_create(ctx->xml, cred, NULL, "SIM"); - add_text_node(ctx, sim, "IMSI", imsi); - if (ctx->eap_method && os_strcmp(ctx->eap_method, "AKA") == 0) - type = "23"; - else if (ctx->eap_method && - os_strcmp(ctx->eap_method, "AKA'") == 0) - type = "50"; - add_text_node(ctx, sim, "EAPType", type); - } else if (cert) { - xml_node_t *dc; - dc = xml_node_create(ctx->xml, cred, NULL, - "DigitalCertificate"); - add_text_node(ctx, dc, "CertificateType", "x509v3"); - add_text_node(ctx, dc, "CertSHA256Fingerprint", cert); - } else { - userpw = build_username_password(ctx, cred, user, pw); - add_text_node(ctx, userpw, "MachineManaged", - machine_managed ? "TRUE" : "FALSE"); - eap = xml_node_create(ctx->xml, userpw, NULL, "EAPMethod"); - add_text_node(ctx, eap, "EAPType", "21"); - add_text_node(ctx, eap, "InnerMethod", "MS-CHAP-V2"); - } - add_text_node(ctx, cred, "Realm", realm); - - return pps; -} - - -static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx, - const char *session_id, - const char *user, - const char *realm, - int add_est_user) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *enroll, *exec_node; - char *val; - char password[11]; - char *b64; - - if (add_est_user && new_password(password, sizeof(password)) < 0) - return NULL; - - spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", - NULL); - if (spp_node == NULL) - return NULL; - - exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); - - enroll = xml_node_create(ctx->xml, exec_node, ns, "getCertificate"); - xml_node_add_attr(ctx->xml, enroll, NULL, "enrollmentProtocol", "EST"); - - val = db_get_osu_config_val(ctx, realm, "est_url"); - xml_node_create_text(ctx->xml, enroll, ns, "enrollmentServerURI", - val ? val : ""); - os_free(val); - - if (!add_est_user) - return spp_node; - - xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user); - - b64 = base64_encode(password, strlen(password), NULL); - if (b64 == NULL) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - xml_node_create_text(ctx->xml, enroll, ns, "estPassword", b64); - free(b64); - - db_update_session_password(ctx, user, realm, session_id, password); - - return spp_node; -} - - -static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx, - const char *session_id, - int enrollment_done) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *node = NULL; - xml_node_t *pps, *tnds; - char buf[400]; - char *str; - char *user, *realm, *pw, *type, *mm, *test; - const char *status; - int cert = 0; - int machine_managed = 0; - char *fingerprint; - - user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); - realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); - pw = db_get_session_val(ctx, NULL, NULL, session_id, "password"); - - if (!user || !realm || !pw) { - debug_print(ctx, 1, "Could not find session info from DB for " - "the new subscription"); - free(user); - free(realm); - free(pw); - return NULL; - } - - mm = db_get_session_val(ctx, NULL, NULL, session_id, "machine_managed"); - if (mm && atoi(mm)) - machine_managed = 1; - free(mm); - - type = db_get_session_val(ctx, NULL, NULL, session_id, "type"); - if (type && strcmp(type, "cert") == 0) - cert = 1; - free(type); - - if (cert && !enrollment_done) { - xml_node_t *ret; - hs20_eventlog(ctx, user, realm, session_id, - "request client certificate enrollment", NULL); - ret = spp_exec_get_certificate(ctx, session_id, user, realm, 1); - free(user); - free(realm); - free(pw); - return ret; - } - - if (!cert && strlen(pw) == 0) { - machine_managed = 1; - free(pw); - pw = malloc(11); - if (pw == NULL || new_password(pw, 11) < 0) { - free(user); - free(realm); - free(pw); - return NULL; - } - } - - status = "Provisioning complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - - fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); - test = db_get_session_val(ctx, NULL, NULL, session_id, "test"); - if (test) - debug_print(ctx, 1, "TEST: Requested special behavior: %s", - test); - pps = build_pps(ctx, user, realm, pw, - fingerprint ? fingerprint : NULL, machine_managed, - test, NULL, NULL, NULL, NULL); - free(fingerprint); - free(test); - if (!pps) { - xml_node_free(ctx->xml, spp_node); - free(user); - free(realm); - free(pw); - return NULL; - } - - debug_print(ctx, 1, "Request DB subscription registration on success " - "notification"); - if (machine_managed) { - db_update_session_password(ctx, user, realm, session_id, pw); - db_update_session_machine_managed(ctx, user, realm, session_id, - machine_managed); - } - db_add_session_pps(ctx, user, realm, session_id, pps); - - hs20_eventlog_node(ctx, user, realm, session_id, - "new subscription", pps); - free(user); - free(pw); - - tnds = mo_to_tnds(ctx->xml, pps, 0, URN_HS20_PPS, NULL); - xml_node_free(ctx->xml, pps); - if (!tnds) { - xml_node_free(ctx->xml, spp_node); - free(realm); - return NULL; - } - - str = xml_node_to_str(ctx->xml, tnds); - xml_node_free(ctx->xml, tnds); - if (str == NULL) { - xml_node_free(ctx->xml, spp_node); - free(realm); - return NULL; - } - - node = xml_node_create_text(ctx->xml, spp_node, ns, "addMO", str); - free(str); - snprintf(buf, sizeof(buf), "./Wi-Fi/%s/PerProviderSubscription", realm); - free(realm); - xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", buf); - xml_node_add_attr(ctx->xml, node, ns, "moURN", URN_HS20_PPS); - - return spp_node; -} - - -static xml_node_t * hs20_user_input_free_remediation(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *session_id) -{ - xml_namespace_t *ns; - xml_node_t *spp_node; - xml_node_t *cred; - char buf[400]; - char *status; - char *free_account, *pw; - - free_account = db_get_osu_config_val(ctx, realm, "free_account"); - if (free_account == NULL) - return NULL; - pw = db_get_val(ctx, free_account, realm, "password", 0); - if (pw == NULL) { - free(free_account); - return NULL; - } - - cred = build_credential_pw(ctx, free_account, realm, pw, 1); - free(free_account); - free(pw); - if (!cred) { - xml_node_free(ctx->xml, cred); - return NULL; - } - - status = "Remediation complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", - realm); - - if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "free/public remediation", cred); - xml_node_free(ctx->xml, cred); - - return spp_node; -} - - -static xml_node_t * hs20_user_input_complete(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - char *val; - enum hs20_session_operation oper; - - val = db_get_session_val(ctx, user, realm, session_id, "operation"); - if (val == NULL) { - debug_print(ctx, 1, "No session %s found to continue", - session_id); - return NULL; - } - oper = atoi(val); - free(val); - - if (oper == USER_REMEDIATION) { - return hs20_user_input_remediation(ctx, user, realm, dmacc, - session_id); - } - - if (oper == FREE_REMEDIATION) { - return hs20_user_input_free_remediation(ctx, user, realm, - session_id); - } - - if (oper == SUBSCRIPTION_REGISTRATION) { - return hs20_user_input_registration(ctx, session_id, 0); - } - - debug_print(ctx, 1, "User session %s not in state for user input " - "completion", session_id); - return NULL; -} - - -static xml_node_t * hs20_cert_reenroll_complete(struct hs20_svc *ctx, - const char *session_id) -{ - char *user, *realm, *cert; - char *status; - xml_namespace_t *ns; - xml_node_t *spp_node, *cred; - char buf[400]; - - user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); - realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); - cert = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); - if (!user || !realm || !cert) { - debug_print(ctx, 1, - "Could not find session info from DB for certificate reenrollment"); - free(user); - free(realm); - free(cert); - return NULL; - } - - cred = build_credential_cert(ctx, user, realm, cert); - if (!cred) { - debug_print(ctx, 1, "Could not build credential"); - free(user); - free(realm); - free(cert); - return NULL; - } - - status = "Remediation complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) { - debug_print(ctx, 1, "Could not build sppPostDevDataResponse"); - free(user); - free(realm); - free(cert); - xml_node_free(ctx->xml, cred); - return NULL; - } - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", - realm); - - if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) { - debug_print(ctx, 1, "Could not add update node"); - xml_node_free(ctx->xml, spp_node); - free(user); - free(realm); - free(cert); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "certificate reenrollment", cred); - xml_node_free(ctx->xml, cred); - - free(user); - free(realm); - free(cert); - return spp_node; -} - - -static xml_node_t * hs20_cert_enroll_completed(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - char *val; - enum hs20_session_operation oper; - - val = db_get_session_val(ctx, NULL, NULL, session_id, "operation"); - if (val == NULL) { - debug_print(ctx, 1, "No session %s found to continue", - session_id); - return NULL; - } - oper = atoi(val); - free(val); - - if (oper == SUBSCRIPTION_REGISTRATION) - return hs20_user_input_registration(ctx, session_id, 1); - if (oper == CERT_REENROLL) - return hs20_cert_reenroll_complete(ctx, session_id); - - debug_print(ctx, 1, "User session %s not in state for certificate " - "enrollment completion", session_id); - return NULL; -} - - -static xml_node_t * hs20_cert_enroll_failed(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - char *val; - enum hs20_session_operation oper; - xml_node_t *spp_node, *node; - char *status; - xml_namespace_t *ns; - - val = db_get_session_val(ctx, user, realm, session_id, "operation"); - if (val == NULL) { - debug_print(ctx, 1, "No session %s found to continue", - session_id); - return NULL; - } - oper = atoi(val); - free(val); - - if (oper != SUBSCRIPTION_REGISTRATION) { - debug_print(ctx, 1, "User session %s not in state for " - "enrollment failure", session_id); - return NULL; - } - - status = "Error occurred"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); - xml_node_add_attr(ctx->xml, node, NULL, "errorCode", - "Credentials cannot be provisioned at this time"); - db_remove_session(ctx, user, realm, session_id); - - return spp_node; -} - - -static xml_node_t * hs20_sim_provisioning(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *node = NULL; - xml_node_t *pps, *tnds; - char buf[400]; - char *str; - const char *status; - char dmacc_username[32]; - char dmacc_password[32]; - char *policy; - xml_node_t *policy_node = NULL; - - if (!ctx->imsi) { - debug_print(ctx, 1, "IMSI not available for SIM provisioning"); - return NULL; - } - - if (new_password(dmacc_username, sizeof(dmacc_username)) < 0 || - new_password(dmacc_password, sizeof(dmacc_password)) < 0) { - debug_print(ctx, 1, - "Failed to generate DMAcc username/password"); - return NULL; - } - - status = "Provisioning complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (!spp_node) - return NULL; - - policy = db_get_osu_config_val(ctx, realm, "sim_policy"); - if (policy) { - policy_node = read_policy_file(ctx, policy); - os_free(policy); - if (!policy_node) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - update_policy_update_uri(ctx, realm, policy_node); - node = get_node_uri(ctx->xml, policy_node, - "Policy/PolicyUpdate"); - if (node) - build_username_password(ctx, node, dmacc_username, - dmacc_password); - } - - pps = build_pps(ctx, NULL, realm, NULL, NULL, 0, NULL, ctx->imsi, - dmacc_username, dmacc_password, policy_node); - if (!pps) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - - debug_print(ctx, 1, - "Request DB subscription registration on success notification"); - if (!user || !user[0]) - user = ctx->imsi; - db_add_session(ctx, user, realm, session_id, NULL, NULL, - SUBSCRIPTION_REGISTRATION, NULL); - db_add_session_dmacc(ctx, session_id, dmacc_username, dmacc_password); - if (ctx->eap_method) - db_add_session_eap_method(ctx, session_id, ctx->eap_method); - if (ctx->id_hash) - db_add_session_id_hash(ctx, session_id, ctx->id_hash); - db_add_session_pps(ctx, user, realm, session_id, pps); - - hs20_eventlog_node(ctx, user, realm, session_id, - "new subscription", pps); - - tnds = mo_to_tnds(ctx->xml, pps, 0, URN_HS20_PPS, NULL); - xml_node_free(ctx->xml, pps); - if (!tnds) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - - str = xml_node_to_str(ctx->xml, tnds); - xml_node_free(ctx->xml, tnds); - if (!str) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - - node = xml_node_create_text(ctx->xml, spp_node, ns, "addMO", str); - free(str); - snprintf(buf, sizeof(buf), "./Wi-Fi/%s/PerProviderSubscription", realm); - xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", buf); - xml_node_add_attr(ctx->xml, node, ns, "moURN", URN_HS20_PPS); - - return spp_node; -} - - -static xml_node_t * hs20_spp_post_dev_data(struct hs20_svc *ctx, - xml_node_t *node, - const char *user, - const char *realm, - const char *session_id, - int dmacc) -{ - const char *req_reason; - char *redirect_uri = NULL; - char *req_reason_buf = NULL; - char str[200]; - xml_node_t *ret = NULL, *devinfo = NULL, *devdetail = NULL; - xml_node_t *mo, *macaddr; - char *version; - int valid; - char *supp, *pos; - char *err; - u8 wifi_mac_addr[ETH_ALEN]; - - version = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, - "sppVersion"); - if (version == NULL || strstr(version, "1.0") == NULL) { - ret = build_post_dev_data_response( - ctx, NULL, session_id, "Error occurred", - "SPP version not supported"); - hs20_eventlog_node(ctx, user, realm, session_id, - "Unsupported sppVersion", ret); - xml_node_get_attr_value_free(ctx->xml, version); - return ret; - } - xml_node_get_attr_value_free(ctx->xml, version); - - mo = get_node(ctx->xml, node, "supportedMOList"); - if (mo == NULL) { - ret = build_post_dev_data_response( - ctx, NULL, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, session_id, - "No supportedMOList element", ret); - return ret; - } - supp = xml_node_get_text(ctx->xml, mo); - for (pos = supp; pos && *pos; pos++) - *pos = tolower(*pos); - if (supp == NULL || - strstr(supp, URN_OMA_DM_DEVINFO) == NULL || - strstr(supp, URN_OMA_DM_DEVDETAIL) == NULL || - strstr(supp, URN_HS20_PPS) == NULL) { - xml_node_get_text_free(ctx->xml, supp); - ret = build_post_dev_data_response( - ctx, NULL, session_id, "Error occurred", - "One or more mandatory MOs not supported"); - hs20_eventlog_node(ctx, user, realm, session_id, - "Unsupported MOs", ret); - return ret; - } - xml_node_get_text_free(ctx->xml, supp); - - req_reason_buf = xml_node_get_attr_value(ctx->xml, node, - "requestReason"); - if (req_reason_buf == NULL) { - debug_print(ctx, 1, "No requestReason attribute"); - return NULL; - } - req_reason = req_reason_buf; - - redirect_uri = xml_node_get_attr_value(ctx->xml, node, "redirectURI"); - - debug_print(ctx, 1, "requestReason: %s sessionID: %s redirectURI: %s", - req_reason, session_id, redirect_uri); - snprintf(str, sizeof(str), "sppPostDevData: requestReason=%s", - req_reason); - hs20_eventlog(ctx, user, realm, session_id, str, NULL); - - devinfo = spp_get_mo(ctx, node, URN_OMA_DM_DEVINFO, &valid, &err); - if (devinfo == NULL) { - ret = build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", "Other"); - hs20_eventlog_node(ctx, user, realm, session_id, - "No DevInfo moContainer in sppPostDevData", - ret); - os_free(err); - goto out; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "Received DevInfo MO", devinfo); - if (valid == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "OMA-DM DDF DTD validation errors in DevInfo MO", - err); - ret = build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", "Other"); - os_free(err); - goto out; - } - os_free(err); - if (user) - db_update_mo(ctx, user, realm, "devinfo", devinfo); - - devdetail = spp_get_mo(ctx, node, URN_OMA_DM_DEVDETAIL, &valid, &err); - if (devdetail == NULL) { - ret = build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", "Other"); - hs20_eventlog_node(ctx, user, realm, session_id, - "No DevDetail moContainer in sppPostDevData", - ret); - os_free(err); - goto out; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "Received DevDetail MO", devdetail); - if (valid == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "OMA-DM DDF DTD validation errors " - "in DevDetail MO", err); - ret = build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", "Other"); - os_free(err); - goto out; - } - os_free(err); - - os_memset(wifi_mac_addr, 0, ETH_ALEN); - macaddr = get_node(ctx->xml, devdetail, - "Ext/org.wi-fi/Wi-Fi/Wi-FiMACAddress"); - if (macaddr) { - char *addr, buf[50]; - - addr = xml_node_get_text(ctx->xml, macaddr); - if (addr && hwaddr_compact_aton(addr, wifi_mac_addr) == 0) { - snprintf(buf, sizeof(buf), "DevDetail MAC address: " - MACSTR, MAC2STR(wifi_mac_addr)); - hs20_eventlog(ctx, user, realm, session_id, buf, NULL); - xml_node_get_text_free(ctx->xml, addr); - } else { - hs20_eventlog(ctx, user, realm, session_id, - "Could not extract MAC address from DevDetail", - NULL); - } - } else { - hs20_eventlog(ctx, user, realm, session_id, - "No MAC address in DevDetail", NULL); - } - - if (user) - db_update_mo(ctx, user, realm, "devdetail", devdetail); - - if (user) - mo = spp_get_mo(ctx, node, URN_HS20_PPS, &valid, &err); - else { - mo = NULL; - err = NULL; - } - if (user && mo) { - hs20_eventlog_node(ctx, user, realm, session_id, - "Received PPS MO", mo); - if (valid == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "OMA-DM DDF DTD validation errors " - "in PPS MO", err); - xml_node_get_attr_value_free(ctx->xml, redirect_uri); - os_free(err); - return build_post_dev_data_response( - ctx, NULL, session_id, - "Error occurred", "Other"); - } - db_update_mo(ctx, user, realm, "pps", mo); - db_update_val(ctx, user, realm, "fetch_pps", "0", dmacc); - xml_node_free(ctx->xml, mo); - } - os_free(err); - - if (user && !mo) { - char *fetch; - int fetch_pps; - - fetch = db_get_val(ctx, user, realm, "fetch_pps", dmacc); - fetch_pps = fetch ? atoi(fetch) : 0; - free(fetch); - - if (fetch_pps) { - enum hs20_session_operation oper; - if (strcasecmp(req_reason, "Subscription remediation") - == 0) - oper = CONTINUE_SUBSCRIPTION_REMEDIATION; - else if (strcasecmp(req_reason, "Policy update") == 0) - oper = CONTINUE_POLICY_UPDATE; - else - oper = NO_OPERATION; - if (db_add_session(ctx, user, realm, session_id, NULL, - NULL, oper, NULL) < 0) - goto out; - - ret = spp_exec_upload_mo(ctx, session_id, - URN_HS20_PPS); - hs20_eventlog_node(ctx, user, realm, session_id, - "request PPS MO upload", - ret); - goto out; - } - } - - if (user && strcasecmp(req_reason, "MO upload") == 0) { - char *val = db_get_session_val(ctx, user, realm, session_id, - "operation"); - enum hs20_session_operation oper; - if (!val) { - debug_print(ctx, 1, "No session %s found to continue", - session_id); - goto out; - } - oper = atoi(val); - free(val); - if (oper == CONTINUE_SUBSCRIPTION_REMEDIATION) - req_reason = "Subscription remediation"; - else if (oper == CONTINUE_POLICY_UPDATE) - req_reason = "Policy update"; - else { - debug_print(ctx, 1, - "No pending operation in session %s", - session_id); - goto out; - } - } - - if (strcasecmp(req_reason, "Subscription registration") == 0) { - ret = hs20_subscription_registration(ctx, realm, session_id, - redirect_uri, - wifi_mac_addr); - hs20_eventlog_node(ctx, user, realm, session_id, - "subscription registration response", - ret); - goto out; - } - if (user && strcasecmp(req_reason, "Subscription remediation") == 0) { - ret = hs20_subscription_remediation(ctx, user, realm, - session_id, dmacc, - redirect_uri); - hs20_eventlog_node(ctx, user, realm, session_id, - "subscription remediation response", - ret); - goto out; - } - if (user && strcasecmp(req_reason, "Policy update") == 0) { - ret = hs20_policy_update(ctx, user, realm, session_id, dmacc); - hs20_eventlog_node(ctx, user, realm, session_id, - "policy update response", - ret); - goto out; - } - - if (strcasecmp(req_reason, "User input completed") == 0) { - db_add_session_devinfo(ctx, session_id, devinfo); - db_add_session_devdetail(ctx, session_id, devdetail); - ret = hs20_user_input_complete(ctx, user, realm, dmacc, - session_id); - hs20_eventlog_node(ctx, user, realm, session_id, - "user input completed response", ret); - goto out; - } - - if (strcasecmp(req_reason, "Certificate enrollment completed") == 0) { - ret = hs20_cert_enroll_completed(ctx, user, realm, dmacc, - session_id); - hs20_eventlog_node(ctx, user, realm, session_id, - "certificate enrollment response", ret); - goto out; - } - - if (strcasecmp(req_reason, "Certificate enrollment failed") == 0) { - ret = hs20_cert_enroll_failed(ctx, user, realm, dmacc, - session_id); - hs20_eventlog_node(ctx, user, realm, session_id, - "certificate enrollment failed response", - ret); - goto out; - } - - if (strcasecmp(req_reason, "Subscription provisioning") == 0) { - ret = hs20_sim_provisioning(ctx, user, realm, dmacc, - session_id); - hs20_eventlog_node(ctx, user, realm, session_id, - "subscription provisioning response", - ret); - goto out; - } - - debug_print(ctx, 1, "Unsupported requestReason '%s' user '%s'", - req_reason, user); -out: - xml_node_get_attr_value_free(ctx->xml, req_reason_buf); - xml_node_get_attr_value_free(ctx->xml, redirect_uri); - if (devinfo) - xml_node_free(ctx->xml, devinfo); - if (devdetail) - xml_node_free(ctx->xml, devdetail); - return ret; -} - - -static xml_node_t * build_spp_exchange_complete(struct hs20_svc *ctx, - const char *session_id, - const char *status, - const char *error_code) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *node; - - spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, - "sppExchangeComplete"); - - - xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); - xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); - xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status); - - if (error_code) { - node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); - xml_node_add_attr(ctx->xml, node, NULL, "errorCode", - error_code); - } - - return spp_node; -} - - -static int add_subscription(struct hs20_svc *ctx, const char *session_id) -{ - char *user, *realm, *pw, *pw_mm, *pps, *str; - char *osu_user, *osu_password, *eap_method; - char *policy = NULL; - char *sql; - int ret = -1; - char *free_account; - int free_acc; - char *type; - int cert = 0; - char *cert_pem, *fingerprint; - const char *method; - - user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); - realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); - pw = db_get_session_val(ctx, NULL, NULL, session_id, "password"); - pw_mm = db_get_session_val(ctx, NULL, NULL, session_id, - "machine_managed"); - pps = db_get_session_val(ctx, NULL, NULL, session_id, "pps"); - cert_pem = db_get_session_val(ctx, NULL, NULL, session_id, "cert_pem"); - fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); - type = db_get_session_val(ctx, NULL, NULL, session_id, "type"); - if (type && strcmp(type, "cert") == 0) - cert = 1; - free(type); - osu_user = db_get_session_val(ctx, NULL, NULL, session_id, "osu_user"); - osu_password = db_get_session_val(ctx, NULL, NULL, session_id, - "osu_password"); - eap_method = db_get_session_val(ctx, NULL, NULL, session_id, - "eap_method"); - - if (!user || !realm || !pw) { - debug_print(ctx, 1, "Could not find session info from DB for " - "the new subscription"); - goto out; - } - - free_account = db_get_osu_config_val(ctx, realm, "free_account"); - free_acc = free_account && strcmp(free_account, user) == 0; - free(free_account); - - policy = db_get_osu_config_val(ctx, realm, "sim_policy"); - - debug_print(ctx, 1, - "New subscription: user='%s' realm='%s' free_acc=%d", - user, realm, free_acc); - debug_print(ctx, 1, "New subscription: pps='%s'", pps); - - sql = sqlite3_mprintf("UPDATE eventlog SET user=%Q, realm=%Q WHERE " - "sessionid=%Q AND (user='' OR user IS NULL)", - user, realm, session_id); - if (sql) { - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update eventlog in " - "sqlite database: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); - } - - if (free_acc) { - hs20_eventlog(ctx, user, realm, session_id, - "completed shared free account registration", - NULL); - ret = 0; - goto out; - } - - str = db_get_session_val(ctx, NULL, NULL, session_id, "mac_addr"); - - if (eap_method && eap_method[0]) - method = eap_method; - else - method = cert ? "TLS" : "TTLS-MSCHAPV2"; - sql = sqlite3_mprintf("INSERT INTO users(identity,realm,phase2,methods,cert,cert_pem,machine_managed,mac_addr,osu_user,osu_password,policy) VALUES (%Q,%Q,%d,%Q,%Q,%Q,%d,%Q,%Q,%Q,%Q)", - user, realm, cert ? 0 : 1, - method, - fingerprint ? fingerprint : "", - cert_pem ? cert_pem : "", - pw_mm && atoi(pw_mm) ? 1 : 0, - str ? str : "", - osu_user ? osu_user : "", - osu_password ? osu_password : "", - policy ? policy : ""); - free(str); - if (sql == NULL) - goto out; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add user in sqlite database: %s", - sqlite3_errmsg(ctx->db)); - sqlite3_free(sql); - goto out; - } - sqlite3_free(sql); - - if (cert) - ret = 0; - else - ret = update_password(ctx, user, realm, pw, 0); - if (ret < 0) { - sql = sqlite3_mprintf("DELETE FROM users WHERE identity=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", - user, realm); - if (sql) { - debug_print(ctx, 1, "DB: %s", sql); - sqlite3_exec(ctx->db, sql, NULL, NULL, NULL); - sqlite3_free(sql); - } - } - - if (pps) - db_update_mo_str(ctx, user, realm, "pps", pps); - - str = db_get_session_val(ctx, NULL, NULL, session_id, "devinfo"); - if (str) { - db_update_mo_str(ctx, user, realm, "devinfo", str); - free(str); - } - - str = db_get_session_val(ctx, NULL, NULL, session_id, "devdetail"); - if (str) { - db_update_mo_str(ctx, user, realm, "devdetail", str); - free(str); - } - - if (cert && user) { - const char *serialnum; - - str = db_get_session_val(ctx, NULL, NULL, session_id, - "mac_addr"); - - if (os_strncmp(user, "cert-", 5) == 0) - serialnum = user + 5; - else - serialnum = ""; - sql = sqlite3_mprintf("INSERT OR REPLACE INTO cert_enroll (mac_addr,user,realm,serialnum) VALUES(%Q,%Q,%Q,%Q)", - str ? str : "", user, realm ? realm : "", - serialnum); - free(str); - if (sql) { - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != - SQLITE_OK) { - debug_print(ctx, 1, - "Failed to add cert_enroll entry into sqlite database: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); - } - } - - str = db_get_session_val(ctx, NULL, NULL, session_id, - "mobile_identifier_hash"); - if (str) { - sql = sqlite3_mprintf("DELETE FROM sim_provisioning WHERE mobile_identifier_hash=%Q", - str); - if (sql) { - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != - SQLITE_OK) { - debug_print(ctx, 1, - "Failed to delete pending sim_provisioning entry: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); - } - os_free(str); - } - - if (ret == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "completed subscription registration", NULL); - } - -out: - free(user); - free(realm); - free(pw); - free(pw_mm); - free(pps); - free(cert_pem); - free(fingerprint); - free(osu_user); - free(osu_password); - free(eap_method); - os_free(policy); - return ret; -} - - -static xml_node_t * hs20_spp_update_response(struct hs20_svc *ctx, - xml_node_t *node, - const char *user, - const char *realm, - const char *session_id, - int dmacc) -{ - char *status; - xml_node_t *ret; - char *val; - enum hs20_session_operation oper; - - status = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, - "sppStatus"); - if (status == NULL) { - debug_print(ctx, 1, "No sppStatus attribute"); - return NULL; - } - - debug_print(ctx, 1, "sppUpdateResponse: sppStatus: %s sessionID: %s", - status, session_id); - - val = db_get_session_val(ctx, NULL, NULL, session_id, "operation"); - if (!val) { - debug_print(ctx, 1, - "No session active for sessionID: %s", - session_id); - oper = NO_OPERATION; - } else - oper = atoi(val); - - if (strcasecmp(status, "OK") == 0) { - char *new_pw = NULL; - - xml_node_get_attr_value_free(ctx->xml, status); - - if (oper == USER_REMEDIATION) { - new_pw = db_get_session_val(ctx, user, realm, - session_id, "password"); - if (new_pw == NULL || strlen(new_pw) == 0) { - free(new_pw); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, "No password " - "had been assigned for " - "session", ret); - db_remove_session(ctx, user, realm, session_id); - return ret; - } - oper = UPDATE_PASSWORD; - } - if (oper == UPDATE_PASSWORD) { - if (!new_pw) { - new_pw = db_get_session_val(ctx, user, realm, - session_id, - "password"); - if (!new_pw) { - db_remove_session(ctx, user, realm, - session_id); - return NULL; - } - } - debug_print(ctx, 1, "Update user '%s' password in DB", - user); - if (update_password(ctx, user, realm, new_pw, dmacc) < - 0) { - debug_print(ctx, 1, "Failed to update user " - "'%s' password in DB", user); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, "Failed to " - "update database", ret); - db_remove_session(ctx, user, realm, session_id); - return ret; - } - hs20_eventlog(ctx, user, realm, - session_id, "Updated user password " - "in database", NULL); - } - if (oper == CLEAR_REMEDIATION) { - debug_print(ctx, 1, - "Clear remediation requirement for user '%s' in DB", - user); - if (clear_remediation(ctx, user, realm, dmacc) < 0) { - debug_print(ctx, 1, - "Failed to clear remediation requirement for user '%s' in DB", - user); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, - "Failed to update database", - ret); - db_remove_session(ctx, user, realm, session_id); - return ret; - } - hs20_eventlog(ctx, user, realm, - session_id, - "Cleared remediation requirement in database", - NULL); - } - if (oper == SUBSCRIPTION_REGISTRATION) { - if (add_subscription(ctx, session_id) < 0) { - debug_print(ctx, 1, "Failed to add " - "subscription into DB"); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, "Failed to " - "update database", ret); - db_remove_session(ctx, user, realm, session_id); - return ret; - } - } - if (oper == POLICY_REMEDIATION || oper == POLICY_UPDATE) { - char *val; - val = db_get_val(ctx, user, realm, "remediation", - dmacc); - if (val && strcmp(val, "policy") == 0) - db_update_val(ctx, user, realm, "remediation", - "", dmacc); - free(val); - } - if (oper == POLICY_UPDATE) - db_update_val(ctx, user, realm, "polupd_done", "1", - dmacc); - if (oper == CERT_REENROLL) { - char *new_user; - char event[200]; - - new_user = db_get_session_val(ctx, NULL, NULL, - session_id, "user"); - if (!new_user) { - debug_print(ctx, 1, - "Failed to find new user name (cert-serialnum)"); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, - "Failed to find new user name (cert reenroll)", - ret); - db_remove_session(ctx, NULL, NULL, session_id); - return ret; - } - - debug_print(ctx, 1, - "Update certificate user entry to use the new serial number (old=%s new=%s)", - user, new_user); - os_snprintf(event, sizeof(event), "renamed user to: %s", - new_user); - hs20_eventlog(ctx, user, realm, session_id, event, - NULL); - - if (db_update_val(ctx, user, realm, "identity", - new_user, 0) < 0 || - db_update_val(ctx, new_user, realm, "remediation", - "", 0) < 0) { - debug_print(ctx, 1, - "Failed to update user name (cert-serialnum)"); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, - "Failed to update user name (cert reenroll)", - ret); - db_remove_session(ctx, NULL, NULL, session_id); - os_free(new_user); - return ret; - } - - os_free(new_user); - } - ret = build_spp_exchange_complete( - ctx, session_id, - "Exchange complete, release TLS connection", NULL); - hs20_eventlog_node(ctx, user, realm, session_id, - "Exchange completed", ret); - db_remove_session(ctx, NULL, NULL, session_id); - return ret; - } - - ret = build_spp_exchange_complete(ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, session_id, "Error occurred", ret); - db_remove_session(ctx, user, realm, session_id); - xml_node_get_attr_value_free(ctx->xml, status); - return ret; -} - - -#define SPP_SESSION_ID_LEN 16 - -static char * gen_spp_session_id(void) -{ - FILE *f; - int i; - char *session; - - session = os_malloc(SPP_SESSION_ID_LEN * 2 + 1); - if (session == NULL) - return NULL; - - f = fopen("/dev/urandom", "r"); - if (f == NULL) { - os_free(session); - return NULL; - } - for (i = 0; i < SPP_SESSION_ID_LEN; i++) - os_snprintf(session + i * 2, 3, "%02x", fgetc(f)); - - fclose(f); - return session; -} - -xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node, - const char *auth_user, - const char *auth_realm, int dmacc) -{ - xml_node_t *ret = NULL; - char *session_id; - const char *op_name; - char *xml_err; - char fname[200]; - - debug_dump_node(ctx, "received request", node); - - if (!dmacc && auth_user && auth_realm) { - char *real; - real = db_get_val(ctx, auth_user, auth_realm, "identity", 0); - if (!real) { - real = db_get_val(ctx, auth_user, auth_realm, - "identity", 1); - if (real) - dmacc = 1; - } - os_free(real); - } - - snprintf(fname, sizeof(fname), "%s/spp/spp.xsd", ctx->root_dir); - if (xml_validate(ctx->xml, node, fname, &xml_err) < 0) { - /* - * We may not be able to extract the sessionID from invalid - * input, but well, we can try. - */ - session_id = xml_node_get_attr_value_ns(ctx->xml, node, - SPP_NS_URI, - "sessionID"); - 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, - "Validation errors", xml_err); - os_free(xml_err); - xml_node_get_attr_value_free(ctx->xml, session_id); - /* TODO: what to return here? */ - ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, - "SppValidationError"); - return ret; - } - - session_id = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, - "sessionID"); - if (session_id) { - char *tmp; - debug_print(ctx, 1, "Received sessionID %s", session_id); - tmp = os_strdup(session_id); - xml_node_get_attr_value_free(ctx->xml, session_id); - if (tmp == NULL) - return NULL; - session_id = tmp; - } else { - session_id = gen_spp_session_id(); - if (session_id == NULL) { - debug_print(ctx, 1, "Failed to generate sessionID"); - return NULL; - } - debug_print(ctx, 1, "Generated sessionID %s", session_id); - } - - op_name = xml_node_get_localname(ctx->xml, node); - if (op_name == NULL) { - debug_print(ctx, 1, "Could not get op_name"); - return NULL; - } - - if (strcmp(op_name, "sppPostDevData") == 0) { - hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, - "sppPostDevData received and validated", - node); - ret = hs20_spp_post_dev_data(ctx, node, auth_user, auth_realm, - session_id, dmacc); - } else if (strcmp(op_name, "sppUpdateResponse") == 0) { - hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, - "sppUpdateResponse received and validated", - node); - ret = hs20_spp_update_response(ctx, node, auth_user, - auth_realm, session_id, dmacc); - } else { - hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, - "Unsupported SPP message received and " - "validated", node); - debug_print(ctx, 1, "Unsupported operation '%s'", op_name); - /* TODO: what to return here? */ - ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, - "SppUnknownCommandError"); - } - os_free(session_id); - - if (ret == NULL) { - /* TODO: what to return here? */ - ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, - "SppInternalError"); - } - - return ret; -} - - -int hs20_spp_server_init(struct hs20_svc *ctx) -{ - char fname[200]; - ctx->db = NULL; - snprintf(fname, sizeof(fname), "%s/AS/DB/eap_user.db", ctx->root_dir); - if (sqlite3_open(fname, &ctx->db)) { - printf("Failed to open sqlite database: %s\n", - sqlite3_errmsg(ctx->db)); - sqlite3_close(ctx->db); - return -1; - } - - return 0; -} - - -void hs20_spp_server_deinit(struct hs20_svc *ctx) -{ - sqlite3_close(ctx->db); - ctx->db = NULL; -} diff --git a/contrib/wpa/hs20/server/spp_server.h b/contrib/wpa/hs20/server/spp_server.h deleted file mode 100644 index 421974c607b8..000000000000 --- a/contrib/wpa/hs20/server/spp_server.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hotspot 2.0 SPP server - * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef SPP_SERVER_H -#define SPP_SERVER_H - -struct hs20_svc { - const void *ctx; - struct xml_node_ctx *xml; - char *root_dir; - FILE *debug_log; - sqlite3 *db; - const char *addr; - const char *test; - const char *imsi; - const char *eap_method; - const char *id_hash; -}; - - -void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...) - __attribute__ ((format (printf, 3, 4))); -void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node); - -xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node, - const char *auth_user, - const char *auth_realm, int dmacc); -int hs20_spp_server_init(struct hs20_svc *ctx); -void hs20_spp_server_deinit(struct hs20_svc *ctx); - -#endif /* SPP_SERVER_H */ diff --git a/contrib/wpa/hs20/server/sql-example.txt b/contrib/wpa/hs20/server/sql-example.txt deleted file mode 100644 index 20dcf2f5c688..000000000000 --- a/contrib/wpa/hs20/server/sql-example.txt +++ /dev/null @@ -1,17 +0,0 @@ -INSERT INTO osu_config(realm,field,value) VALUES('example.com','fqdn','example.com'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','friendly_name','Example Operator'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','spp_http_auth_url','https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','trust_root_cert_url','https://osu-server.osu.example.com/hs20/files/spp-root-ca.der'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','trust_root_cert_fingerprint','5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','aaa_trust_root_cert_url','https://osu-server.osu.example.com/hs20/files/aaa-root-ca.der'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','aaa_trust_root_cert_fingerprint','5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','free_account','free'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','policy_url','https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','remediation_url','https://subscription-server.osu.example.com/hs20/remediation.php?session_id='); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','free_remediation_url','https://subscription-server.osu.example.com/hs20/free-remediation.php?session_id='); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','signup_url','https://subscription-server.osu.example.com/hs20/signup.php?session_id='); - - -INSERT INTO users(identity,realm,methods,password,phase2,shared) VALUES('free','example.com','TTLS-MSCHAPV2','free',1,1); - -INSERT INTO wildcards(identity,methods) VALUES('','TTLS,TLS'); diff --git a/contrib/wpa/hs20/server/sql.txt b/contrib/wpa/hs20/server/sql.txt deleted file mode 100644 index 2cc6edea4063..000000000000 --- a/contrib/wpa/hs20/server/sql.txt +++ /dev/null @@ -1,108 +0,0 @@ -CREATE TABLE eventlog( - user TEXT, - realm TEXT, - sessionid TEXT COLLATE NOCASE, - timestamp TEXT, - notes TEXT, - dump TEXT, - addr TEXT -); - -CREATE TABLE sessions( - timestamp TEXT, - id TEXT COLLATE NOCASE, - user TEXT, - realm TEXT, - password TEXT, - machine_managed BOOLEAN, - operation INTEGER, - type TEXT, - pps TEXT, - redirect_uri TEXT, - devinfo TEXT, - devdetail TEXT, - cert TEXT, - cert_pem TEXT, - mac_addr TEXT, - osu_user TEXT, - osu_password TEXT, - eap_method TEXT, - mobile_identifier_hash TEXT, - test TEXT -); - -CREATE index sessions_id_index ON sessions(id); - -CREATE TABLE osu_config( - realm TEXT, - field TEXT, - value TEXT -); - -CREATE TABLE users( - identity TEXT PRIMARY KEY, - methods TEXT, - password TEXT, - machine_managed BOOLEAN, - remediation TEXT, - phase2 INTEGER, - realm TEXT, - policy TEXT, - devinfo TEXT, - devdetail TEXT, - pps TEXT, - fetch_pps INTEGER, - osu_user TEXT, - osu_password TEXT, - shared INTEGER, - cert TEXT, - cert_pem TEXT, - t_c_timestamp INTEGER, - mac_addr TEXT, - last_msk TEXT, - polupd_done TEXT, - subrem TEXT -); - -CREATE TABLE wildcards( - identity TEXT PRIMARY KEY, - methods TEXT -); - -CREATE TABLE authlog( - timestamp TEXT, - session TEXT, - nas_ip TEXT, - username TEXT, - note TEXT -); - -CREATE TABLE pending_tc( - mac_addr TEXT PRIMARY KEY, - identity TEXT -); - -CREATE TABLE current_sessions( - mac_addr TEXT PRIMARY KEY, - identity TEXT, - start_time TEXT, - nas TEXT, - hs20_t_c_filtering BOOLEAN, - waiting_coa_ack BOOLEAN, - coa_ack_received BOOLEAN -); - -CREATE TABLE cert_enroll( - mac_addr TEXT PRIMARY KEY, - user TEXT, - realm TEXT, - serialnum TEXT -); - -CREATE TABLE sim_provisioning( - mobile_identifier_hash TEXT PRIMARY KEY, - imsi TEXT, - mac_addr TEXT, - eap_method TEXT, - timestamp TEXT -); diff --git a/contrib/wpa/hs20/server/www/add-free.php b/contrib/wpa/hs20/server/www/add-free.php deleted file mode 100644 index 1efc65563274..000000000000 --- a/contrib/wpa/hs20/server/www/add-free.php +++ /dev/null @@ -1,50 +0,0 @@ -query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} - -$uri = $row['redirect_uri']; -$rowid = $row['rowid']; -$realm = $row['realm']; - -$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch(); -if (!$row || strlen($row['value']) == 0) { - die("Free account disabled"); -} - -$user = $row['value']; - -$row = $db->query("SELECT password FROM users WHERE identity='$user' AND realm='$realm'")->fetch(); -if (!$row) - die("Free account not found"); - -$pw = $row['password']; - -if (!$db->exec("UPDATE sessions SET user='$user', password='$pw', realm='$realm', machine_managed='1' WHERE rowid=$rowid")) { - die("Failed to update session database"); -} - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('$user', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'completed user input response for a new PPS MO')"); - -header("Location: $uri", true, 302); - -?> diff --git a/contrib/wpa/hs20/server/www/add-mo.php b/contrib/wpa/hs20/server/www/add-mo.php deleted file mode 100644 index a3b4513531f8..000000000000 --- a/contrib/wpa/hs20/server/www/add-mo.php +++ /dev/null @@ -1,56 +0,0 @@ -

Invalid username

\n"; - echo "Try again\n"; - echo "\n"; - exit; -} - -$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} -$realm = $row['realm']; - -$userrow = $db->query("SELECT identity FROM users WHERE identity='$user' AND realm='$realm'")->fetch(); -if ($userrow) { - echo "

Selected username is not available

\n"; - echo "Try again\n"; - echo "\n"; - exit; -} - -$uri = $row['redirect_uri']; -$rowid = $row['rowid']; - -if (!$db->exec("UPDATE sessions SET user='$user', password='$pw', realm='$realm', type='password' WHERE rowid=$rowid")) { - die("Failed to update session database"); -} - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('$user', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'completed user input response for a new PPS MO')"); - -header("Location: $uri", true, 302); - -?> diff --git a/contrib/wpa/hs20/server/www/cert-enroll.php b/contrib/wpa/hs20/server/www/cert-enroll.php deleted file mode 100644 index f023ca5a5b03..000000000000 --- a/contrib/wpa/hs20/server/www/cert-enroll.php +++ /dev/null @@ -1,39 +0,0 @@ -query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} - -$uri = $row['redirect_uri']; -$rowid = $row['rowid']; -$realm = $row['realm']; - -$user = sha1(mt_rand()); - -if (!$db->exec("UPDATE sessions SET user='$user', type='cert' WHERE rowid=$rowid")) { - die("Failed to update session database"); -} - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'completed user input response for client certificate enrollment')"); - -header("Location: $uri", true, 302); - -?> diff --git a/contrib/wpa/hs20/server/www/config.php b/contrib/wpa/hs20/server/www/config.php deleted file mode 100644 index 4272b102a88c..000000000000 --- a/contrib/wpa/hs20/server/www/config.php +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/contrib/wpa/hs20/server/www/est.php b/contrib/wpa/hs20/server/www/est.php deleted file mode 100644 index b7fb260d56c4..000000000000 --- a/contrib/wpa/hs20/server/www/est.php +++ /dev/null @@ -1,232 +0,0 @@ -1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, - 'uri'=>1, 'response'=>1); - $data = array(); - $keys = implode('|', array_keys($needed)); - preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', - $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER); - foreach ($matches as $m) { - $data[$m[1]] = $m[3] ? $m[3] : $m[4]; - unset($needed[$m[1]]); - } - if ($needed) { - error_log("EST: Missing auth parameter"); - die('Authentication failed'); - } - $user = $data['username']; - if (strlen($user) < 1) { - error_log("EST: Empty username"); - die('Authentication failed'); - } - - $sql = "SELECT rowid,password,operation FROM sessions " . - "WHERE user='$user' AND realm='$realm'"; - $q = $db->query($sql); - if (!$q) { - error_log("EST: Session not found for user=$user realm=$realm"); - die("Session not found"); - } - $row = $q->fetch(); - if (!$row) { - error_log("EST: Session fetch failed for user=$user realm=$realm"); - die('Session not found'); - } - $rowid = $row['rowid']; - - $oper = $row['operation']; - if ($oper != '5') { - error_log("EST: Unexpected operation $oper for user=$user realm=$realm"); - die("Session not found"); - } - $pw = $row['password']; - if (strlen($pw) < 1) { - error_log("EST: Empty password for user=$user realm=$realm"); - die('Authentication failed'); - } - - $A1 = md5($user . ':' . $realm . ':' . $pw); - $A2 = md5($method . ':' . $data['uri']); - $resp = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' . - $data['cnonce'] . ':' . $data['qop'] . ':' . $A2); - if ($data['response'] != $resp) { - error_log("EST: Incorrect authentication response for user=$user realm=$realm"); - die('Authentication failed'); - } -} else if (isset($_SERVER["SSL_CLIENT_VERIFY"]) && - $_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" && - isset($_SERVER["SSL_CLIENT_M_SERIAL"])) { - $user = "cert-" . $_SERVER["SSL_CLIENT_M_SERIAL"]; - $sql = "SELECT rowid,password,operation FROM sessions " . - "WHERE user='$user' AND realm='$realm'"; - $q = $db->query($sql); - if (!$q) { - error_log("EST: Session not found for user=$user realm=$realm"); - die("Session not found"); - } - $row = $q->fetch(); - if (!$row) { - error_log("EST: Session fetch failed for user=$user realm=$realm"); - die('Session not found'); - } - $rowid = $row['rowid']; - - $oper = $row['operation']; - if ($oper != '10') { - error_log("EST: Unexpected operation $oper for user=$user realm=$realm"); - die("Session not found"); - } -} - - -if ($method == "GET" && $cmd == "cacerts") { - $fname = "$osu_root/est/$realm-cacerts.pkcs7"; - if (!file_exists($fname)) { - error_log("EST: cacerts - unknown realm $realm"); - die("Unknown realm"); - } - - header("Content-Transfer-Encoding: base64"); - header("Content-Type: application/pkcs7-mime"); - - $data = file_get_contents($fname); - echo wordwrap(base64_encode($data), 72, "\n", true); - echo "\n"; - error_log("EST: cacerts"); -} else if ($method == "GET" && $cmd == "csrattrs") { - header("Content-Transfer-Encoding: base64"); - header("Content-Type: application/csrattrs"); - readfile("$osu_root/est/est-attrs.b64"); - error_log("EST: csrattrs"); -} else if ($method == "POST" && - ($cmd == "simpleenroll" || $cmd == "simplereenroll")) { - $reenroll = $cmd == "simplereenroll"; - if (!$reenroll && (!isset($user) || strlen($user) == 0)) { - header('HTTP/1.1 401 Unauthorized'); - header('WWW-Authenticate: Digest realm="'.$realm. - '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); - error_log("EST: simpleenroll - require authentication"); - die('Authentication required'); - } - if ($reenroll && - (!isset($user) || - !isset($_SERVER["SSL_CLIENT_VERIFY"]) || - $_SERVER["SSL_CLIENT_VERIFY"] != "SUCCESS")) { - header('HTTP/1.1 403 Forbidden'); - error_log("EST: simplereenroll - require certificate authentication"); - die('Authentication required'); - } - if (!isset($_SERVER["CONTENT_TYPE"])) { - error_log("EST: simpleenroll without Content-Type"); - die("Missing Content-Type"); - } - if (!stristr($_SERVER["CONTENT_TYPE"], "application/pkcs10")) { - error_log("EST: simpleenroll - unexpected Content-Type: " . - $_SERVER["CONTENT_TYPE"]); - die("Unexpected Content-Type"); - } - - $data = file_get_contents("php://input"); - error_log("EST: simpleenroll - POST data from php://input: " . $data); - $req = base64_decode($data); - if ($req == FALSE) { - error_log("EST: simpleenroll - Invalid base64-encoded PKCS#10 data"); - die("Invalid base64-encoded PKCS#10 data"); - } - $cadir = "$osu_root/est"; - $reqfile = "$cadir/tmp/cert-req.pkcs10"; - $f = fopen($reqfile, "wb"); - fwrite($f, $req); - fclose($f); - - $req_pem = "$reqfile.pem"; - if (file_exists($req_pem)) - unlink($req_pem); - exec("openssl req -in $reqfile -inform DER -out $req_pem -outform PEM"); - if (!file_exists($req_pem)) { - error_log("EST: simpleenroll - Failed to parse certificate request"); - die("Failed to parse certificate request"); - } - - /* FIX: validate request and add HS 2.0 extensions to cert */ - $cert_pem = "$cadir/tmp/req-signed.pem"; - if (file_exists($cert_pem)) - unlink($cert_pem); - exec("openssl x509 -req -in $req_pem -CAkey $cadir/cakey.pem -out $cert_pem -CA $cadir/cacert.pem -CAserial $cadir/serial -days 365 -text"); - if (!file_exists($cert_pem)) { - error_log("EST: simpleenroll - Failed to sign certificate"); - die("Failed to sign certificate"); - } - - $cert = file_get_contents($cert_pem); - $handle = popen("openssl x509 -in $cert_pem -serial -noout", "r"); - $serial = fread($handle, 200); - pclose($handle); - $pattern = "/serial=(?P[0-9a-fA-F:]*)/m"; - preg_match($pattern, $serial, $matches); - if (!isset($matches['snhex']) || strlen($matches['snhex']) < 1) { - error_log("EST: simpleenroll - Could not get serial number"); - die("Could not get serial number"); - } - $sn = str_replace(":", "", strtoupper($matches['snhex'])); - - $user = "cert-$sn"; - error_log("EST: user = $user"); - - $cert_der = "$cadir/tmp/req-signed.der"; - if (file_exists($cert_der)) - unlink($cert_der); - exec("openssl x509 -in $cert_pem -inform PEM -out $cert_der -outform DER"); - if (!file_exists($cert_der)) { - error_log("EST: simpleenroll - Failed to convert certificate"); - die("Failed to convert certificate"); - } - $der = file_get_contents($cert_der); - $fingerprint = hash("sha256", $der); - error_log("EST: sha256(DER cert): $fingerprint"); - - $pkcs7 = "$cadir/tmp/est-client.pkcs7"; - if (file_exists($pkcs7)) - unlink($pkcs7); - exec("openssl crl2pkcs7 -nocrl -certfile $cert_pem -out $pkcs7 -outform DER"); - if (!file_exists($pkcs7)) { - error_log("EST: simpleenroll - Failed to prepare PKCS#7 file"); - die("Failed to prepare PKCS#7 file"); - } - - if (!$db->exec("UPDATE sessions SET user='$user', cert='$fingerprint', cert_pem='$cert' WHERE rowid=$rowid")) { - error_log("EST: simpleenroll - Failed to update session database"); - die("Failed to update session database"); - } - - header("Content-Transfer-Encoding: base64"); - header("Content-Type: application/pkcs7-mime"); - - $data = file_get_contents($pkcs7); - $resp = wordwrap(base64_encode($data), 72, "\n", true); - echo $resp . "\n"; - error_log("EST: simpleenroll - PKCS#7 response: " . $resp); -} else { - header("HTTP/1.0 404 Not Found"); - error_log("EST: Unexpected method or path"); - die("Unexpected method or path"); -} - -?> diff --git a/contrib/wpa/hs20/server/www/free-remediation.php b/contrib/wpa/hs20/server/www/free-remediation.php deleted file mode 100644 index 5648b30e8d6b..000000000000 --- a/contrib/wpa/hs20/server/www/free-remediation.php +++ /dev/null @@ -1,19 +0,0 @@ - - -Hotspot 2.0 - public and free hotspot - remediation - - - -

Hotspot 2.0 - public and free hotspot

- -

Terms and conditions have changed. You need to accept the new terms -to continue using this network.

- -

Terms and conditions..

- -Accept
\n"; -?> - - - diff --git a/contrib/wpa/hs20/server/www/free.php b/contrib/wpa/hs20/server/www/free.php deleted file mode 100644 index 8195069ed8ff..000000000000 --- a/contrib/wpa/hs20/server/www/free.php +++ /dev/null @@ -1,23 +0,0 @@ - - -Hotspot 2.0 - public and free hotspot - - - -Hotspot 2.0 - public and free hotspot\n"; - -echo "
\n"; -echo "\n"; - -?> - -

Terms and conditions..

- -
- - - diff --git a/contrib/wpa/hs20/server/www/redirect.php b/contrib/wpa/hs20/server/www/redirect.php deleted file mode 100644 index 8fc9cd644273..000000000000 --- a/contrib/wpa/hs20/server/www/redirect.php +++ /dev/null @@ -1,32 +0,0 @@ -query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} - -$uri = $row['redirect_uri']; - -header("Location: $uri", true, 302); - -$user = $row['user']; -$realm = $row['realm']; - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('$user', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'redirected after user input')"); - -?> diff --git a/contrib/wpa/hs20/server/www/remediation-pw.php b/contrib/wpa/hs20/server/www/remediation-pw.php deleted file mode 100644 index 76fdccbdf9f7..000000000000 --- a/contrib/wpa/hs20/server/www/remediation-pw.php +++ /dev/null @@ -1,41 +0,0 @@ -query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} -$user = $row['user']; -$realm = $row['realm']; - -$uri = $row['redirect_uri']; -$rowid = $row['rowid']; - -if (!$db->exec("UPDATE sessions SET password='$pw' WHERE rowid=$rowid")) { - die("Failed to update session database"); -} - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('$user', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'completed user input response for subscription remediation')"); - -header("Location: $uri", true, 302); - -?> diff --git a/contrib/wpa/hs20/server/www/remediation.php b/contrib/wpa/hs20/server/www/remediation.php deleted file mode 100644 index 3628065ac225..000000000000 --- a/contrib/wpa/hs20/server/www/remediation.php +++ /dev/null @@ -1,55 +0,0 @@ - - -Hotspot 2.0 subscription remediation - - - -\n"; - -$row = $db->query("SELECT * FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} - -$username = $row['user']; -echo "User: " . $username . "@" . $row['realm'] . "
\n"; - -$user = $db->query("SELECT machine_managed,methods FROM users WHERE identity='$username'")->fetch(); -if ($user == false) { - die("User not found"); -} - -echo "

\n"; - -$cert = $user['methods'] == "TLS" || strncmp($username, "cert-", 5) == 0; - -if ($cert) { - echo "Complete user subscription remediation
\n"; -} else if ($user['machine_managed'] == "1") { - echo "Complete user subscription remediation
\n"; - echo "This will provide a new machine-generated password.
\n"; -} else { - echo "
\n"; - echo "\n"; - echo "New password:
\n"; - echo "\n"; - echo "
\n"; -} - -?> - - - diff --git a/contrib/wpa/hs20/server/www/signup.php b/contrib/wpa/hs20/server/www/signup.php deleted file mode 100644 index 80a9d403e8fc..000000000000 --- a/contrib/wpa/hs20/server/www/signup.php +++ /dev/null @@ -1,59 +0,0 @@ - - -Hotspot 2.0 signup - - - -query("SELECT realm,test FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found for id: $id"); -} -$realm = $row['realm']; -$test = $row['test']; - -if (strlen($test) > 0) { - echo "

Special test functionality: $test

\n"; -} - -echo "

Sign up for a subscription - $realm

\n"; - -echo "

This page can be used to select between three different types of subscriptions for testing purposes.

\n"; - -echo "

Option 1 - shared free access credential

\n"; - -$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch(); -if ($row && strlen($row['value']) > 0) { - echo "

Sign up for free access

\n"; -} - -echo "

Option 2 - username/password credential

\n"; - -echo "
\n"; -echo "\n"; -?> -Select a username and password. Leave password empty to get automatically -generated and machine managed password.
-Username:
-Password:
- -
- -Option 3 - client certificate credential\n"; - -echo "

Enroll a client certificate

\n" -?> - - - diff --git a/contrib/wpa/hs20/server/www/spp.php b/contrib/wpa/hs20/server/www/spp.php deleted file mode 100644 index c56d3d69e0ed..000000000000 --- a/contrib/wpa/hs20/server/www/spp.php +++ /dev/null @@ -1,168 +0,0 @@ -1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, - 'uri'=>1, 'response'=>1); - $data = array(); - $keys = implode('|', array_keys($needed)); - preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', - $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER); - foreach ($matches as $m) { - $data[$m[1]] = $m[3] ? $m[3] : $m[4]; - unset($needed[$m[1]]); - } - if ($needed) { - error_log("spp.php - Authentication failed - missing: " . print_r($needed)); - die('Authentication failed'); - } - $user = $data['username']; - if (strlen($user) < 1) { - error_log("spp.php - Authentication failed - empty username"); - die('Authentication failed'); - } - - - $db = new PDO($osu_db); - if (!$db) { - error_log("spp.php - Could not access database"); - die("Could not access database"); - } - $row = $db->query("SELECT password FROM users " . - "WHERE identity='$user' AND realm='$realm'")->fetch(); - if (!$row) { - $row = $db->query("SELECT osu_password FROM users " . - "WHERE osu_user='$user' AND realm='$realm'")->fetch(); - $pw = $row['osu_password']; - } else - $pw = $row['password']; - if (!$row) { - error_log("spp.php - Authentication failed - user '$user' not found"); - die('Authentication failed'); - } - if (strlen($pw) < 1) { - error_log("spp.php - Authentication failed - empty password"); - die('Authentication failed'); - } - - $A1 = md5($user . ':' . $realm . ':' . $pw); - $A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $data['uri']); - $resp = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' . - $data['cnonce'] . ':' . $data['qop'] . ':' . $A2); - if ($data['response'] != $resp) { - error_log("Authentication failure - response mismatch"); - die('Authentication failed'); - } -} else if (isset($_SERVER["SSL_CLIENT_VERIFY"]) && - $_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" && - isset($_SERVER["SSL_CLIENT_M_SERIAL"])) { - $user = "cert-" . $_SERVER["SSL_CLIENT_M_SERIAL"]; - putenv("HS20CERT=yes"); -} else if (isset($_GET["hotspot2dot0-mobile-identifier-hash"])) { - $id_hash = $_GET["hotspot2dot0-mobile-identifier-hash"]; - $id_hash = PREG_REPLACE("/[^0-9a-h]/i", '', $id_hash); - - $db = new PDO($osu_db); - if (!$db) { - error_log("spp.php - Could not access database"); - die("Could not access database"); - } - - $row = $db->query("SELECT * FROM sim_provisioning " . - "WHERE mobile_identifier_hash='$id_hash'")->fetch(); - if (!$row) { - error_log("spp.php - SIM provisioning failed - mobile_identifier_hash not found"); - die('SIM provisioning failed - mobile_identifier_hash not found'); - } - - $imsi = $row['imsi']; - $mac_addr = $row['mac_addr']; - $eap_method = $row['eap_method']; - - $row = $db->query("SELECT COUNT(*) FROM osu_config " . - "WHERE realm='$realm'")->fetch(); - if (!$row || intval($row[0]) < 1) { - error_log("spp.php - SIM provisioning failed - realm $realm not found"); - die('SIM provisioning failed'); - } - - error_log("spp.php - SIM provisioning for IMSI $imsi"); - putenv("HS20SIMPROV=yes"); - putenv("HS20IMSI=$imsi"); - putenv("HS20MACADDR=$mac_addr"); - putenv("HS20EAPMETHOD=$eap_method"); - putenv("HS20IDHASH=$id_hash"); -} else if (!isset($_SERVER["PATH_INFO"]) || - $_SERVER["PATH_INFO"] != "/signup") { - header('HTTP/1.1 401 Unauthorized'); - header('WWW-Authenticate: Digest realm="'.$realm. - '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); - error_log("spp.php - Authentication required (not signup)"); - die('Authentication required (not signup)'); -} - - -if (isset($user) && strlen($user) > 0) - putenv("HS20USER=$user"); -else - putenv("HS20USER"); - -putenv("HS20REALM=$realm"); -$postdata = file_get_contents("php://input"); -putenv("HS20POST=$postdata"); -$addr = $_SERVER["REMOTE_ADDR"]; -putenv("HS20ADDR=$addr"); -putenv("HS20TEST=$test"); - -$last = exec("$osu_root/spp/hs20_spp_server -r$osu_root -f/tmp/hs20_spp_server.log", $output, $ret); - -if ($ret == 2) { - if (empty($_SERVER['PHP_AUTH_DIGEST'])) { - header('HTTP/1.1 401 Unauthorized'); - header('WWW-Authenticate: Digest realm="'.$realm. - '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); - error_log("spp.php - Authentication required (ret 2)"); - die('Authentication required'); - } else { - error_log("spp.php - Unexpected authentication error"); - die("Unexpected authentication error"); - } -} -if ($ret != 0) { - error_log("spp.php - Failed to process SPP request"); - die("Failed to process SPP request"); -} -//error_log("spp.php: Response: " . implode($output)); - -header("Content-Type: application/soap+xml"); - -echo implode($output); - -?> diff --git a/contrib/wpa/hs20/server/www/terms.php b/contrib/wpa/hs20/server/www/terms.php deleted file mode 100644 index acba23ef1ad7..000000000000 --- a/contrib/wpa/hs20/server/www/terms.php +++ /dev/null @@ -1,87 +0,0 @@ -\n"; - echo "HS 2.0 Terms and Conditions\n"; - echo "\n"; -} - -$db = new PDO($osu_db); -if (!$db) { - die($sqliteerror); -} - -if (!isset($_GET["addr"])) { - die("Missing addr parameter"); -} -$addr = $_GET["addr"]; - -$accept = isset($_GET["accept"]) && $_GET["accept"] == "yes"; - -$res = $db->prepare("SELECT identity FROM pending_tc WHERE mac_addr=?"); -$res->execute(array($addr)); -$row = $res->fetch(); -if (!$row) { - die("No pending session for the specified MAC address"); -} -$identity = $row[0]; - -if (!$accept) { - print_header(); - - echo "

Accept the following terms and conditions by clicking here: Accept

\n
\n"; - readfile($t_c_file); -} else { - $res = $db->prepare("UPDATE users SET t_c_timestamp=? WHERE identity=?"); - if (!$res->execute(array($t_c_timestamp, $identity))) { - die("Failed to update user account."); - } - - $res = $db->prepare("DELETE FROM pending_tc WHERE mac_addr=?"); - $res->execute(array($addr)); - - $fp = fsockopen($hostapd_ctrl); - if (!$fp) { - die("Could not connect to hostapd(AS)"); - } - - fwrite($fp, "DAC_REQUEST coa $addr t_c_clear"); - fclose($fp); - - $waiting = true; - $ack = false; - for ($i = 1; $i <= 10; $i++) { - $res = $db->prepare("SELECT waiting_coa_ack,coa_ack_received FROM current_sessions WHERE mac_addr=?"); - $res->execute(array($addr)); - $row = $res->fetch(); - if (!$row) { - die("No current session for the specified MAC address"); - } - if (strlen($row[0]) > 0) - $waiting = $row[0] == 1; - if (strlen($row[1]) > 0) - $ack = $row[1] == 1; - $res->closeCursor(); - if (!$waiting) - break; - sleep(1); - } - if ($ack) { - header('X-WFA-Hotspot20-Filtering: removed'); - print_header(); - echo "

Terms and conditions were accepted.

\n"; - - echo "

Filtering disabled.

\n"; - } else { - print_header(); - echo "

Failed to disable filtering.

\n"; - } -} - -?> - - - diff --git a/contrib/wpa/hs20/server/www/users.php b/contrib/wpa/hs20/server/www/users.php deleted file mode 100644 index 2bd555275dda..000000000000 --- a/contrib/wpa/hs20/server/www/users.php +++ /dev/null @@ -1,377 +0,0 @@ - 0) { - $row = $db->query("SELECT dump FROM eventlog WHERE rowid=$id")->fetch(); - $dump = $row['dump']; - if ($dump[0] == '<') { - header("Content-type: text/xml"); - echo "\n"; - echo $dump; - } else { - header("Content-type: text/plain"); - echo $dump; - } - exit; -} - -if ($cmd == 'mo' && $id > 0) { - $mo = $_GET["mo"]; - if (!isset($mo)) - exit; - if ($mo != "devinfo" && $mo != "devdetail" && $mo != "pps") - exit; - $row = $db->query("SELECT $mo FROM users WHERE rowid=$id")->fetch(); - header("Content-type: text/xml"); - echo "\n"; - echo $row[$mo]; - exit; -} - -if ($cmd == 'cert' && $id > 0) { - $row = $db->query("SELECT cert_pem FROM users WHERE rowid=$id")->fetch(); - header("Content-type: text/plain"); - echo $row['cert_pem']; - exit; -} - -?> - - -HS 2.0 users - - - 0) { - $db->exec("UPDATE users SET remediation='' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-user' && $id > 0) { - $db->exec("UPDATE users SET remediation='user' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-machine' && $id > 0) { - $db->exec("UPDATE users SET remediation='machine' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-reenroll' && $id > 0) { - $db->exec("UPDATE users SET remediation='reenroll' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-policy' && $id > 0) { - $db->exec("UPDATE users SET remediation='policy' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-free' && $id > 0) { - $db->exec("UPDATE users SET remediation='free' WHERE rowid=$id"); -} -if ($cmd == 'fetch-pps-on' && $id > 0) { - $db->exec("UPDATE users SET fetch_pps=1 WHERE rowid=$id"); -} -if ($cmd == 'fetch-pps-off' && $id > 0) { - $db->exec("UPDATE users SET fetch_pps=0 WHERE rowid=$id"); -} -if ($cmd == 'reset-pw' && $id > 0) { - $db->exec("UPDATE users SET password='ChangeMe' WHERE rowid=$id"); -} -if ($cmd == "policy" && $id > 0 && isset($_GET["policy"])) { - $policy = $_GET["policy"]; - if ($policy == "no-policy" || - is_readable("$osu_root/spp/policy/$policy.xml")) { - $db->exec("UPDATE users SET policy='$policy' WHERE rowid=$id"); - } -} -if ($cmd == "account-type" && $id > 0 && isset($_GET["type"])) { - $type = $_GET["type"]; - if ($type == "shared") - $db->exec("UPDATE users SET shared=1 WHERE rowid=$id"); - if ($type == "default") - $db->exec("UPDATE users SET shared=0 WHERE rowid=$id"); -} - -if ($cmd == "set-osu-cred" && $id > 0) { - $osu_user = $_POST["osu_user"]; - $osu_password = $_POST["osu_password"]; - if (strlen($osu_user) == 0) - $osu_password = ""; - $db->exec("UPDATE users SET osu_user='$osu_user', osu_password='$osu_password' WHERE rowid=$id"); -} - -if ($cmd == 'clear-t-c' && $id > 0) { - $db->exec("UPDATE users SET t_c_timestamp=NULL WHERE rowid=$id"); -} - -$dump = 0; - -if ($id > 0) { - -if (isset($_GET["dump"])) { - $dump = $_GET["dump"]; - if (!is_numeric($dump)) - $dump = 0; -} else - $dump = 0; - -echo "[All users] "; -if ($dump == 0) - echo "[Include debug dump] "; -else - echo "[Without debug dump] "; -echo "
\n"; - -$row = $db->query("SELECT rowid,* FROM users WHERE rowid=$id")->fetch(); - -echo "

" . $row['identity'] . "@" . $row['realm'] . "

\n"; - -echo "MO: "; -if (strlen($row['devinfo']) > 0) { - echo "[DevInfo]\n"; -} -if (strlen($row['devdetail']) > 0) { - echo "[DevDetail]\n"; -} -if (strlen($row['pps']) > 0) { - echo "[PPS]\n"; -} -if (strlen($row['cert_pem']) > 0) { - echo "[Certificate]\n"; -} -echo "
\n"; - -echo "Fetch PPS MO: "; -if ($row['fetch_pps'] == "1") { - echo "On next connection " . - "[" . - "do not fetch]
\n"; -} else { - echo "Do not fetch " . - "[" . - "request fetch]
\n"; -} - -$cert = $row['cert']; -if (strlen($cert) > 0) { - echo "Certificate fingerprint: $cert
\n"; -} - -echo "Remediation: "; -$rem = $row['remediation']; -if ($rem == "") { - echo "Not required"; - echo " [add:user]"; - echo " [add:machine]"; - if ($row['methods'] == 'TLS') { - echo " [add:reenroll]"; - } - echo " [add:policy]"; - echo " [add:free]"; -} else if ($rem == "user") { - echo "User [clear]"; -} else if ($rem == "policy") { - echo "Policy [clear]"; -} else if ($rem == "free") { - echo "Free [clear]"; -} else if ($rem == "reenroll") { - echo "Reenroll [clear]"; -} else { - echo "Machine [clear]"; -} -echo "
\n"; - -if (strncmp($row['identity'], "cert-", 5) != 0) - echo "Machine managed: " . ($row['machine_managed'] == "1" ? "TRUE" : "FALSE") . "
\n"; - -echo "
Policy:
\n"; - -echo "
Account type:
\n"; - -echo "Phase 2 method(s): " . $row['methods'] . "
\n"; - -echo "
\n"; -echo "Reset AAA password
\n"; - -echo "
\n"; -echo "
\n"; -echo "OSU credentials (if username empty, AAA credentials are used):
\n"; -echo "username: \n"; -echo "password: \n"; -echo "\n"; -echo "
\n"; - -if (strlen($row['t_c_timestamp']) > 0) { - echo "
\n"; - echo "Clear Terms and Conditions acceptance
\n"; -} - -echo "
\n"; - -$user = $row['identity']; -$osu_user = $row['osu_user']; -$realm = $row['realm']; -} - -if ($id > 0 || ($id == 0 && $cmd == 'eventlog')) { - - if ($id == 0) { - echo "[All users] "; - echo "
\n"; - } - -echo "\n"; -echo ""; -if ($id == 0) { - echo ""; - if ($id == 0) { - echo "
userrealm"; -} -echo "timeaddresssessionIDnotes"; -if ($dump > 0) - echo "dump"; -echo "\n"; -if (isset($_GET["limit"])) { - $limit = $_GET["limit"]; - if (!is_numeric($limit)) - $limit = 20; -} else - $limit = 20; -if ($id == 0) - $res = $db->query("SELECT rowid,* FROM eventlog ORDER BY timestamp DESC LIMIT $limit"); -else if (strlen($osu_user) > 0) - $res = $db->query("SELECT rowid,* FROM eventlog WHERE (user='$user' OR user='$osu_user') AND realm='$realm' ORDER BY timestamp DESC LIMIT $limit"); -else - $res = $db->query("SELECT rowid,* FROM eventlog WHERE user='$user' AND realm='$realm' ORDER BY timestamp DESC LIMIT $limit"); -foreach ($res as $row) { - echo "
" . $row['user'] . "\n"; - echo "" . $row['realm'] . "\n"; - } - echo "" . $row['timestamp'] . "\n"; - echo "" . $row['addr'] . "\n"; - echo "" . $row['sessionid'] . "\n"; - echo "" . $row['notes'] . "\n"; - $d = $row['dump']; - if (strlen($d) > 0) { - echo "["; - if ($d[0] == '<') - echo "XML"; - else - echo "txt"; - echo "]\n"; - if ($dump > 0) - echo "" . htmlspecialchars($d) . "\n"; - } -} -echo "
\n"; - -} - - -if ($id == 0 && $cmd != 'eventlog') { - -echo "[Eventlog] "; -echo "
\n"; - -echo "\n"; -echo "
UserRealmRemediationPolicyAccount typePhase 2 method(s)DevIdMAC AddressT&C\n"; - -$res = $db->query('SELECT rowid,* FROM users WHERE (phase2=1 OR methods=\'TLS\') ORDER BY identity'); -foreach ($res as $row) { - echo "
" . - $row['identity'] . " "; - echo "" . $row['realm']; - $rem = $row['remediation']; - echo ""; - if ($rem == "") { - echo "-"; - } else if ($rem == "user") { - echo "User"; - } else if ($rem == "policy") { - echo "Policy"; - } else if ($rem == "free") { - echo "Free"; - } else if ($rem == "reenroll") { - echo "Reenroll"; - } else { - echo "Machine"; - } - echo "" . $row['policy']; - if ($row['shared'] > 0) - echo "shared"; - else - echo "default"; - echo "" . $row['methods'] . ""; - echo ""; - $xml = xml_parser_create(); - xml_parse_into_struct($xml, $row['devinfo'], $devinfo); - foreach($devinfo as $k) { - if ($k['tag'] == 'DEVID') { - echo "" . $k['value'] . ""; - break; - } - } - echo "" . $row['mac_addr'] . ""; - echo "" . $row['t_c_timestamp'] . ""; - echo "\n"; -} -echo "
\n"; - -} - -?> - - diff --git a/contrib/wpa/src/common/dragonfly.c b/contrib/wpa/src/common/dragonfly.c index 547be66f1561..1e842716668e 100644 --- a/contrib/wpa/src/common/dragonfly.c +++ b/contrib/wpa/src/common/dragonfly.c @@ -213,3 +213,37 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order, "dragonfly: Unable to get randomness for own scalar"); return -1; } + + +/* res = sqrt(val) */ +int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, + struct crypto_bignum *res) +{ + const struct crypto_bignum *prime; + struct crypto_bignum *tmp, *one; + int ret = 0; + u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; + size_t prime_len; + + /* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */ + + prime = crypto_ec_get_prime(ec); + prime_len = crypto_ec_prime_len(ec); + tmp = crypto_bignum_init(); + one = crypto_bignum_init_uint(1); + + if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), + prime_len) < 0 || + (prime_bin[prime_len - 1] & 0x03) != 3 || + !tmp || !one || + /* tmp = (p+1)/4 */ + crypto_bignum_add(prime, one, tmp) < 0 || + crypto_bignum_rshift(tmp, 2, tmp) < 0 || + /* res = sqrt(val) */ + crypto_bignum_exptmod(val, tmp, prime, res) < 0) + ret = -1; + + crypto_bignum_deinit(tmp, 0); + crypto_bignum_deinit(one, 0); + return ret; +} diff --git a/contrib/wpa/src/common/dragonfly.h b/contrib/wpa/src/common/dragonfly.h index ec3dd593eda4..84d67f575c54 100644 --- a/contrib/wpa/src/common/dragonfly.h +++ b/contrib/wpa/src/common/dragonfly.h @@ -27,5 +27,7 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order, struct crypto_bignum *_rand, struct crypto_bignum *_mask, struct crypto_bignum *scalar); +int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, + struct crypto_bignum *res); #endif /* DRAGONFLY_H */ diff --git a/contrib/wpa/src/common/qca-vendor.h b/contrib/wpa/src/common/qca-vendor.h index d9eab0212e73..b77e29939195 100644 --- a/contrib/wpa/src/common/qca-vendor.h +++ b/contrib/wpa/src/common/qca-vendor.h @@ -1462,6 +1462,11 @@ enum qca_wlan_vendor_attr_p2p_listen_offload { * Used with event to notify the puncture pattern selected in ACS operation. * Encoding for this attribute will follow the convention used in the Disabled * Subchannel Bitmap field of the EHT Operation IE. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED: Flag attribute. + * Used with command to configure ACS operation for EHT mode. + * Disable (flag attribute not present) - EHT disabled and + * Enable (flag attribute present) - EHT enabled. */ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, @@ -1483,6 +1488,7 @@ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16, QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17, QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18, + QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19, /* keep last */ QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST, @@ -1788,36 +1794,53 @@ enum qca_access_policy { }; /** - * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture - * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32) - * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value - * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized - * SOC timer value at TSF capture + * enum qca_vendor_attr_tsf_cmd: Vendor attributes for TSF capture + * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: Required (u32) + * Specify the TSF command. Possible values are defined in + * &enum qca_tsf_cmd. + * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64) + * This attribute contains TSF timer value. This attribute is only available + * in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response. + * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64) + * This attribute contains SOC timer value at TSF capture. This attribute is + * only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response. + * @QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL: Optional (u32) + * This attribute is used to provide TSF sync interval and only applicable when + * TSF command is %QCA_TSF_SYNC_START. If this attribute is not provided, the + * driver will use the default value. Time unit is in milliseconds. */ enum qca_vendor_attr_tsf_cmd { QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TSF_CMD, QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE, QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE, + QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL, QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TSF_MAX = QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1 }; /** - * enum qca_tsf_operation: TSF driver commands + * enum qca_tsf_cmd: TSF driver commands * @QCA_TSF_CAPTURE: Initiate TSF Capture * @QCA_TSF_GET: Get TSF capture value * @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value * @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target * will automatically send TSF report to the host. To query - * QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be + * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be * initiated first. * @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target * will not automatically send TSF report to the host. If - * QCA_TSF_AUTO_REPORT_ENABLE is initiated and - * QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this + * %QCA_TSF_AUTO_REPORT_ENABLE is initiated and + * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this * operation needs to be initiated. + * @QCA_TSF_SYNC_START: Start periodic TSF sync feature. The driver periodically + * fetches TSF and host time mapping from the firmware with interval configured + * through the %QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL attribute. If the + * interval value is not provided the driver will use the default value. The + * userspace can query the TSF and host time mapping via the %QCA_TSF_GET + * command. + * @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature. */ enum qca_tsf_cmd { QCA_TSF_CAPTURE, @@ -1825,6 +1848,8 @@ enum qca_tsf_cmd { QCA_TSF_SYNC_GET, QCA_TSF_AUTO_REPORT_ENABLE, QCA_TSF_AUTO_REPORT_DISABLE, + QCA_TSF_SYNC_START, + QCA_TSF_SYNC_STOP, }; /** diff --git a/contrib/wpa/src/common/sae.c b/contrib/wpa/src/common/sae.c index b768c22faa9d..c0f154e9134d 100644 --- a/contrib/wpa/src/common/sae.c +++ b/contrib/wpa/src/common/sae.c @@ -290,14 +290,16 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, int pwd_seed_odd = 0; u8 prime[SAE_MAX_ECC_PRIME_LEN]; size_t prime_len; - struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL; + struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL; u8 x_bin[SAE_MAX_ECC_PRIME_LEN]; u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN]; u8 qr_bin[SAE_MAX_ECC_PRIME_LEN]; u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN]; + u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN]; int res = -1; u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* * mask */ + unsigned int is_eq; os_memset(x_bin, 0, sizeof(x_bin)); @@ -396,25 +398,42 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, goto fail; } - if (!sae->tmp->pwe_ecc) - sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); - if (!sae->tmp->pwe_ecc) - res = -1; - else - res = crypto_ec_point_solve_y_coord(sae->tmp->ec, - sae->tmp->pwe_ecc, x, - pwd_seed_odd); - if (res < 0) { - /* - * This should not happen since we already checked that there - * is a result. - */ + /* y = sqrt(x^3 + ax + b) mod p + * if LSB(save) == LSB(y): PWE = (x, y) + * else: PWE = (x, p - y) + * + * Calculate y and the two possible values for PWE and after that, + * use constant time selection to copy the correct alternative. + */ + y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x); + if (!y || + dragonfly_sqrt(sae->tmp->ec, y, y) < 0 || + crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN, + prime_len) < 0 || + crypto_bignum_sub(sae->tmp->prime, y, y) < 0 || + crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN, + SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) { wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); + goto fail; + } + + is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01); + const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN, + prime_len, x_y + prime_len); + os_memcpy(x_y, x_bin, prime_len); + wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len); + crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1); + sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y); + if (!sae->tmp->pwe_ecc) { + wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); + res = -1; } fail: + forced_memzero(x_y, sizeof(x_y)); crypto_bignum_deinit(qr, 0); crypto_bignum_deinit(qnr, 0); + crypto_bignum_deinit(y, 1); os_free(stub_password); bin_clear_free(tmp_password, password_len); crypto_bignum_deinit(x, 1); @@ -747,19 +766,9 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group, const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y); wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len); - /* y = sqrt(v) - * For prime p such that p = 3 mod 4 --> v^((p+1)/4) */ - if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0) - goto fail; - if ((bin1[prime_len - 1] & 0x03) != 3) { - wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4"); - goto fail; - } + /* y = sqrt(v) */ y = crypto_bignum_init(); - if (!y || - crypto_bignum_add(prime, one, t1) < 0 || - crypto_bignum_rshift(t1, 2, t1) < 0 || - crypto_bignum_exptmod(v, t1, prime, y) < 0) + if (!y || dragonfly_sqrt(ec, v, y) < 0) goto fail; debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len); diff --git a/contrib/wpa/src/common/version.h b/contrib/wpa/src/common/version.h index 0235c9bf6776..7502f58e0b87 100644 --- a/contrib/wpa/src/common/version.h +++ b/contrib/wpa/src/common/version.h @@ -9,6 +9,6 @@ #define GIT_VERSION_STR_POSTFIX "" #endif /* GIT_VERSION_STR_POSTFIX */ -#define VERSION_STR "2.10-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX +#define VERSION_STR "2.10" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX #endif /* VERSION_H */ diff --git a/contrib/wpa/src/crypto/crypto.h b/contrib/wpa/src/crypto/crypto.h index eb600699d3d0..e6150b0cf16e 100644 --- a/contrib/wpa/src/crypto/crypto.h +++ b/contrib/wpa/src/crypto/crypto.h @@ -882,18 +882,6 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, */ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p); -/** - * crypto_ec_point_solve_y_coord - Solve y coordinate for an x coordinate - * @e: EC context from crypto_ec_init() - * @p: EC point to use for the returning the result - * @x: x coordinate - * @y_bit: y-bit (0 or 1) for selecting the y value to use - * Returns: 0 on success, -1 on failure - */ -int crypto_ec_point_solve_y_coord(struct crypto_ec *e, - struct crypto_ec_point *p, - const struct crypto_bignum *x, int y_bit); - /** * crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b * @e: EC context from crypto_ec_init() diff --git a/contrib/wpa/src/crypto/crypto_openssl.c b/contrib/wpa/src/crypto/crypto_openssl.c index ef669c408474..82c85762d84f 100644 --- a/contrib/wpa/src/crypto/crypto_openssl.c +++ b/contrib/wpa/src/crypto/crypto_openssl.c @@ -24,6 +24,9 @@ #include #include #endif /* CONFIG_ECC */ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif /* OpenSSL version >= 3.0 */ #include "common.h" #include "utils/const_time.h" @@ -117,6 +120,26 @@ static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x) } #endif /* OpenSSL version < 1.1.0 */ + +void openssl_load_legacy_provider(void) +{ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + static bool loaded = false; + OSSL_PROVIDER *legacy; + + if (loaded) + return; + + legacy = OSSL_PROVIDER_load(NULL, "legacy"); + + if (legacy) { + OSSL_PROVIDER_load(NULL, "default"); + loaded = true; + } +#endif /* OpenSSL version >= 3.0 */ +} + + static BIGNUM * get_group5_prime(void) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ @@ -223,6 +246,7 @@ static int openssl_digest_vector(const EVP_MD *type, size_t num_elem, #ifndef CONFIG_FIPS int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { + openssl_load_legacy_provider(); return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac); } #endif /* CONFIG_FIPS */ @@ -234,6 +258,8 @@ int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) int i, plen, ret = -1; EVP_CIPHER_CTX *ctx; + openssl_load_legacy_provider(); + /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { @@ -271,6 +297,8 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip, int res = -1; unsigned char skip_buf[16]; + openssl_load_legacy_provider(); + ctx = EVP_CIPHER_CTX_new(); if (!ctx || !EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) || @@ -1923,48 +1951,27 @@ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) } -int crypto_ec_point_solve_y_coord(struct crypto_ec *e, - struct crypto_ec_point *p, - const struct crypto_bignum *x, int y_bit) -{ - if (TEST_FAIL()) - return -1; - if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p, - (const BIGNUM *) x, y_bit, - e->bnctx) || - !EC_POINT_is_on_curve(e->group, (EC_POINT *) p, e->bnctx)) - return -1; - return 0; -} - - struct crypto_bignum * crypto_ec_point_compute_y_sqr(struct crypto_ec *e, const struct crypto_bignum *x) { - BIGNUM *tmp, *tmp2, *y_sqr = NULL; + BIGNUM *tmp; if (TEST_FAIL()) return NULL; tmp = BN_new(); - tmp2 = BN_new(); - /* y^2 = x^3 + ax + b */ - if (tmp && tmp2 && + /* y^2 = x^3 + ax + b = (x^2 + a)x + b */ + if (tmp && BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) && + BN_mod_add_quick(tmp, e->a, tmp, e->prime) && BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) && - BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) && - BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) && - BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) { - y_sqr = tmp2; - tmp2 = NULL; - } + BN_mod_add_quick(tmp, tmp, e->b, e->prime)) + return (struct crypto_bignum *) tmp; BN_clear_free(tmp); - BN_clear_free(tmp2); - - return (struct crypto_bignum *) y_sqr; + return NULL; } @@ -2480,12 +2487,13 @@ struct crypto_ec_key * crypto_ec_key_gen(int group) goto fail; } - eckey = EVP_PKEY_get0_EC_KEY(key); + eckey = EVP_PKEY_get1_EC_KEY(key); if (!eckey) { key = NULL; goto fail; } EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); + EC_KEY_free(eckey); fail: EC_KEY_free(ec_params); @@ -2595,12 +2603,34 @@ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) unsigned char *der = NULL; int der_len; struct wpabuf *buf; + EC_KEY *eckey; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY *tmp; +#endif /* OpenSSL version >= 3.0 */ + + eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key); + if (!eckey) + return NULL; /* For now, all users expect COMPRESSED form */ - EC_KEY_set_conv_form(EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key), - POINT_CONVERSION_COMPRESSED); + EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + tmp = EVP_PKEY_new(); + if (!tmp) + return NULL; + if (EVP_PKEY_set1_EC_KEY(tmp, eckey) != 1) { + EVP_PKEY_free(tmp); + return NULL; + } + key = (struct crypto_ec_key *) tmp; +#endif /* OpenSSL version >= 3.0 */ der_len = i2d_PUBKEY((EVP_PKEY *) key, &der); + EC_KEY_free(eckey); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY_free(tmp); +#endif /* OpenSSL version >= 3.0 */ if (der_len <= 0) { wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s", ERR_error_string(ERR_get_error(), NULL)); @@ -2623,7 +2653,7 @@ struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key, struct wpabuf *buf; unsigned int key_flags; - eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); + eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key); if (!eckey) return NULL; @@ -2637,6 +2667,7 @@ struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key, EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); der_len = i2d_ECPrivateKey(eckey, &der); + EC_KEY_free(eckey); if (der_len <= 0) return NULL; buf = wpabuf_alloc_copy(der, der_len); @@ -2697,7 +2728,7 @@ struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key, const struct crypto_ec_point * crypto_ec_key_get_public_key(struct crypto_ec_key *key) { - EC_KEY *eckey; + const EC_KEY *eckey; eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); if (!eckey) @@ -2709,7 +2740,7 @@ crypto_ec_key_get_public_key(struct crypto_ec_key *key) const struct crypto_bignum * crypto_ec_key_get_private_key(struct crypto_ec_key *key) { - EC_KEY *eckey; + const EC_KEY *eckey; eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); if (!eckey) diff --git a/contrib/wpa/src/crypto/crypto_wolfssl.c b/contrib/wpa/src/crypto/crypto_wolfssl.c index 6f116eb62f53..00ecf61352a1 100644 --- a/contrib/wpa/src/crypto/crypto_wolfssl.c +++ b/contrib/wpa/src/crypto/crypto_wolfssl.c @@ -1630,30 +1630,6 @@ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) } -int crypto_ec_point_solve_y_coord(struct crypto_ec *e, - struct crypto_ec_point *p, - const struct crypto_bignum *x, int y_bit) -{ - byte buf[1 + 2 * MAX_ECC_BYTES]; - int ret; - int prime_len = crypto_ec_prime_len(e); - - if (TEST_FAIL()) - return -1; - - buf[0] = y_bit ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN; - ret = crypto_bignum_to_bin(x, buf + 1, prime_len, prime_len); - if (ret <= 0) - return -1; - ret = wc_ecc_import_point_der(buf, 1 + 2 * ret, e->key.idx, - (ecc_point *) p); - if (ret != 0) - return -1; - - return 0; -} - - struct crypto_bignum * crypto_ec_point_compute_y_sqr(struct crypto_ec *e, const struct crypto_bignum *x) diff --git a/contrib/wpa/src/crypto/tls_openssl.c b/contrib/wpa/src/crypto/tls_openssl.c index 203b0f781ff5..c9e00b3af855 100644 --- a/contrib/wpa/src/crypto/tls_openssl.c +++ b/contrib/wpa/src/crypto/tls_openssl.c @@ -957,6 +957,10 @@ void * tls_init(const struct tls_config *conf) const char *ciphers; if (tls_openssl_ref_count == 0) { + void openssl_load_legacy_provider(void); + + openssl_load_legacy_provider(); + tls_global = context = tls_context_new(conf); if (context == NULL) return NULL; @@ -3019,13 +3023,23 @@ static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags, #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER) && \ !defined(OPENSSL_IS_BORINGSSL) - if ((flags & (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) && - SSL_get_security_level(ssl) >= 2) { - /* - * Need to drop to security level 1 to allow TLS versions older - * than 1.2 to be used when explicitly enabled in configuration. - */ - SSL_set_security_level(conn->ssl, 1); + { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + int need_level = 0; +#else + int need_level = 1; +#endif + + if ((flags & + (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) && + SSL_get_security_level(ssl) > need_level) { + /* + * Need to drop to security level 1 (or 0 with OpenSSL + * 3.0) to allow TLS versions older than 1.2 to be used + * when explicitly enabled in configuration. + */ + SSL_set_security_level(conn->ssl, need_level); + } } #endif diff --git a/contrib/wpa/src/eap_common/eap_pwd_common.c b/contrib/wpa/src/eap_common/eap_pwd_common.c index 2b2b8efdbd01..ff22b29b087a 100644 --- a/contrib/wpa/src/eap_common/eap_pwd_common.c +++ b/contrib/wpa/src/eap_common/eap_pwd_common.c @@ -127,7 +127,8 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN]; u8 x_bin[MAX_ECC_PRIME_LEN]; u8 prime_bin[MAX_ECC_PRIME_LEN]; - struct crypto_bignum *tmp2 = NULL; + u8 x_y[2 * MAX_ECC_PRIME_LEN]; + struct crypto_bignum *tmp2 = NULL, *y = NULL; struct crypto_hash *hash; unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr; int ret = 0, res; @@ -139,6 +140,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, u8 found_ctr = 0, is_odd = 0; int cmp_prime; unsigned int in_range; + unsigned int is_eq; if (grp->pwe) return -1; @@ -151,11 +153,6 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), primebytelen) < 0) return -1; - grp->pwe = crypto_ec_point_init(grp->group); - if (!grp->pwe) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums"); - goto fail; - } if ((prfbuf = os_malloc(primebytelen)) == NULL) { wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf " @@ -261,10 +258,37 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, */ crypto_bignum_deinit(x_candidate, 1); x_candidate = crypto_bignum_init_set(x_bin, primebytelen); - if (!x_candidate || - crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate, - is_odd) != 0) { - wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y"); + if (!x_candidate) + goto fail; + + /* y = sqrt(x^3 + ax + b) mod p + * if LSB(y) == LSB(pwd-seed): PWE = (x, y) + * else: PWE = (x, p - y) + * + * Calculate y and the two possible values for PWE and after that, + * use constant time selection to copy the correct alternative. + */ + y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate); + if (!y || + dragonfly_sqrt(grp->group, y, y) < 0 || + crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 || + crypto_bignum_sub(prime, y, y) < 0 || + crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN, + MAX_ECC_PRIME_LEN, primebytelen) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); + goto fail; + } + + /* Constant time selection of the y coordinate from the two + * options */ + is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01); + const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN, + primebytelen, x_y + primebytelen); + os_memcpy(x_y, x_bin, primebytelen); + wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen); + grp->pwe = crypto_ec_point_from_bin(grp->group, x_y); + if (!grp->pwe) { + wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE"); goto fail; } @@ -289,6 +313,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, /* cleanliness and order.... */ crypto_bignum_deinit(x_candidate, 1); crypto_bignum_deinit(tmp2, 1); + crypto_bignum_deinit(y, 1); crypto_bignum_deinit(qr, 1); crypto_bignum_deinit(qnr, 1); bin_clear_free(prfbuf, primebytelen); @@ -296,6 +321,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num, os_memset(qnr_bin, 0, sizeof(qnr_bin)); os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin)); os_memset(pwe_digest, 0, sizeof(pwe_digest)); + forced_memzero(x_y, sizeof(x_y)); return ret; } diff --git a/contrib/wpa/wpa_supplicant/ChangeLog b/contrib/wpa/wpa_supplicant/ChangeLog index 5ca82457ad1b..efcc6cd9c9ba 100644 --- a/contrib/wpa/wpa_supplicant/ChangeLog +++ b/contrib/wpa/wpa_supplicant/ChangeLog @@ -1,5 +1,58 @@ ChangeLog for wpa_supplicant +2022-01-16 - v2.10 + * SAE changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + - added support for the hash-to-element mechanism (sae_pwe=1 or + sae_pwe=2); this is currently disabled by default, but will likely + get enabled by default in the future + - fixed PMKSA caching with OKC + - added support for SAE-PK + * EAP-pwd changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + * fixed P2P provision discovery processing of a specially constructed + invalid frame + [https://w1.fi/security/2021-1/] + * fixed P2P group information processing of a specially constructed + invalid frame + [https://w1.fi/security/2020-2/] + * fixed PMF disconnection protection bypass in AP mode + [https://w1.fi/security/2019-7/] + * added support for using OpenSSL 3.0 + * increased the maximum number of EAP message exchanges (mainly to + support cases with very large certificates) + * fixed various issues in experimental support for EAP-TEAP peer + * added support for DPP release 2 (Wi-Fi Device Provisioning Protocol) + * a number of MKA/MACsec fixes and extensions + * added support for SAE (WPA3-Personal) AP mode configuration + * added P2P support for EDMG (IEEE 802.11ay) channels + * fixed EAP-FAST peer with TLS GCM/CCM ciphers + * improved throughput estimation and BSS selection + * dropped support for libnl 1.1 + * added support for nl80211 control port for EAPOL frame TX/RX + * fixed OWE key derivation with groups 20 and 21; this breaks backwards + compatibility for these groups while the default group 19 remains + backwards compatible + * added support for Beacon protection + * added support for Extended Key ID for pairwise keys + * removed WEP support from the default build (CONFIG_WEP=y can be used + to enable it, if really needed) + * added a build option to remove TKIP support (CONFIG_NO_TKIP=y) + * added support for Transition Disable mechanism to allow the AP to + automatically disable transition mode to improve security + * extended D-Bus interface + * added support for PASN + * added a file-based backend for external password storage to allow + secret information to be moved away from the main configuration file + without requiring external tools + * added EAP-TLS peer support for TLS 1.3 (disabled by default for now) + * added support for SCS, MSCS, DSCP policy + * changed driver interface selection to default to automatic fallback + to other compiled in options + * a large number of other fixes, cleanup, and extensions + 2019-08-07 - v2.9 * SAE changes - disable use of groups using Brainpool curves diff --git a/contrib/wpa/wpa_supplicant/README b/contrib/wpa/wpa_supplicant/README index 05f15ff46bda..c643b2684700 100644 --- a/contrib/wpa/wpa_supplicant/README +++ b/contrib/wpa/wpa_supplicant/README @@ -1,7 +1,7 @@ wpa_supplicant ============== -Copyright (c) 2003-2019, Jouni Malinen and contributors +Copyright (c) 2003-2022, Jouni Malinen and contributors All Rights Reserved. This program is licensed under the BSD license (the one with diff --git a/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl b/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl deleted file mode 100644 index ea11d426df1f..000000000000 --- a/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl +++ /dev/null @@ -1,16 +0,0 @@ -/* - * binder interface for wpa_supplicant daemon - * Copyright (c) 2004-2016, Jouni Malinen - * Copyright (c) 2004-2016, Roshan Pius - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -package fi.w1.wpa_supplicant; - -/** - * Interface exposed by wpa_supplicant for each network interface it controls. - */ -interface IIface { -} diff --git a/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl b/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl deleted file mode 100644 index 1cbee20a620f..000000000000 --- a/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl +++ /dev/null @@ -1,59 +0,0 @@ -/* - * WPA Supplicant - binder interface for wpa_supplicant daemon - * Copyright (c) 2004-2016, Jouni Malinen - * Copyright (c) 2004-2016, Roshan Pius - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -package fi.w1.wpa_supplicant; - -import android.os.PersistableBundle; -import fi.w1.wpa_supplicant.IIface; - -/** - * Interface exposed by the wpa_supplicant binder service registered - * with the service manager with name: fi.w1.wpa_supplicant. - */ -interface ISupplicant { - /* Error values returned by the service to RPC method calls. */ - const int ERROR_INVALID_ARGS = 1; - const int ERROR_UNKNOWN = 2; - const int ERROR_IFACE_EXISTS = 3; - const int ERROR_IFACE_UNKNOWN = 4; - - /** - * Registers a wireless interface in wpa_supplicant. - * - * @param args A dictionary with arguments used to add the interface to - * wpa_supplicant. - * The dictionary may contain the following entries: - * Ifname(String) Name of the network interface to control, e.g., - * wlan0. - * BridgeIfname(String) Name of the bridge interface to control, e.g., - * br0. - * Driver(String) Driver name which the interface uses, e.g., nl80211. - * ConfigFile(String) Configuration file path. - * - * @return Binder object representing the interface. - */ - IIface CreateInterface(in PersistableBundle args); - - /** - * Deregisters a wireless interface from wpa_supplicant. - * - * @param ifname Name of the network interface, e.g., wlan0 - */ - void RemoveInterface(in @utf8InCpp String ifname); - - /** - * Gets a binder object for the interface corresponding to ifname - * which wpa_supplicant already controls. - * - * @param ifname Name of the network interface, e.g., wlan0 - * - * @return Binder object representing the interface. - */ - IIface GetInterface(in @utf8InCpp String ifname); -} diff --git a/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl b/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl deleted file mode 100644 index d624d9133603..000000000000 --- a/contrib/wpa/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * binder interface for wpa_supplicant daemon - * Copyright (c) 2004-2016, Jouni Malinen - * Copyright (c) 2004-2016, Roshan Pius - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -package fi.w1.wpa_supplicant; - -import android.os.PersistableBundle; - -/** - * Callback Interface exposed by the wpa_supplicant service. Clients need - * to host an instance of this binder object and pass a reference of the object - * to wpa_supplicant via the registerCallbacksObject method. - */ -interface ISupplicantCallbacks { -} diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c index 545e9f64295a..959a68b4cdf5 100644 --- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1780,6 +1780,7 @@ DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message, } +#ifdef CONFIG_INTERWORKING DBusMessage * wpas_dbus_handler_interworking_select(DBusMessage *message, struct wpa_supplicant *wpa_s) @@ -1800,6 +1801,7 @@ wpas_dbus_handler_interworking_select(DBusMessage *message, return reply; } +#endif /* CONFIG_INTERWORKING */ /** diff --git a/contrib/wpa/wpa_supplicant/doc/docbook/eapol_test.sgml b/contrib/wpa/wpa_supplicant/doc/docbook/eapol_test.sgml index 4cfa3c1db384..b9b0a95c2691 100644 --- a/contrib/wpa/wpa_supplicant/doc/docbook/eapol_test.sgml +++ b/contrib/wpa/wpa_supplicant/doc/docbook/eapol_test.sgml @@ -198,7 +198,7 @@ eapol_test -ctest.conf -a127.0.0.1 -p1812 -ssecret -r1 Legal - wpa_supplicant is copyright (c) 2003-2019, + wpa_supplicant is copyright (c) 2003-2022, Jouni Malinen j@w1.fi and contributors. All Rights Reserved. diff --git a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_background.sgml b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_background.sgml index 22241ccf9006..b0592e233b88 100644 --- a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_background.sgml +++ b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_background.sgml @@ -94,7 +94,7 @@ Legal - wpa_supplicant is copyright (c) 2003-2019, + wpa_supplicant is copyright (c) 2003-2022, Jouni Malinen j@w1.fi and contributors. All Rights Reserved. diff --git a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_cli.sgml b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_cli.sgml index 2ba1fe42236a..b3d95ee20abb 100644 --- a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_cli.sgml +++ b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_cli.sgml @@ -349,7 +349,7 @@ CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar Legal - wpa_supplicant is copyright (c) 2003-2019, + wpa_supplicant is copyright (c) 2003-2022, Jouni Malinen j@w1.fi and contributors. All Rights Reserved. diff --git a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_gui.sgml b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_gui.sgml index cb0c735e4ce7..c391645eef15 100644 --- a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_gui.sgml +++ b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_gui.sgml @@ -95,7 +95,7 @@ Legal - wpa_supplicant is copyright (c) 2003-2019, + wpa_supplicant is copyright (c) 2003-2022, Jouni Malinen j@w1.fi and contributors. All Rights Reserved. diff --git a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_passphrase.sgml index 077296904f89..5934e79ae108 100644 --- a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_passphrase.sgml +++ b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_passphrase.sgml @@ -66,7 +66,7 @@ Legal - wpa_supplicant is copyright (c) 2003-2019, + wpa_supplicant is copyright (c) 2003-2022, Jouni Malinen j@w1.fi and contributors. All Rights Reserved. diff --git a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_priv.sgml b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_priv.sgml index 0d5c94a9f776..4053eda3b3ba 100644 --- a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_priv.sgml +++ b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_priv.sgml @@ -141,7 +141,7 @@ wpa_supplicant -i ath0 -c wpa_supplicant.conf Legal - wpa_supplicant is copyright (c) 2003-2019, + wpa_supplicant is copyright (c) 2003-2022, Jouni Malinen j@w1.fi and contributors. All Rights Reserved. diff --git a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_supplicant.sgml index e4a83698393a..02012d1b08de 100644 --- a/contrib/wpa/wpa_supplicant/doc/docbook/wpa_supplicant.sgml +++ b/contrib/wpa/wpa_supplicant/doc/docbook/wpa_supplicant.sgml @@ -753,7 +753,7 @@ fi Legal - wpa_supplicant is copyright (c) 2003-2019, + wpa_supplicant is copyright (c) 2003-2022, Jouni Malinen j@w1.fi and contributors. All Rights Reserved. diff --git a/contrib/wpa/wpa_supplicant/sme.c b/contrib/wpa/wpa_supplicant/sme.c index 1dc7001a7305..7f43216c6582 100644 --- a/contrib/wpa/wpa_supplicant/sme.c +++ b/contrib/wpa/wpa_supplicant/sme.c @@ -946,6 +946,9 @@ static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit) struct wpa_supplicant *wpa_s = work->wpa_s; wpa_s->roam_in_progress = false; +#ifdef CONFIG_WNM + wpa_s->bss_trans_mgmt_in_progress = false; +#endif /* CONFIG_WNM */ if (deinit) { if (work->started) @@ -992,6 +995,13 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, "SME: Reject sme_authenticate() in favor of explicit roam request"); return; } +#ifdef CONFIG_WNM + if (wpa_s->bss_trans_mgmt_in_progress) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SME: Reject sme_authenticate() in favor of BSS transition management request"); + return; + } +#endif /* CONFIG_WNM */ if (radio_work_pending(wpa_s, "sme-connect")) { /* * The previous sme-connect work might no longer be valid due to diff --git a/contrib/wpa/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj b/contrib/wpa/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj deleted file mode 100755 index c92b8fd89d6c..000000000000 --- a/contrib/wpa/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj +++ /dev/null @@ -1,477 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/wpa/wpa_supplicant/vs2005/wpa_cli/wpa_cli.vcproj b/contrib/wpa/wpa_supplicant/vs2005/wpa_cli/wpa_cli.vcproj deleted file mode 100755 index d2de768e7cdc..000000000000 --- a/contrib/wpa/wpa_supplicant/vs2005/wpa_cli/wpa_cli.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/wpa/wpa_supplicant/vs2005/wpa_passphrase/wpa_passphrase.vcproj b/contrib/wpa/wpa_supplicant/vs2005/wpa_passphrase/wpa_passphrase.vcproj deleted file mode 100755 index 97aa2c5aecb5..000000000000 --- a/contrib/wpa/wpa_supplicant/vs2005/wpa_passphrase/wpa_passphrase.vcproj +++ /dev/null @@ -1,236 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/wpa/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj b/contrib/wpa/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj deleted file mode 100755 index 10c05b565597..000000000000 --- a/contrib/wpa/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj +++ /dev/null @@ -1,465 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/wpa/wpa_supplicant/wnm_sta.c b/contrib/wpa/wpa_supplicant/wnm_sta.c index 8a1a44690ba5..96160dccbf5b 100644 --- a/contrib/wpa/wpa_supplicant/wnm_sta.c +++ b/contrib/wpa/wpa_supplicant/wnm_sta.c @@ -1097,6 +1097,8 @@ static void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, int after_new_scan) { + struct wpa_radio_work *already_connecting; + wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Transition to BSS " MACSTR " based on BSS Transition Management Request (old BSSID " @@ -1121,9 +1123,18 @@ static void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s, return; } + already_connecting = radio_work_pending(wpa_s, "sme-connect"); wpa_s->reassociate = 1; wpa_printf(MSG_DEBUG, "WNM: Issuing connect"); wpa_supplicant_connect(wpa_s, bss, ssid); + + /* + * Indicate that a BSS transition is in progress so scan results that + * come in before the 'sme-connect' radio work gets executed do not + * override the original connection attempt. + */ + if (!already_connecting && radio_work_pending(wpa_s, "sme-connect")) + wpa_s->bss_trans_mgmt_in_progress = true; wnm_deallocate_memory(wpa_s); } diff --git a/contrib/wpa/wpa_supplicant/wpa_cli.c b/contrib/wpa/wpa_supplicant/wpa_cli.c index 5bbc4535e364..465d63862ee7 100644 --- a/contrib/wpa/wpa_supplicant/wpa_cli.c +++ b/contrib/wpa/wpa_supplicant/wpa_cli.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - command line interface for wpa_supplicant daemon - * Copyright (c) 2004-2019, Jouni Malinen + * Copyright (c) 2004-2022, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -29,7 +29,7 @@ static const char *const wpa_cli_version = "wpa_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2019, Jouni Malinen and contributors"; +"Copyright (c) 2004-2022, Jouni Malinen and contributors"; #define VENDOR_ELEM_FRAME_ID \ " 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \ diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant.c b/contrib/wpa/wpa_supplicant/wpa_supplicant.c index 53b44035f16e..cf990f5a8f85 100644 --- a/contrib/wpa/wpa_supplicant/wpa_supplicant.c +++ b/contrib/wpa/wpa_supplicant/wpa_supplicant.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - * Copyright (c) 2003-2019, Jouni Malinen + * Copyright (c) 2003-2022, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -71,7 +71,7 @@ const char *const wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" -"Copyright (c) 2003-2019, Jouni Malinen and contributors"; +"Copyright (c) 2003-2022, Jouni Malinen and contributors"; const char *const wpa_supplicant_license = "This software may be distributed under the terms of the BSD license.\n" @@ -3621,6 +3621,11 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) struct ieee80211_vht_capabilities vhtcaps_mask; #endif /* CONFIG_VHT_OVERRIDES */ + wpa_s->roam_in_progress = false; +#ifdef CONFIG_WNM + wpa_s->bss_trans_mgmt_in_progress = false; +#endif /* CONFIG_WNM */ + if (deinit) { if (work->started) { wpa_s->connect_work = NULL; @@ -8173,6 +8178,10 @@ void wpas_request_disconnection(struct wpa_supplicant *wpa_s) eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); radio_remove_works(wpa_s, "connect", 0); radio_remove_works(wpa_s, "sme-connect", 0); + wpa_s->roam_in_progress = false; +#ifdef CONFIG_WNM + wpa_s->bss_trans_mgmt_in_progress = false; +#endif /* CONFIG_WNM */ } diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h b/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h index 5fa765fda25c..8bb8672fbf7f 100644 --- a/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h +++ b/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h @@ -1286,6 +1286,7 @@ struct wpa_supplicant { struct os_reltime wnm_cand_valid_until; u8 wnm_cand_from_bss[ETH_ALEN]; enum bss_trans_mgmt_status_code bss_tm_status; + bool bss_trans_mgmt_in_progress; struct wpabuf *coloc_intf_elems; u8 coloc_intf_dialog_token; u8 coloc_intf_auto_report;