From a9574f0f99042b0214c9d3b408a672f513f7bb90 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 17 Oct 2018 19:08:12 +0300 Subject: [PATCH] HS 2.0: OSU server test functionality for incorrect behavior Add a mechanism to allow special incorrect behavior to be requested from OSU server by adding an optional parameter test= to the initial signup URL. This is for protocol testing purposes for the OSU client. This commit adds two special behavior cases: corrupt_aaa_hash and corrupt_subrem_hash. These can be used to generate PPS MO with invalid CertSHA256Fingerprint values for AAAServerTrustRoot and SubscriptionUpdate nodes. Signed-off-by: Jouni Malinen --- hs20/server/hs20_spp_server.c | 4 +++ hs20/server/spp_server.c | 65 +++++++++++++++++++++++++++++------ hs20/server/spp_server.h | 1 + hs20/server/sql.txt | 3 +- hs20/server/www/signup.php | 7 +++- hs20/server/www/spp.php | 6 ++++ 6 files changed, 74 insertions(+), 12 deletions(-) diff --git a/hs20/server/hs20_spp_server.c b/hs20/server/hs20_spp_server.c index 591f66bbd..abd6867dd 100644 --- a/hs20/server/hs20_spp_server.c +++ b/hs20/server/hs20_spp_server.c @@ -70,6 +70,10 @@ static int process(struct hs20_svc *ctx) 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) diff --git a/hs20/server/spp_server.c b/hs20/server/spp_server.c index 389f6b0a7..18290d9e8 100644 --- a/hs20/server/spp_server.c +++ b/hs20/server/spp_server.c @@ -69,14 +69,14 @@ static int db_add_session(struct hs20_svc *ctx, else addr[0] = '\0'; sql = sqlite3_mprintf("INSERT INTO sessions(timestamp,id,user,realm," - "operation,password,redirect_uri,mac_addr) " + "operation,password,redirect_uri,mac_addr,test) " "VALUES " "(strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," - "%Q,%Q,%Q,%d,%Q,%Q,%Q)", + "%Q,%Q,%Q,%d,%Q,%Q,%Q,%Q)", sessionid, user ? user : "", realm ? realm : "", operation, pw ? pw : "", redirect_uri ? redirect_uri : "", - addr); + addr, ctx->test); if (sql == NULL) return -1; debug_print(ctx, 1, "DB: %s", sql); @@ -336,6 +336,29 @@ static void add_text_node_conf(struct hs20_svc *ctx, const char *realm, } +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; @@ -1241,7 +1264,7 @@ static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, 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) + int machine_managed, const char *test) { xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp; xml_node_t *cred, *eap, *userpw; @@ -1261,8 +1284,16 @@ static xml_node_t * build_pps(struct hs20_svc *ctx, aaa1 = xml_node_create(ctx->xml, aaa, NULL, "AAA1"); add_text_node_conf(ctx, realm, aaa1, "CertURL", "aaa_trust_root_cert_url"); - add_text_node_conf(ctx, realm, aaa1, "CertSHA256Fingerprint", - "aaa_trust_root_cert_fingerprint"); + 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"); + } upd = xml_node_create(ctx->xml, c, NULL, "SubscriptionUpdate"); add_text_node(ctx, upd, "UpdateInterval", "4294967295"); @@ -1271,8 +1302,16 @@ static xml_node_t * build_pps(struct hs20_svc *ctx, 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"); - add_text_node_conf(ctx, realm, trust, "CertSHA256Fingerprint", - "trust_root_cert_fingerprint"); + 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"); + } homesp = xml_node_create(ctx->xml, c, NULL, "HomeSP"); add_text_node_conf(ctx, realm, homesp, "FriendlyName", "friendly_name"); @@ -1356,7 +1395,7 @@ static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx, xml_node_t *pps, *tnds; char buf[400]; char *str; - char *user, *realm, *pw, *type, *mm; + char *user, *realm, *pw, *type, *mm, *test; const char *status; int cert = 0; int machine_managed = 0; @@ -1415,9 +1454,15 @@ static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx, 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); + fingerprint ? fingerprint : NULL, machine_managed, + test); free(fingerprint); + free(test); if (!pps) { xml_node_free(ctx->xml, spp_node); free(user); diff --git a/hs20/server/spp_server.h b/hs20/server/spp_server.h index 7b27be3c1..3556f5c9d 100644 --- a/hs20/server/spp_server.h +++ b/hs20/server/spp_server.h @@ -16,6 +16,7 @@ struct hs20_svc { FILE *debug_log; sqlite3 *db; const char *addr; + const char *test; }; diff --git a/hs20/server/sql.txt b/hs20/server/sql.txt index 75d2700e5..8fa019f57 100644 --- a/hs20/server/sql.txt +++ b/hs20/server/sql.txt @@ -23,7 +23,8 @@ CREATE TABLE sessions( devdetail TEXT, cert TEXT, cert_pem TEXT, - mac_addr TEXT + mac_addr TEXT, + test TEXT ); CREATE index sessions_id_index ON sessions(id); diff --git a/hs20/server/www/signup.php b/hs20/server/www/signup.php index 25dc33202..80a9d403e 100644 --- a/hs20/server/www/signup.php +++ b/hs20/server/www/signup.php @@ -15,11 +15,16 @@ if (!$db) { die($sqliteerror); } -$row = $db->query("SELECT realm FROM sessions WHERE id='$id'")->fetch(); +$row = $db->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"; diff --git a/hs20/server/www/spp.php b/hs20/server/www/spp.php index 002d0280f..f10e5ab81 100644 --- a/hs20/server/www/spp.php +++ b/hs20/server/www/spp.php @@ -20,6 +20,11 @@ if (isset($_GET["realm"])) { die("Realm not specified"); } +if (isset($_GET["test"])) + $test = PREG_REPLACE("/[^0-9a-zA-Z\_\-]/i", '', $_GET["test"]); +else + $test = ""; + unset($user); putenv("HS20CERT"); @@ -100,6 +105,7 @@ $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);