hs20: prepare server using uci-defaults and ship files
authorDaniel Golle <redacted>
Mon, 17 Aug 2020 01:13:44 +0000 (02:13 +0100)
committerDaniel Golle <redacted>
Mon, 17 Aug 2020 13:12:05 +0000 (14:12 +0100)
Setup user database if non-existent, configure uhttpd .php interpreter
and patch php scripts to work out-of-the-box.
Also ship Hotspot 2.0 SPP and OMA DM XML schema/DTD files needed at
run-time for both client and server.

Signed-off-by: Daniel Golle <redacted>
net/hs20/Makefile
net/hs20/files/hostapd.config [new file with mode: 0644]
net/hs20/files/hs20-server.defaults [new file with mode: 0644]
net/hs20/files/hs20.config
net/hs20/files/hs20.init [new file with mode: 0644]
net/hs20/patches/100-fix-hs20_spp_server-path.patch [new file with mode: 0644]
net/hs20/patches/200-adapt-config-php.patch [new file with mode: 0644]
net/hs20/patches/300-paths-in-ca-setup-sh.patch [new file with mode: 0644]

index 159f721ee84f1c64b89261070f287ca7cee0a6f8..daad12f9e973a61b43498060ce3c62c070b649c3 100644 (file)
@@ -1,7 +1,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=hs20
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE_URL:=http://w1.fi/hostap.git
 PKG_SOURCE_PROTO:=git
@@ -18,6 +18,19 @@ PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
 PKG_LICENSE:=BSD-3-Clause
 PKG_CPE_ID:=cpe:/a:w1.fi:hostapd
 
+define Download/dm-ddf-dtd
+  URL:=http://www.openmobilealliance.org/tech/DTD
+  FILE:=dm_ddf-v1_2.dtd
+  HASH:=1fb8f97ee13b673e0d2386ef3ec64fbc9c8d75429a9725dc3fac295c4d5ccae4
+endef
+
+define Download/spp-xsd
+  URL:=https://raw.githubusercontent.com/greearb/hostap-ct/7a7b81d0e58c81796c7408a47082c9cc7587aa21/hs20/server/examples/Fedora20/hs20/spp
+  URL_FILE:=spp.xsd
+  FILE:=spp-v1_0.xsd
+  HASH:=83be16db72e96cca8d654d7f0b446cdd017090d5512a4cd5f7172204331fd8f2
+endef
+
 PKG_BUILD_PARALLEL:=1
 PKG_ASLR_PIE_REGULAR:=1
 
@@ -28,13 +41,32 @@ endif
 
 include $(INCLUDE_DIR)/package.mk
 
+define Package/hs20-common
+  SECTION:=net
+  CATEGORY:=Network
+  SUBMENU:=WirelessAPD
+  TITLE:=Hotspot 2.0 OSU common files
+  URL:=http://hostap.epitest.fi/
+endef
+
+define Package/hs20-common/description
+Hotspot 2.0 OSU common files
+
+Hotspot 2.0 SPP and OMA DM XML schema/DTD files
+endef
+
 define Package/hs20-client
   SECTION:=net
   CATEGORY:=Network
   SUBMENU:=WirelessAPD
   TITLE:=Hotspot 2.0 OSU client
   URL:=http://hostap.epitest.fi/
-  DEPENDS:=+libopenssl +libcurl +libxml2
+  DEPENDS:=+hs20-common +libopenssl +libcurl +libxml2
+endef
+
+define Package/hs20-client/description
+Hotspot 2.0 OSU client
+
 endef
 
 define Package/hs20-server
@@ -43,11 +75,26 @@ define Package/hs20-server
   SUBMENU:=WirelessAPD
   TITLE:=Hotspot 2.0 OSU server
   URL:=http://hostap.epitest.fi/
-  DEPENDS:=+libopenssl +libsqlite3 +libxml2 +php7 +php7-cgi +php7-mod-xml +openssl-util +sqlite3-cli
+  DEPENDS:=+hs20-common +libopenssl +libsqlite3 +libxml2 +php7 +php7-cgi +php7-mod-xml +php7-mod-pdo-sqlite +openssl-util +sqlite3-cli +uhttpd +xxd
+endef
+
+define Package/hs20-server/description
+Hotspot 2.0 OSU server
+
+This implementation and the example configuration 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.
+endef
+
+define Build/Prepare
+       $(call Build/Prepare/Default)
+       $(eval $(call Download,dm-ddf-dtd))
+       $(eval $(call Download,spp-xsd))
 endef
 
 define Build/Configure
-       cp "./files/hs20.config" "$(PKG_BUILD_DIR)/hostapd/.config"
+       $(CP) ./files/hostapd.config $(PKG_BUILD_DIR)/hostapd/.config
 endef
 
 define Build/RunMake
@@ -67,20 +114,30 @@ define Build/Compile
        $(call Build/RunMake,hs20/client,-lssl -lcrypto -lcurl -lxml2,all)
 endef
 
+define Package/hs20-common/install
+       $(INSTALL_DIR) $(1)/etc/hs20/spp
+       $(INSTALL_DATA) $(DL_DIR)/dm_ddf-v1_2.dtd $(1)/etc/hs20/spp
+       $(INSTALL_DATA) $(DL_DIR)/spp-v1_0.xsd $(1)/etc/hs20/spp/spp.xsd
+endef
+
 define Package/hs20-client/install
        $(INSTALL_DIR) $(1)/usr/sbin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/hs20/client/hs20-osu-client $(1)/usr/sbin/
 endef
 
 define Package/hs20-server/install
-       $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hs20/ca $(1)/www/hs20
+       $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hs20/ca $(1)/www/hs20 $(1)/etc/uci-defaults $(1)/etc/hs20/spp $(1)/etc/config $(1)/etc/init.d
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd/hostapd $(1)/usr/sbin/hostapd-hs20-radius-server
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd/hlr_auc_gw $(1)/usr/sbin/
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/hs20/server/hs20_spp_server $(1)/usr/sbin/
        $(INSTALL_DATA) $(PKG_BUILD_DIR)/hs20/server/www/* $(1)/www/hs20
-       $(INSTALL_DATA) $(PKG_BUILD_DIR)/hs20/server/*.txt $(1)/usr/share/hs20
-       $(INSTALL_DATA) $(PKG_BUILD_DIR)/hs20/server/ca/* $(1)/usr/share/hs20/ca
+       $(INSTALL_DATA) $(PKG_BUILD_DIR)/hs20/server/sql.txt $(1)/usr/share/hs20
+       $(CP) $(PKG_BUILD_DIR)/hs20/server/ca/* $(1)/usr/share/hs20/ca
+       $(INSTALL_BIN) ./files/hs20-server.defaults $(1)/etc/uci-defaults/hs20-server
+       $(INSTALL_CONF) ./files/hs20.config $(1)/etc/config/hs20
+       $(INSTALL_BIN) ./files/hs20.init $(1)/etc/init.d/hs20
 endef
 
+$(eval $(call BuildPackage,hs20-common))
 $(eval $(call BuildPackage,hs20-client))
 $(eval $(call BuildPackage,hs20-server))
diff --git a/net/hs20/files/hostapd.config b/net/hs20/files/hostapd.config
new file mode 100644 (file)
index 0000000..c93431d
--- /dev/null
@@ -0,0 +1,15 @@
+CONFIG_DRIVER_NONE=y
+CONFIG_PKCS12=y
+CONFIG_RADIUS_SERVER=y
+CONFIG_EAP=y
+CONFIG_EAP_TLS=y
+CONFIG_EAP_MSCHAPV2=y
+CONFIG_EAP_PEAP=y
+CONFIG_EAP_GTC=y
+CONFIG_EAP_TTLS=y
+CONFIG_EAP_SIM=y
+CONFIG_EAP_AKA=y
+CONFIG_EAP_AKA_PRIME=y
+CONFIG_SQLITE=y
+CONFIG_HS20=y
+CONFIG_WPS=y
diff --git a/net/hs20/files/hs20-server.defaults b/net/hs20/files/hs20-server.defaults
new file mode 100644 (file)
index 0000000..7ec5332
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+uci -q get uhttpd.main.interpreter | grep -q "^\.php" || uci -q batch <<-EOF >/dev/null
+add_list uhttpd.main.interpreter='.php=/usr/bin/php-cgi'
+commit uhttpd
+EOF
+
+mkdir -p /etc/hs20/AS/DB
+[ -e /etc/hs20/AS/DB/eap_user.db ] || sqlite3 /etc/hs20/AS/DB/eap_user.db < /usr/share/hs20/sql.txt
+
+exit 0
index 417d2ce093191d6f8195201b3142c58479ff6dc2..3fa298148b0abf87982aee8683d39ff414dbc1e6 100644 (file)
@@ -1,14 +1,36 @@
-CONFIG_DRIVER_NONE=y
-CONFIG_PKCS12=y
-CONFIG_RADIUS_SERVER=y
-CONFIG_EAP=y
-CONFIG_EAP_TLS=y
-CONFIG_EAP_MSCHAPV2=y
-CONFIG_EAP_PEAP=y
-CONFIG_EAP_GTC=y
-CONFIG_EAP_TTLS=y
-CONFIG_EAP_SIM=y
-CONFIG_EAP_AKA=y
-CONFIG_EAP_AKA_PRIME=y
-CONFIG_SQLITE=y
-CONFIG_HS20=y
+config server server
+       option enabled '0'
+       option spp_http_auth_url 'https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com'
+       option trust_root_cert_url 'https://osu-server.osu.example.com/hs20/files/spp-root-ca.der'
+       option trust_root_cert_fingerprint '5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647'
+       option aaa_trust_root_cert_url 'https://osu-server.osu.example.com/hs20/files/aaa-root-ca.der'
+       option aaa_trust_root_cert_fingerprint '5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647'
+       option free_account 'free'
+       option policy_url 'https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com'
+       option remediation_url 'https://subscription-server.osu.example.com/hs20/remediation.php?session_id='
+       option free_remediation_url 'https://subscription-server.osu.example.com/hs20/free-remediation.php?session_id='
+       option signup_url 'https://subscription-server.osu.example.com/hs20/signup.php?session_id='
+       option osu_nai 'osen@w1.fi'
+       option radius_passphrase 'radius-s3CReT'
+       option as_passphrase 'as-s3CReT'
+
+config ca ca
+       option company 'OpenWrt.org'
+       option friendly_name 'Example Operator'
+       option rootsubject 'Hotspot 2.0 Testing Root CA - 99'
+       option logo_sha1 '5e1d5085676eede6b02da14d31c523ec20ffba0b'
+       option logo_sha256 '4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d'
+       option logo_url 'http://osu.w1.fi/w1fi_logo.png'
+       option domain 'w1.fi'
+       option osu_client_subject 'osu-client.w1.fi'
+       option ocsp_server_subject 'ocsp.w1.fi'
+       option key_passphrase 'whatever'
+       option osu_server_name 'osu.w1.fi'
+       option ocsp_uri 'http://ocsp.w1.fi:8888/'
+       option revoked_subject 'osu-revoked.w1.fi'
+
+config policy policy
+       option update_interval '30'
+       option update_method 'ClientInitiated'
+       option restriction 'Unrestricted'
+       option uri 'https://policy-server.osu.example.com/hs20/spp.php'
diff --git a/net/hs20/files/hs20.init b/net/hs20/files/hs20.init
new file mode 100644 (file)
index 0000000..3812dd8
--- /dev/null
@@ -0,0 +1,195 @@
+#!/bin/sh /etc/rc.common
+
+START=49
+
+USE_PROCD=1
+
+setup_ca() {
+       [ -e /etc/hs20/AS/Key/server.pem ] && return 0
+
+       local company friendly_name rootsubject logo_sha1 logo_sha256 logo_url domain osu_client_subject ocsp_server_subject key_passphrase osu_server_name ocsp_uri revoked_subject
+       config_load hs20
+       config_get company ca company
+       config_get friendly_name ca friendly_name
+       config_get rootsubject ca rootsubject
+       config_get logo_sha1 ca logo_sha1
+       config_get logo_sha256 ca logo_sha256
+       config_get logo_url ca logo_url
+       config_get domain ca domain
+       config_get osu_client_subject ca osu_client_subject
+       config_get ocsp_server_subject ca ocsp_server_subject
+       config_get key_passphrase ca key_passphrase
+       config_get osu_server_name ca osu_server_name
+       config_get ocsp_uri ca ocsp_uri
+
+       mkdir -p /etc/hs20/ca
+       (
+         cd /etc/hs20/ca
+         /bin/busybox sh /usr/share/hs20/ca/setup.sh -c "$company" -C "$friendly_name" -g "$logo_sha1" -G "$logo_sha256" -l "$logo_url" -m "$domain" -o "$osu_client_subject" -O "$ocsp_server_subject" -p "$key_passphrase" -S "$osu_server_name" -u "$ocsp_uri" -V "$revoked_subject"
+       )
+
+       mkdir -p /etc/hs20/AS/Key
+       cp /etc/hs20/ca/server.* /etc/hs20/ca/ca.pem /etc/hs20/AS/Key
+
+       return 0
+}
+
+sql_set() {
+       echo "DELETE FROM osu_config WHERE realm='$1' AND field='$2';"
+       echo "INSERT INTO osu_config(realm,field,value) VALUES('$1','$2','$3');"
+}
+
+setup_dbconf() {
+       local domain spp_http_auth_url trust_root_cert_url
+       config_load hs20
+       config_get realm ca domain
+       config_get spp_http_auth_url server spp_http_auth_url
+       config_get trust_root_cert_url server trust_root_cert_url
+       config_get trust_root_cert_fingerprint server trust_root_cert_fingerprint
+       config_get aaa_trust_root_cert_url server aaa_trust_root_cert_url
+       config_get aaa_trust_root_cert_fingerprint server aaa_trust_root_cert_fingerprint
+       config_get free_account server free_account
+       config_get policy_url server policy_url
+       config_get remediation_url server remediation_url
+       config_get free_remediation_url server free_remediation_url
+       config_get signup_url server signup_url
+       (
+               sql_set $realm spp_http_auth_url "$spp_http_auth_url"
+               sql_set $realm trust_root_cert_url "$trust_root_cert_url"
+               sql_set $realm trust_root_cert_fingerprint "$trust_root_cert_fingerprint"
+               sql_set $realm aaa_trust_root_cert_url "$aaa_trust_root_cert_url"
+               sql_set $realm aaa_trust_root_cert_fingerprint "$aaa_trust_root_cert_fingerprint"
+               sql_set $realm free_account "$free_account"
+               sql_set $realm policy_url "$policy_url"
+               sql_set $realm remediation_url "$remediation_url"
+               sql_set $realm free_remediation_url "$free_remediation_url"
+               sql_set $realm signup_url "$signup_url"
+       ) | sqlite3 /etc/hs20/AS/DB/eap_user.db
+
+       return 0
+}
+
+setup_policy() {
+       local update_interval update_method restriction uri
+       config_load hs20
+       config_get update_interval policy update_interval
+       config_get update_method policy update_method
+       config_get restriction policy restriction
+       config_get uri policy uri
+
+       if [ ! -e "/etc/hs20/spp/policy/default.xml" ]; then
+               mkdir -p /etc/hs20/spp/policy
+               ln -s /tmp/run/spp-default-policy.xml /etc/hs20/spp/policy/default.xml
+       fi
+
+       cat > /tmp/run/spp-default-policy.xml <<EOF
+<Policy>
+       <PolicyUpdate>
+               <UpdateInterval>$update_interval</UpdateInterval>
+               <UpdateMethod>$update_method</UpdateMethod>
+               <Restriction>$restriction</Restriction>
+               <URI>$uri</URI>
+       </PolicyUpdate>
+</Policy>
+
+EOF
+       return 0
+}
+
+prepare_config() {
+       local key_passphrase subscr_remediation_url osu_nai as_passphrase radius_passphrase
+       config_load hs20
+       config_get key_passphrase ca key_passphrase
+       config_get subscr_remediation_url policy uri
+       config_get osu_nai server osu_nai
+       config_get as_passphrase server as_passphrase
+       config_get radius_passphrase server radius_passphrase
+
+       cat > /tmp/run/as-sql.conf <<EOF
+driver=none
+radius_server_clients=/etc/hs20/AS/as.radius_clients
+eap_server=1
+eap_user_file=sqlite:/etc/hs20/AS/DB/eap_user.db
+ca_cert=/etc/hs20/AS/Key/ca.pem
+server_cert=/etc/hs20/AS/Key/server.pem
+private_key=/etc/hs20/AS/Key/server.key
+private_key_passwd=$key_passphrase
+eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/etc/hs20/AS/DB/eap_sim.db
+subscr_remediation_url=$subscr_remediation_url
+EOF
+
+       mkdir -p /var/run/hostapd/hs20-radius
+       cat > /tmp/run/radius-sql.conf <<EOF
+# hostapd-radius config for the radius used by the OSEN AP
+interface=lo
+driver=none
+logger_syslog=-1
+logger_syslog_level=2
+logger_stdout=-1
+logger_stdout_level=2
+ctrl_interface=/var/run/hostapd/hs20-radius
+ctrl_interface_group=0
+eap_server=1
+eap_user_file=/etc/hs20/AS/hostapd-osen.eap_user
+server_id=ben-ota-2-osen
+radius_server_auth_port=1811
+radius_server_clients=/etc/hs20/AS/hostap.radius_clients
+
+ca_cert=/etc/hs20/ca/ca.pem
+server_cert=/etc/hs20/ca/server.pem
+private_key=/etc/hs20/ca/server.key
+private_key_passwd=$key_passphrase
+
+ocsp_stapling_response=/etc/hs20/ca/ocsp-server-cache.der
+EOF
+
+       cat > /etc/hs20/AS/hostapd-osen.eap_user <<EOF
+# For OSEN authentication (Hotspot 2.0 Release 2)
+"$osu_nai"      WFA-UNAUTH-TLS
+EOF
+
+       cat > /etc/hs20/AS/hostap.radius_clients <<EOF
+0.0.0.0/0       $radius_passphrase
+EOF
+
+       cat > /etc/hs20/AS/as.radius_clients <<EOF
+0.0.0.0/0       $as_passphrase
+EOF
+
+       return 0
+}
+
+start_service() {
+       local enabled
+       config_load hs20
+       config_get enabled server enabled
+
+       [ "$enabled" != "1" ] && [ "$enabled" != "true" ] && exit 0
+       echo "starting"
+
+       setup_ca
+       setup_policy
+       setup_dbconf
+       prepare_config
+
+       procd_open_instance ocsp-responder
+       procd_set_param command /usr/bin/openssl ocsp -index /etc/hs20/ca/demoCA/index.txt -port 8888 -nmin 5 -rsigner /etc/hs20/ca/ocsp.pem -rkey /etc/hs20/ca/ocsp.key -CA /etc/hs20/ca/demoCA/cacert.pem -text -ignore_err
+       procd_set_param stdout 1
+       procd_set_param stderr 1
+       procd_set_param respawn
+       procd_close_instance
+
+       procd_open_instance hs20-ac
+       procd_set_param command /usr/sbin/hostapd-hs20-radius-server /tmp/run/as-sql.conf
+       procd_set_param stdout 1
+       procd_set_param stderr 1
+       procd_set_param respawn
+       procd_close_instance
+
+       procd_open_instance hs20-radius
+       procd_set_param command /usr/sbin/hostapd-hs20-radius-server /tmp/run/radius-sql.conf
+       procd_set_param stdout 1
+       procd_set_param stderr 1
+       procd_set_param respawn
+       procd_close_instance
+}
diff --git a/net/hs20/patches/100-fix-hs20_spp_server-path.patch b/net/hs20/patches/100-fix-hs20_spp_server-path.patch
new file mode 100644 (file)
index 0000000..5b2f3c3
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/hs20/server/www/spp.php
++++ b/hs20/server/www/spp.php
+@@ -141,7 +141,7 @@ $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);
++$last = exec("/usr/sbin/hs20_spp_server -r$osu_root -f/tmp/hs20_spp_server.log", $output, $ret);
+ if ($ret == 2) {
+   if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
diff --git a/net/hs20/patches/200-adapt-config-php.patch b/net/hs20/patches/200-adapt-config-php.patch
new file mode 100644 (file)
index 0000000..6494bd0
--- /dev/null
@@ -0,0 +1,17 @@
+--- a/hs20/server/www/config.php
++++ b/hs20/server/www/config.php
+@@ -1,7 +1,11 @@
+ <?php
+-$osu_root = "/home/user/hs20-server";
++$osu_root = "/etc/hs20";
+ $osu_db = "sqlite:$osu_root/AS/DB/eap_user.db";
+ $t_c_file = "$osu_root/terms-and-conditions";
+-$t_c_timestamp = 123456789;
+-$hostapd_ctrl = "udg:///home/user/hs20-server/AS/ctrl/as"
++if (file_exists($t_c_file)) {
++      $t_c_timestamp = filemtime($t_c_file);
++} else {
++      $t_c_timestamp = filemtime($osu_root);
++}
++$hostapd_ctrl = "udg:///var/run/hostapd/hs20-radius/lo"
+ ?>
diff --git a/net/hs20/patches/300-paths-in-ca-setup-sh.patch b/net/hs20/patches/300-paths-in-ca-setup-sh.patch
new file mode 100644 (file)
index 0000000..5e98ac4
--- /dev/null
@@ -0,0 +1,24 @@
+--- a/hs20/server/ca/setup.sh
++++ b/hs20/server/ca/setup.sh
+@@ -3,7 +3,7 @@
+ if [ -z "$OPENSSL" ]; then
+     OPENSSL=openssl
+ fi
+-export OPENSSL_CONF=$PWD/openssl.cnf
++export OPENSSL_CONF=/usr/share/hs20/ca/openssl.cnf
+ PASS=whatever
+ if [ -z "$DOMAIN" ]; then
+     DOMAIN=w1.fi
+@@ -83,10 +83,10 @@ then
+ fi
+ # Set the passphrase and some other common config accordingly.
+-cat openssl-root.cnf | sed "s/@PASSWORD@/$PASS/" \
++cat /usr/share/hs20/ca/openssl-root.cnf | sed "s/@PASSWORD@/$PASS/" \
+  > my-openssl-root.cnf
+-cat openssl.cnf | sed "s/@PASSWORD@/$PASS/" |
++cat /usr/share/hs20/ca/openssl.cnf | sed "s/@PASSWORD@/$PASS/" |
+ sed "s,@OCSP_URI@,$OCSP_URI," |
+ sed "s,@LOGO_URI@,$LOGO_URI," |
+ sed "s,@LOGO_HASH1@,$LOGO_HASH1," |
git clone https://git.99rst.org/PROJECT