123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292 |
- /*
- * 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 <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #include <errno.h>
- #include <sqlite3.h>
- #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,
- };
- 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 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)
- {
- char *sql;
- int ret = 0;
- sql = sqlite3_mprintf("INSERT INTO sessions(timestamp,id,user,realm,"
- "operation,password,redirect_uri) "
- "VALUES "
- "(strftime('%%Y-%%m-%%d %%H:%%M:%%f','now'),"
- "%Q,%Q,%Q,%d,%Q,%Q)",
- sessionid, user ? user : "", realm ? realm : "",
- operation, pw ? pw : "",
- redirect_uri ? redirect_uri : "");
- 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_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",
- 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 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",
- 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",
- 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 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;
- node = xml_node_create(ctx->xml, parent, NULL, "UsernamePassword");
- if (node == NULL)
- return NULL;
- add_text_node(ctx, node, "Username", user);
- b64 = (char *) base64_encode((unsigned char *) pw, strlen(pw), NULL);
- if (b64 == NULL)
- return NULL;
- 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)
- {
- xml_node_t *node;
- node = build_username_password(ctx, cred, user, pw);
- if (node == NULL)
- return -1;
- add_text_node(ctx, node, "MachineManaged", "TRUE");
- 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)
- {
- 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) < 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);
- }
- 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 * 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 *real_user = NULL;
- char *status;
- char *cert;
- if (dmacc) {
- real_user = db_get_val(ctx, user, realm, "identity", dmacc);
- if (real_user == NULL) {
- debug_print(ctx, 1, "Could not find user identity for "
- "dmacc user '%s'", user);
- return NULL;
- }
- }
- cert = db_get_val(ctx, user, realm, "cert", dmacc);
- if (cert && cert[0] == '\0')
- cert = NULL;
- if (cert) {
- cred = build_credential_cert(ctx, real_user ? real_user : user,
- realm, cert);
- } 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");
- 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");
- return NULL;
- }
- snprintf(buf, sizeof(buf),
- "./Wi-Fi/%s/PerProviderSubscription/Credential1/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);
- 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, "Certificate credential - no need for DB "
- "password update on success notification");
- } 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);
- }
- 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 * 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);
- 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/Credential1/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);
- 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);
- 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
- ret = machine_remediation(ctx, user, realm, session_id, dmacc);
- free(type);
- return ret;
- }
- static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user,
- const char *realm, int use_dmacc)
- {
- char *policy_id;
- char fname[200];
- 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;
- }
- snprintf(fname, sizeof(fname), "%s/spp/policy/%s.xml",
- ctx->root_dir, policy_id);
- free(policy_id);
- debug_print(ctx, 1, "Use policy file %s", fname);
- policy = node_from_file(ctx->xml, fname);
- if (policy == NULL)
- return NULL;
- node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate/URI");
- if (node) {
- char *url;
- url = db_get_osu_config_val(ctx, realm, "policy_url");
- if (url == NULL) {
- xml_node_free(ctx->xml, policy);
- return NULL;
- }
- xml_node_set_text(ctx->xml, node, url);
- free(url);
- }
- 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);
- 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/Credential1/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)
- {
- 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) < 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)
- {
- xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp;
- xml_node_t *cred, *eap, *userpw;
- pps = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
- "PerProviderSubscription");
- if (pps == NULL)
- return NULL;
- add_text_node(ctx, pps, "UpdateIdentifier", "1");
- c = xml_node_create(ctx->xml, pps, NULL, "Credential1");
- add_text_node(ctx, c, "CredentialPriority", "1");
- 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");
- 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");
- add_text_node(ctx, upd, "UpdateMethod", "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");
- 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");
- 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 (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)
- {
- xml_namespace_t *ns;
- xml_node_t *spp_node, *enroll, *exec_node;
- char *val;
- char password[11];
- char *b64;
- if (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);
- xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user);
- b64 = (char *) base64_encode((unsigned char *) 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;
- 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);
- 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");
- pps = build_pps(ctx, user, realm, pw,
- fingerprint ? fingerprint : NULL, machine_managed);
- free(fingerprint);
- 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);
- 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/Credential1/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_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, 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)
- return hs20_user_input_registration(ctx, session_id, 1);
- 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_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;
- char *version;
- int valid;
- char *supp, *pos;
- char *err;
- 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);
- 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) < 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);
- 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) {
- if (devinfo)
- db_add_session_devinfo(ctx, session_id, devinfo);
- if (devdetail)
- 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;
- }
- 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 *sql;
- int ret = -1;
- char *free_account;
- int free_acc;
- char *type;
- int cert = 0;
- char *cert_pem, *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");
- 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);
- 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);
- 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;
- }
- sql = sqlite3_mprintf("INSERT INTO users(identity,realm,phase2,"
- "methods,cert,cert_pem,machine_managed) VALUES "
- "(%Q,%Q,1,%Q,%Q,%Q,%d)",
- user, realm, cert ? "TLS" : "TTLS-MSCHAPV2",
- fingerprint ? fingerprint : "",
- cert_pem ? cert_pem : "",
- pw_mm && atoi(pw_mm) ? 1 : 0);
- 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",
- 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 (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);
- 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, user, realm, session_id, "operation");
- if (!val) {
- debug_print(ctx, 1,
- "No session active for user: %s sessionID: %s",
- user, 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 == 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);
- }
- 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, user, realm, 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;
- }
|