1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290 |
- /*
- * 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) {
- db_add_session_devinfo(ctx, session_id, devinfo);
- db_add_session_devdetail(ctx, session_id, devdetail);
- ret = hs20_user_input_complete(ctx, user, realm, dmacc,
- session_id);
- hs20_eventlog_node(ctx, user, realm, session_id,
- "user input completed response", ret);
- goto out;
- }
- if (strcasecmp(req_reason, "Certificate enrollment completed") == 0) {
- ret = hs20_cert_enroll_completed(ctx, user, realm, dmacc,
- session_id);
- hs20_eventlog_node(ctx, user, realm, session_id,
- "certificate enrollment response", ret);
- goto out;
- }
- if (strcasecmp(req_reason, "Certificate enrollment failed") == 0) {
- ret = hs20_cert_enroll_failed(ctx, user, realm, dmacc,
- session_id);
- hs20_eventlog_node(ctx, user, realm, session_id,
- "certificate enrollment failed response",
- ret);
- goto out;
- }
- 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;
- }
|