spp_server.c 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292
  1. /*
  2. * Hotspot 2.0 SPP server
  3. * Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <time.h>
  13. #include <errno.h>
  14. #include <sqlite3.h>
  15. #include "common.h"
  16. #include "base64.h"
  17. #include "md5_i.h"
  18. #include "xml-utils.h"
  19. #include "spp_server.h"
  20. #define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp"
  21. #define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0"
  22. #define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0"
  23. #define URN_OMA_DM_DMACC "urn:oma:mo:oma-dm-dmacc:1.0"
  24. #define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0"
  25. /* TODO: timeout to expire sessions */
  26. enum hs20_session_operation {
  27. NO_OPERATION,
  28. UPDATE_PASSWORD,
  29. CONTINUE_SUBSCRIPTION_REMEDIATION,
  30. CONTINUE_POLICY_UPDATE,
  31. USER_REMEDIATION,
  32. SUBSCRIPTION_REGISTRATION,
  33. POLICY_REMEDIATION,
  34. POLICY_UPDATE,
  35. FREE_REMEDIATION,
  36. };
  37. static char * db_get_session_val(struct hs20_svc *ctx, const char *user,
  38. const char *realm, const char *session_id,
  39. const char *field);
  40. static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm,
  41. const char *field);
  42. static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user,
  43. const char *realm, int use_dmacc);
  44. static int db_add_session(struct hs20_svc *ctx,
  45. const char *user, const char *realm,
  46. const char *sessionid, const char *pw,
  47. const char *redirect_uri,
  48. enum hs20_session_operation operation)
  49. {
  50. char *sql;
  51. int ret = 0;
  52. sql = sqlite3_mprintf("INSERT INTO sessions(timestamp,id,user,realm,"
  53. "operation,password,redirect_uri) "
  54. "VALUES "
  55. "(strftime('%%Y-%%m-%%d %%H:%%M:%%f','now'),"
  56. "%Q,%Q,%Q,%d,%Q,%Q)",
  57. sessionid, user ? user : "", realm ? realm : "",
  58. operation, pw ? pw : "",
  59. redirect_uri ? redirect_uri : "");
  60. if (sql == NULL)
  61. return -1;
  62. debug_print(ctx, 1, "DB: %s", sql);
  63. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  64. debug_print(ctx, 1, "Failed to add session entry into sqlite "
  65. "database: %s", sqlite3_errmsg(ctx->db));
  66. ret = -1;
  67. }
  68. sqlite3_free(sql);
  69. return ret;
  70. }
  71. static void db_update_session_password(struct hs20_svc *ctx, const char *user,
  72. const char *realm, const char *sessionid,
  73. const char *pw)
  74. {
  75. char *sql;
  76. sql = sqlite3_mprintf("UPDATE sessions SET password=%Q WHERE id=%Q AND "
  77. "user=%Q AND realm=%Q",
  78. pw, sessionid, user, realm);
  79. if (sql == NULL)
  80. return;
  81. debug_print(ctx, 1, "DB: %s", sql);
  82. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  83. debug_print(ctx, 1, "Failed to update session password: %s",
  84. sqlite3_errmsg(ctx->db));
  85. }
  86. sqlite3_free(sql);
  87. }
  88. static void db_update_session_machine_managed(struct hs20_svc *ctx,
  89. const char *user,
  90. const char *realm,
  91. const char *sessionid,
  92. const int pw_mm)
  93. {
  94. char *sql;
  95. sql = sqlite3_mprintf("UPDATE sessions SET machine_managed=%Q WHERE id=%Q AND user=%Q AND realm=%Q",
  96. pw_mm ? "1" : "0", sessionid, user, realm);
  97. if (sql == NULL)
  98. return;
  99. debug_print(ctx, 1, "DB: %s", sql);
  100. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  101. debug_print(ctx, 1,
  102. "Failed to update session machine_managed: %s",
  103. sqlite3_errmsg(ctx->db));
  104. }
  105. sqlite3_free(sql);
  106. }
  107. static void db_add_session_pps(struct hs20_svc *ctx, const char *user,
  108. const char *realm, const char *sessionid,
  109. xml_node_t *node)
  110. {
  111. char *str;
  112. char *sql;
  113. str = xml_node_to_str(ctx->xml, node);
  114. if (str == NULL)
  115. return;
  116. sql = sqlite3_mprintf("UPDATE sessions SET pps=%Q WHERE id=%Q AND "
  117. "user=%Q AND realm=%Q",
  118. str, sessionid, user, realm);
  119. free(str);
  120. if (sql == NULL)
  121. return;
  122. debug_print(ctx, 1, "DB: %s", sql);
  123. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  124. debug_print(ctx, 1, "Failed to add session pps: %s",
  125. sqlite3_errmsg(ctx->db));
  126. }
  127. sqlite3_free(sql);
  128. }
  129. static void db_add_session_devinfo(struct hs20_svc *ctx, const char *sessionid,
  130. xml_node_t *node)
  131. {
  132. char *str;
  133. char *sql;
  134. str = xml_node_to_str(ctx->xml, node);
  135. if (str == NULL)
  136. return;
  137. sql = sqlite3_mprintf("UPDATE sessions SET devinfo=%Q WHERE id=%Q",
  138. str, sessionid);
  139. free(str);
  140. if (sql == NULL)
  141. return;
  142. debug_print(ctx, 1, "DB: %s", sql);
  143. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  144. debug_print(ctx, 1, "Failed to add session devinfo: %s",
  145. sqlite3_errmsg(ctx->db));
  146. }
  147. sqlite3_free(sql);
  148. }
  149. static void db_add_session_devdetail(struct hs20_svc *ctx,
  150. const char *sessionid,
  151. xml_node_t *node)
  152. {
  153. char *str;
  154. char *sql;
  155. str = xml_node_to_str(ctx->xml, node);
  156. if (str == NULL)
  157. return;
  158. sql = sqlite3_mprintf("UPDATE sessions SET devdetail=%Q WHERE id=%Q",
  159. str, sessionid);
  160. free(str);
  161. if (sql == NULL)
  162. return;
  163. debug_print(ctx, 1, "DB: %s", sql);
  164. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  165. debug_print(ctx, 1, "Failed to add session devdetail: %s",
  166. sqlite3_errmsg(ctx->db));
  167. }
  168. sqlite3_free(sql);
  169. }
  170. static void db_remove_session(struct hs20_svc *ctx,
  171. const char *user, const char *realm,
  172. const char *sessionid)
  173. {
  174. char *sql;
  175. if (user == NULL || realm == NULL) {
  176. sql = sqlite3_mprintf("DELETE FROM sessions WHERE "
  177. "id=%Q", sessionid);
  178. } else {
  179. sql = sqlite3_mprintf("DELETE FROM sessions WHERE "
  180. "user=%Q AND realm=%Q AND id=%Q",
  181. user, realm, sessionid);
  182. }
  183. if (sql == NULL)
  184. return;
  185. debug_print(ctx, 1, "DB: %s", sql);
  186. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  187. debug_print(ctx, 1, "Failed to delete session entry from "
  188. "sqlite database: %s", sqlite3_errmsg(ctx->db));
  189. }
  190. sqlite3_free(sql);
  191. }
  192. static void hs20_eventlog(struct hs20_svc *ctx,
  193. const char *user, const char *realm,
  194. const char *sessionid, const char *notes,
  195. const char *dump)
  196. {
  197. char *sql;
  198. char *user_buf = NULL, *realm_buf = NULL;
  199. debug_print(ctx, 1, "eventlog: %s", notes);
  200. if (user == NULL) {
  201. user_buf = db_get_session_val(ctx, NULL, NULL, sessionid,
  202. "user");
  203. user = user_buf;
  204. realm_buf = db_get_session_val(ctx, NULL, NULL, sessionid,
  205. "realm");
  206. realm = realm_buf;
  207. }
  208. sql = sqlite3_mprintf("INSERT INTO eventlog"
  209. "(user,realm,sessionid,timestamp,notes,dump,addr)"
  210. " VALUES (%Q,%Q,%Q,"
  211. "strftime('%%Y-%%m-%%d %%H:%%M:%%f','now'),"
  212. "%Q,%Q,%Q)",
  213. user, realm, sessionid, notes,
  214. dump ? dump : "", ctx->addr ? ctx->addr : "");
  215. free(user_buf);
  216. free(realm_buf);
  217. if (sql == NULL)
  218. return;
  219. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  220. debug_print(ctx, 1, "Failed to add eventlog entry into sqlite "
  221. "database: %s", sqlite3_errmsg(ctx->db));
  222. }
  223. sqlite3_free(sql);
  224. }
  225. static void hs20_eventlog_node(struct hs20_svc *ctx,
  226. const char *user, const char *realm,
  227. const char *sessionid, const char *notes,
  228. xml_node_t *node)
  229. {
  230. char *str;
  231. if (node)
  232. str = xml_node_to_str(ctx->xml, node);
  233. else
  234. str = NULL;
  235. hs20_eventlog(ctx, user, realm, sessionid, notes, str);
  236. free(str);
  237. }
  238. static void db_update_mo_str(struct hs20_svc *ctx, const char *user,
  239. const char *realm, const char *name,
  240. const char *str)
  241. {
  242. char *sql;
  243. if (user == NULL || realm == NULL || name == NULL)
  244. return;
  245. sql = sqlite3_mprintf("UPDATE users SET %s=%Q "
  246. "WHERE identity=%Q AND realm=%Q AND phase2=1",
  247. name, str, user, realm);
  248. if (sql == NULL)
  249. return;
  250. debug_print(ctx, 1, "DB: %s", sql);
  251. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  252. debug_print(ctx, 1, "Failed to update user MO entry in sqlite "
  253. "database: %s", sqlite3_errmsg(ctx->db));
  254. }
  255. sqlite3_free(sql);
  256. }
  257. static void db_update_mo(struct hs20_svc *ctx, const char *user,
  258. const char *realm, const char *name, xml_node_t *mo)
  259. {
  260. char *str;
  261. str = xml_node_to_str(ctx->xml, mo);
  262. if (str == NULL)
  263. return;
  264. db_update_mo_str(ctx, user, realm, name, str);
  265. free(str);
  266. }
  267. static void add_text_node(struct hs20_svc *ctx, xml_node_t *parent,
  268. const char *name, const char *value)
  269. {
  270. xml_node_create_text(ctx->xml, parent, NULL, name, value ? value : "");
  271. }
  272. static void add_text_node_conf(struct hs20_svc *ctx, const char *realm,
  273. xml_node_t *parent, const char *name,
  274. const char *field)
  275. {
  276. char *val;
  277. val = db_get_osu_config_val(ctx, realm, field);
  278. xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : "");
  279. os_free(val);
  280. }
  281. static int new_password(char *buf, int buflen)
  282. {
  283. int i;
  284. if (buflen < 1)
  285. return -1;
  286. buf[buflen - 1] = '\0';
  287. if (os_get_random((unsigned char *) buf, buflen - 1) < 0)
  288. return -1;
  289. for (i = 0; i < buflen - 1; i++) {
  290. unsigned char val = buf[i];
  291. val %= 2 * 26 + 10;
  292. if (val < 26)
  293. buf[i] = 'a' + val;
  294. else if (val < 2 * 26)
  295. buf[i] = 'A' + val - 26;
  296. else
  297. buf[i] = '0' + val - 2 * 26;
  298. }
  299. return 0;
  300. }
  301. struct get_db_field_data {
  302. const char *field;
  303. char *value;
  304. };
  305. static int get_db_field(void *ctx, int argc, char *argv[], char *col[])
  306. {
  307. struct get_db_field_data *data = ctx;
  308. int i;
  309. for (i = 0; i < argc; i++) {
  310. if (os_strcmp(col[i], data->field) == 0 && argv[i]) {
  311. os_free(data->value);
  312. data->value = os_strdup(argv[i]);
  313. break;
  314. }
  315. }
  316. return 0;
  317. }
  318. static char * db_get_val(struct hs20_svc *ctx, const char *user,
  319. const char *realm, const char *field, int dmacc)
  320. {
  321. char *cmd;
  322. struct get_db_field_data data;
  323. cmd = sqlite3_mprintf("SELECT %s FROM users WHERE "
  324. "%s=%Q AND realm=%Q AND phase2=1",
  325. field, dmacc ? "osu_user" : "identity",
  326. user, realm);
  327. if (cmd == NULL)
  328. return NULL;
  329. memset(&data, 0, sizeof(data));
  330. data.field = field;
  331. if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK)
  332. {
  333. debug_print(ctx, 1, "Could not find user '%s'", user);
  334. sqlite3_free(cmd);
  335. return NULL;
  336. }
  337. sqlite3_free(cmd);
  338. debug_print(ctx, 1, "DB: user='%s' realm='%s' field='%s' dmacc=%d --> "
  339. "value='%s'", user, realm, field, dmacc, data.value);
  340. return data.value;
  341. }
  342. static int db_update_val(struct hs20_svc *ctx, const char *user,
  343. const char *realm, const char *field,
  344. const char *val, int dmacc)
  345. {
  346. char *cmd;
  347. int ret;
  348. cmd = sqlite3_mprintf("UPDATE users SET %s=%Q WHERE "
  349. "%s=%Q AND realm=%Q AND phase2=1",
  350. field, val, dmacc ? "osu_user" : "identity", user,
  351. realm);
  352. if (cmd == NULL)
  353. return -1;
  354. debug_print(ctx, 1, "DB: %s", cmd);
  355. if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) {
  356. debug_print(ctx, 1,
  357. "Failed to update user in sqlite database: %s",
  358. sqlite3_errmsg(ctx->db));
  359. ret = -1;
  360. } else {
  361. debug_print(ctx, 1,
  362. "DB: user='%s' realm='%s' field='%s' set to '%s'",
  363. user, realm, field, val);
  364. ret = 0;
  365. }
  366. sqlite3_free(cmd);
  367. return ret;
  368. }
  369. static char * db_get_session_val(struct hs20_svc *ctx, const char *user,
  370. const char *realm, const char *session_id,
  371. const char *field)
  372. {
  373. char *cmd;
  374. struct get_db_field_data data;
  375. if (user == NULL || realm == NULL) {
  376. cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE "
  377. "id=%Q", field, session_id);
  378. } else {
  379. cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE "
  380. "user=%Q AND realm=%Q AND id=%Q",
  381. field, user, realm, session_id);
  382. }
  383. if (cmd == NULL)
  384. return NULL;
  385. debug_print(ctx, 1, "DB: %s", cmd);
  386. memset(&data, 0, sizeof(data));
  387. data.field = field;
  388. if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK)
  389. {
  390. debug_print(ctx, 1, "DB: Could not find session %s: %s",
  391. session_id, sqlite3_errmsg(ctx->db));
  392. sqlite3_free(cmd);
  393. return NULL;
  394. }
  395. sqlite3_free(cmd);
  396. debug_print(ctx, 1, "DB: return '%s'", data.value);
  397. return data.value;
  398. }
  399. static int update_password(struct hs20_svc *ctx, const char *user,
  400. const char *realm, const char *pw, int dmacc)
  401. {
  402. char *cmd;
  403. cmd = sqlite3_mprintf("UPDATE users SET password=%Q, "
  404. "remediation='' "
  405. "WHERE %s=%Q AND phase2=1",
  406. pw, dmacc ? "osu_user" : "identity",
  407. user);
  408. if (cmd == NULL)
  409. return -1;
  410. debug_print(ctx, 1, "DB: %s", cmd);
  411. if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) {
  412. debug_print(ctx, 1, "Failed to update database for user '%s'",
  413. user);
  414. }
  415. sqlite3_free(cmd);
  416. return 0;
  417. }
  418. static int add_eap_ttls(struct hs20_svc *ctx, xml_node_t *parent)
  419. {
  420. xml_node_t *node;
  421. node = xml_node_create(ctx->xml, parent, NULL, "EAPMethod");
  422. if (node == NULL)
  423. return -1;
  424. add_text_node(ctx, node, "EAPType", "21");
  425. add_text_node(ctx, node, "InnerMethod", "MS-CHAP-V2");
  426. return 0;
  427. }
  428. static xml_node_t * build_username_password(struct hs20_svc *ctx,
  429. xml_node_t *parent,
  430. const char *user, const char *pw)
  431. {
  432. xml_node_t *node;
  433. char *b64;
  434. node = xml_node_create(ctx->xml, parent, NULL, "UsernamePassword");
  435. if (node == NULL)
  436. return NULL;
  437. add_text_node(ctx, node, "Username", user);
  438. b64 = (char *) base64_encode((unsigned char *) pw, strlen(pw), NULL);
  439. if (b64 == NULL)
  440. return NULL;
  441. add_text_node(ctx, node, "Password", b64);
  442. free(b64);
  443. return node;
  444. }
  445. static int add_username_password(struct hs20_svc *ctx, xml_node_t *cred,
  446. const char *user, const char *pw)
  447. {
  448. xml_node_t *node;
  449. node = build_username_password(ctx, cred, user, pw);
  450. if (node == NULL)
  451. return -1;
  452. add_text_node(ctx, node, "MachineManaged", "TRUE");
  453. add_text_node(ctx, node, "SoftTokenApp", "");
  454. add_eap_ttls(ctx, node);
  455. return 0;
  456. }
  457. static void add_creation_date(struct hs20_svc *ctx, xml_node_t *cred)
  458. {
  459. char str[30];
  460. time_t now;
  461. struct tm tm;
  462. time(&now);
  463. gmtime_r(&now, &tm);
  464. snprintf(str, sizeof(str), "%04u-%02u-%02uT%02u:%02u:%02uZ",
  465. tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
  466. tm.tm_hour, tm.tm_min, tm.tm_sec);
  467. xml_node_create_text(ctx->xml, cred, NULL, "CreationDate", str);
  468. }
  469. static xml_node_t * build_credential_pw(struct hs20_svc *ctx,
  470. const char *user, const char *realm,
  471. const char *pw)
  472. {
  473. xml_node_t *cred;
  474. cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential");
  475. if (cred == NULL) {
  476. debug_print(ctx, 1, "Failed to create Credential node");
  477. return NULL;
  478. }
  479. add_creation_date(ctx, cred);
  480. if (add_username_password(ctx, cred, user, pw) < 0) {
  481. xml_node_free(ctx->xml, cred);
  482. return NULL;
  483. }
  484. add_text_node(ctx, cred, "Realm", realm);
  485. return cred;
  486. }
  487. static xml_node_t * build_credential(struct hs20_svc *ctx,
  488. const char *user, const char *realm,
  489. char *new_pw, size_t new_pw_len)
  490. {
  491. if (new_password(new_pw, new_pw_len) < 0)
  492. return NULL;
  493. debug_print(ctx, 1, "Update password to '%s'", new_pw);
  494. return build_credential_pw(ctx, user, realm, new_pw);
  495. }
  496. static xml_node_t * build_credential_cert(struct hs20_svc *ctx,
  497. const char *user, const char *realm,
  498. const char *cert_fingerprint)
  499. {
  500. xml_node_t *cred, *cert;
  501. cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential");
  502. if (cred == NULL) {
  503. debug_print(ctx, 1, "Failed to create Credential node");
  504. return NULL;
  505. }
  506. add_creation_date(ctx, cred);
  507. cert = xml_node_create(ctx->xml, cred, NULL, "DigitalCertificate");
  508. add_text_node(ctx, cert, "CertificateType", "x509v3");
  509. add_text_node(ctx, cert, "CertSHA256Fingerprint", cert_fingerprint);
  510. add_text_node(ctx, cred, "Realm", realm);
  511. return cred;
  512. }
  513. static xml_node_t * build_post_dev_data_response(struct hs20_svc *ctx,
  514. xml_namespace_t **ret_ns,
  515. const char *session_id,
  516. const char *status,
  517. const char *error_code)
  518. {
  519. xml_node_t *spp_node = NULL;
  520. xml_namespace_t *ns;
  521. spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns,
  522. "sppPostDevDataResponse");
  523. if (spp_node == NULL)
  524. return NULL;
  525. if (ret_ns)
  526. *ret_ns = ns;
  527. xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0");
  528. xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id);
  529. xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status);
  530. if (error_code) {
  531. xml_node_t *node;
  532. node = xml_node_create(ctx->xml, spp_node, ns, "sppError");
  533. if (node)
  534. xml_node_add_attr(ctx->xml, node, NULL, "errorCode",
  535. error_code);
  536. }
  537. return spp_node;
  538. }
  539. static int add_update_node(struct hs20_svc *ctx, xml_node_t *spp_node,
  540. xml_namespace_t *ns, const char *uri,
  541. xml_node_t *upd_node)
  542. {
  543. xml_node_t *node, *tnds;
  544. char *str;
  545. tnds = mo_to_tnds(ctx->xml, upd_node, 0, NULL, NULL);
  546. if (!tnds)
  547. return -1;
  548. str = xml_node_to_str(ctx->xml, tnds);
  549. xml_node_free(ctx->xml, tnds);
  550. if (str == NULL)
  551. return -1;
  552. node = xml_node_create_text(ctx->xml, spp_node, ns, "updateNode", str);
  553. free(str);
  554. xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", uri);
  555. return 0;
  556. }
  557. static xml_node_t * build_sub_rem_resp(struct hs20_svc *ctx,
  558. const char *user, const char *realm,
  559. const char *session_id,
  560. int machine_rem, int dmacc)
  561. {
  562. xml_namespace_t *ns;
  563. xml_node_t *spp_node, *cred;
  564. char buf[400];
  565. char new_pw[33];
  566. char *real_user = NULL;
  567. char *status;
  568. char *cert;
  569. if (dmacc) {
  570. real_user = db_get_val(ctx, user, realm, "identity", dmacc);
  571. if (real_user == NULL) {
  572. debug_print(ctx, 1, "Could not find user identity for "
  573. "dmacc user '%s'", user);
  574. return NULL;
  575. }
  576. }
  577. cert = db_get_val(ctx, user, realm, "cert", dmacc);
  578. if (cert && cert[0] == '\0')
  579. cert = NULL;
  580. if (cert) {
  581. cred = build_credential_cert(ctx, real_user ? real_user : user,
  582. realm, cert);
  583. } else {
  584. cred = build_credential(ctx, real_user ? real_user : user,
  585. realm, new_pw, sizeof(new_pw));
  586. }
  587. free(real_user);
  588. if (!cred) {
  589. debug_print(ctx, 1, "Could not build credential");
  590. return NULL;
  591. }
  592. status = "Remediation complete, request sppUpdateResponse";
  593. spp_node = build_post_dev_data_response(ctx, &ns, session_id, status,
  594. NULL);
  595. if (spp_node == NULL) {
  596. debug_print(ctx, 1, "Could not build sppPostDevDataResponse");
  597. return NULL;
  598. }
  599. snprintf(buf, sizeof(buf),
  600. "./Wi-Fi/%s/PerProviderSubscription/Credential1/Credential",
  601. realm);
  602. if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) {
  603. debug_print(ctx, 1, "Could not add update node");
  604. xml_node_free(ctx->xml, spp_node);
  605. return NULL;
  606. }
  607. hs20_eventlog_node(ctx, user, realm, session_id,
  608. machine_rem ? "machine remediation" :
  609. "user remediation", cred);
  610. xml_node_free(ctx->xml, cred);
  611. if (cert) {
  612. debug_print(ctx, 1, "Certificate credential - no need for DB "
  613. "password update on success notification");
  614. } else {
  615. debug_print(ctx, 1, "Request DB password update on success "
  616. "notification");
  617. db_add_session(ctx, user, realm, session_id, new_pw, NULL,
  618. UPDATE_PASSWORD);
  619. }
  620. return spp_node;
  621. }
  622. static xml_node_t * machine_remediation(struct hs20_svc *ctx,
  623. const char *user,
  624. const char *realm,
  625. const char *session_id, int dmacc)
  626. {
  627. return build_sub_rem_resp(ctx, user, realm, session_id, 1, dmacc);
  628. }
  629. static xml_node_t * policy_remediation(struct hs20_svc *ctx,
  630. const char *user, const char *realm,
  631. const char *session_id, int dmacc)
  632. {
  633. xml_namespace_t *ns;
  634. xml_node_t *spp_node, *policy;
  635. char buf[400];
  636. const char *status;
  637. hs20_eventlog(ctx, user, realm, session_id,
  638. "requires policy remediation", NULL);
  639. db_add_session(ctx, user, realm, session_id, NULL, NULL,
  640. POLICY_REMEDIATION);
  641. policy = build_policy(ctx, user, realm, dmacc);
  642. if (!policy) {
  643. return build_post_dev_data_response(
  644. ctx, NULL, session_id,
  645. "No update available at this time", NULL);
  646. }
  647. status = "Remediation complete, request sppUpdateResponse";
  648. spp_node = build_post_dev_data_response(ctx, &ns, session_id, status,
  649. NULL);
  650. if (spp_node == NULL)
  651. return NULL;
  652. snprintf(buf, sizeof(buf),
  653. "./Wi-Fi/%s/PerProviderSubscription/Credential1/Policy",
  654. realm);
  655. if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) {
  656. xml_node_free(ctx->xml, spp_node);
  657. xml_node_free(ctx->xml, policy);
  658. return NULL;
  659. }
  660. hs20_eventlog_node(ctx, user, realm, session_id,
  661. "policy update (sub rem)", policy);
  662. xml_node_free(ctx->xml, policy);
  663. return spp_node;
  664. }
  665. static xml_node_t * browser_remediation(struct hs20_svc *ctx,
  666. const char *session_id,
  667. const char *redirect_uri,
  668. const char *uri)
  669. {
  670. xml_namespace_t *ns;
  671. xml_node_t *spp_node, *exec_node;
  672. if (redirect_uri == NULL) {
  673. debug_print(ctx, 1, "Missing redirectURI attribute for user "
  674. "remediation");
  675. return NULL;
  676. }
  677. debug_print(ctx, 1, "redirectURI %s", redirect_uri);
  678. spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK",
  679. NULL);
  680. if (spp_node == NULL)
  681. return NULL;
  682. exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec");
  683. xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI",
  684. uri);
  685. return spp_node;
  686. }
  687. static xml_node_t * user_remediation(struct hs20_svc *ctx, const char *user,
  688. const char *realm, const char *session_id,
  689. const char *redirect_uri)
  690. {
  691. char uri[300], *val;
  692. hs20_eventlog(ctx, user, realm, session_id,
  693. "requires user remediation", NULL);
  694. val = db_get_osu_config_val(ctx, realm, "remediation_url");
  695. if (val == NULL)
  696. return NULL;
  697. db_add_session(ctx, user, realm, session_id, NULL, redirect_uri,
  698. USER_REMEDIATION);
  699. snprintf(uri, sizeof(uri), "%s%s", val, session_id);
  700. os_free(val);
  701. return browser_remediation(ctx, session_id, redirect_uri, uri);
  702. }
  703. static xml_node_t * free_remediation(struct hs20_svc *ctx,
  704. const char *user, const char *realm,
  705. const char *session_id,
  706. const char *redirect_uri)
  707. {
  708. char uri[300], *val;
  709. hs20_eventlog(ctx, user, realm, session_id,
  710. "requires free/public account remediation", NULL);
  711. val = db_get_osu_config_val(ctx, realm, "free_remediation_url");
  712. if (val == NULL)
  713. return NULL;
  714. db_add_session(ctx, user, realm, session_id, NULL, redirect_uri,
  715. FREE_REMEDIATION);
  716. snprintf(uri, sizeof(uri), "%s%s", val, session_id);
  717. os_free(val);
  718. return browser_remediation(ctx, session_id, redirect_uri, uri);
  719. }
  720. static xml_node_t * no_sub_rem(struct hs20_svc *ctx,
  721. const char *user, const char *realm,
  722. const char *session_id)
  723. {
  724. const char *status;
  725. hs20_eventlog(ctx, user, realm, session_id,
  726. "no subscription mediation available", NULL);
  727. status = "No update available at this time";
  728. return build_post_dev_data_response(ctx, NULL, session_id, status,
  729. NULL);
  730. }
  731. static xml_node_t * hs20_subscription_remediation(struct hs20_svc *ctx,
  732. const char *user,
  733. const char *realm,
  734. const char *session_id,
  735. int dmacc,
  736. const char *redirect_uri)
  737. {
  738. char *type, *identity;
  739. xml_node_t *ret;
  740. char *free_account;
  741. identity = db_get_val(ctx, user, realm, "identity", dmacc);
  742. if (identity == NULL || strlen(identity) == 0) {
  743. hs20_eventlog(ctx, user, realm, session_id,
  744. "user not found in database for remediation",
  745. NULL);
  746. os_free(identity);
  747. return build_post_dev_data_response(ctx, NULL, session_id,
  748. "Error occurred",
  749. "Not found");
  750. }
  751. os_free(identity);
  752. free_account = db_get_osu_config_val(ctx, realm, "free_account");
  753. if (free_account && strcmp(free_account, user) == 0) {
  754. free(free_account);
  755. return no_sub_rem(ctx, user, realm, session_id);
  756. }
  757. free(free_account);
  758. type = db_get_val(ctx, user, realm, "remediation", dmacc);
  759. if (type && strcmp(type, "free") != 0) {
  760. char *val;
  761. int shared = 0;
  762. val = db_get_val(ctx, user, realm, "shared", dmacc);
  763. if (val)
  764. shared = atoi(val);
  765. free(val);
  766. if (shared) {
  767. free(type);
  768. return no_sub_rem(ctx, user, realm, session_id);
  769. }
  770. }
  771. if (type && strcmp(type, "user") == 0)
  772. ret = user_remediation(ctx, user, realm, session_id,
  773. redirect_uri);
  774. else if (type && strcmp(type, "free") == 0)
  775. ret = free_remediation(ctx, user, realm, session_id,
  776. redirect_uri);
  777. else if (type && strcmp(type, "policy") == 0)
  778. ret = policy_remediation(ctx, user, realm, session_id, dmacc);
  779. else
  780. ret = machine_remediation(ctx, user, realm, session_id, dmacc);
  781. free(type);
  782. return ret;
  783. }
  784. static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user,
  785. const char *realm, int use_dmacc)
  786. {
  787. char *policy_id;
  788. char fname[200];
  789. xml_node_t *policy, *node;
  790. policy_id = db_get_val(ctx, user, realm, "policy", use_dmacc);
  791. if (policy_id == NULL || strlen(policy_id) == 0) {
  792. free(policy_id);
  793. policy_id = strdup("default");
  794. if (policy_id == NULL)
  795. return NULL;
  796. }
  797. snprintf(fname, sizeof(fname), "%s/spp/policy/%s.xml",
  798. ctx->root_dir, policy_id);
  799. free(policy_id);
  800. debug_print(ctx, 1, "Use policy file %s", fname);
  801. policy = node_from_file(ctx->xml, fname);
  802. if (policy == NULL)
  803. return NULL;
  804. node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate/URI");
  805. if (node) {
  806. char *url;
  807. url = db_get_osu_config_val(ctx, realm, "policy_url");
  808. if (url == NULL) {
  809. xml_node_free(ctx->xml, policy);
  810. return NULL;
  811. }
  812. xml_node_set_text(ctx->xml, node, url);
  813. free(url);
  814. }
  815. node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate");
  816. if (node && use_dmacc) {
  817. char *pw;
  818. pw = db_get_val(ctx, user, realm, "osu_password", use_dmacc);
  819. if (pw == NULL ||
  820. build_username_password(ctx, node, user, pw) == NULL) {
  821. debug_print(ctx, 1, "Failed to add Policy/PolicyUpdate/"
  822. "UsernamePassword");
  823. free(pw);
  824. xml_node_free(ctx->xml, policy);
  825. return NULL;
  826. }
  827. free(pw);
  828. }
  829. return policy;
  830. }
  831. static xml_node_t * hs20_policy_update(struct hs20_svc *ctx,
  832. const char *user, const char *realm,
  833. const char *session_id, int dmacc)
  834. {
  835. xml_namespace_t *ns;
  836. xml_node_t *spp_node;
  837. xml_node_t *policy;
  838. char buf[400];
  839. const char *status;
  840. char *identity;
  841. identity = db_get_val(ctx, user, realm, "identity", dmacc);
  842. if (identity == NULL || strlen(identity) == 0) {
  843. hs20_eventlog(ctx, user, realm, session_id,
  844. "user not found in database for policy update",
  845. NULL);
  846. os_free(identity);
  847. return build_post_dev_data_response(ctx, NULL, session_id,
  848. "Error occurred",
  849. "Not found");
  850. }
  851. os_free(identity);
  852. policy = build_policy(ctx, user, realm, dmacc);
  853. if (!policy) {
  854. return build_post_dev_data_response(
  855. ctx, NULL, session_id,
  856. "No update available at this time", NULL);
  857. }
  858. db_add_session(ctx, user, realm, session_id, NULL, NULL, POLICY_UPDATE);
  859. status = "Update complete, request sppUpdateResponse";
  860. spp_node = build_post_dev_data_response(ctx, &ns, session_id, status,
  861. NULL);
  862. if (spp_node == NULL)
  863. return NULL;
  864. snprintf(buf, sizeof(buf),
  865. "./Wi-Fi/%s/PerProviderSubscription/Credential1/Policy",
  866. realm);
  867. if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) {
  868. xml_node_free(ctx->xml, spp_node);
  869. xml_node_free(ctx->xml, policy);
  870. return NULL;
  871. }
  872. hs20_eventlog_node(ctx, user, realm, session_id, "policy update",
  873. policy);
  874. xml_node_free(ctx->xml, policy);
  875. return spp_node;
  876. }
  877. static xml_node_t * spp_get_mo(struct hs20_svc *ctx, xml_node_t *node,
  878. const char *urn, int *valid, char **ret_err)
  879. {
  880. xml_node_t *child, *tnds, *mo;
  881. const char *name;
  882. char *mo_urn;
  883. char *str;
  884. char fname[200];
  885. *valid = -1;
  886. if (ret_err)
  887. *ret_err = NULL;
  888. xml_node_for_each_child(ctx->xml, child, node) {
  889. xml_node_for_each_check(ctx->xml, child);
  890. name = xml_node_get_localname(ctx->xml, child);
  891. if (strcmp(name, "moContainer") != 0)
  892. continue;
  893. mo_urn = xml_node_get_attr_value_ns(ctx->xml, child, SPP_NS_URI,
  894. "moURN");
  895. if (strcasecmp(urn, mo_urn) == 0) {
  896. xml_node_get_attr_value_free(ctx->xml, mo_urn);
  897. break;
  898. }
  899. xml_node_get_attr_value_free(ctx->xml, mo_urn);
  900. }
  901. if (child == NULL)
  902. return NULL;
  903. debug_print(ctx, 1, "moContainer text for %s", urn);
  904. debug_dump_node(ctx, "moContainer", child);
  905. str = xml_node_get_text(ctx->xml, child);
  906. debug_print(ctx, 1, "moContainer payload: '%s'", str);
  907. tnds = xml_node_from_buf(ctx->xml, str);
  908. xml_node_get_text_free(ctx->xml, str);
  909. if (tnds == NULL) {
  910. debug_print(ctx, 1, "could not parse moContainer text");
  911. return NULL;
  912. }
  913. snprintf(fname, sizeof(fname), "%s/spp/dm_ddf-v1_2.dtd", ctx->root_dir);
  914. if (xml_validate_dtd(ctx->xml, tnds, fname, ret_err) == 0)
  915. *valid = 1;
  916. else if (ret_err && *ret_err &&
  917. os_strcmp(*ret_err, "No declaration for attribute xmlns of element MgmtTree\n") == 0) {
  918. free(*ret_err);
  919. debug_print(ctx, 1, "Ignore OMA-DM DDF DTD validation error for MgmtTree namespace declaration with xmlns attribute");
  920. *ret_err = NULL;
  921. *valid = 1;
  922. } else
  923. *valid = 0;
  924. mo = tnds_to_mo(ctx->xml, tnds);
  925. xml_node_free(ctx->xml, tnds);
  926. if (mo == NULL) {
  927. debug_print(ctx, 1, "invalid moContainer for %s", urn);
  928. }
  929. return mo;
  930. }
  931. static xml_node_t * spp_exec_upload_mo(struct hs20_svc *ctx,
  932. const char *session_id, const char *urn)
  933. {
  934. xml_namespace_t *ns;
  935. xml_node_t *spp_node, *node, *exec_node;
  936. spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK",
  937. NULL);
  938. if (spp_node == NULL)
  939. return NULL;
  940. exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec");
  941. node = xml_node_create(ctx->xml, exec_node, ns, "uploadMO");
  942. xml_node_add_attr(ctx->xml, node, ns, "moURN", urn);
  943. return spp_node;
  944. }
  945. static xml_node_t * hs20_subscription_registration(struct hs20_svc *ctx,
  946. const char *realm,
  947. const char *session_id,
  948. const char *redirect_uri)
  949. {
  950. xml_namespace_t *ns;
  951. xml_node_t *spp_node, *exec_node;
  952. char uri[300], *val;
  953. if (db_add_session(ctx, NULL, realm, session_id, NULL, redirect_uri,
  954. SUBSCRIPTION_REGISTRATION) < 0)
  955. return NULL;
  956. val = db_get_osu_config_val(ctx, realm, "signup_url");
  957. if (val == NULL)
  958. return NULL;
  959. spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK",
  960. NULL);
  961. if (spp_node == NULL)
  962. return NULL;
  963. exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec");
  964. snprintf(uri, sizeof(uri), "%s%s", val, session_id);
  965. os_free(val);
  966. xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI",
  967. uri);
  968. return spp_node;
  969. }
  970. static xml_node_t * hs20_user_input_remediation(struct hs20_svc *ctx,
  971. const char *user,
  972. const char *realm, int dmacc,
  973. const char *session_id)
  974. {
  975. return build_sub_rem_resp(ctx, user, realm, session_id, 0, dmacc);
  976. }
  977. static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm,
  978. const char *field)
  979. {
  980. char *cmd;
  981. struct get_db_field_data data;
  982. cmd = sqlite3_mprintf("SELECT value FROM osu_config WHERE realm=%Q AND "
  983. "field=%Q", realm, field);
  984. if (cmd == NULL)
  985. return NULL;
  986. debug_print(ctx, 1, "DB: %s", cmd);
  987. memset(&data, 0, sizeof(data));
  988. data.field = "value";
  989. if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK)
  990. {
  991. debug_print(ctx, 1, "DB: Could not find osu_config %s: %s",
  992. realm, sqlite3_errmsg(ctx->db));
  993. sqlite3_free(cmd);
  994. return NULL;
  995. }
  996. sqlite3_free(cmd);
  997. debug_print(ctx, 1, "DB: return '%s'", data.value);
  998. return data.value;
  999. }
  1000. static xml_node_t * build_pps(struct hs20_svc *ctx,
  1001. const char *user, const char *realm,
  1002. const char *pw, const char *cert,
  1003. int machine_managed)
  1004. {
  1005. xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp;
  1006. xml_node_t *cred, *eap, *userpw;
  1007. pps = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
  1008. "PerProviderSubscription");
  1009. if (pps == NULL)
  1010. return NULL;
  1011. add_text_node(ctx, pps, "UpdateIdentifier", "1");
  1012. c = xml_node_create(ctx->xml, pps, NULL, "Credential1");
  1013. add_text_node(ctx, c, "CredentialPriority", "1");
  1014. aaa = xml_node_create(ctx->xml, c, NULL, "AAAServerTrustRoot");
  1015. aaa1 = xml_node_create(ctx->xml, aaa, NULL, "AAA1");
  1016. add_text_node_conf(ctx, realm, aaa1, "CertURL",
  1017. "aaa_trust_root_cert_url");
  1018. add_text_node_conf(ctx, realm, aaa1, "CertSHA256Fingerprint",
  1019. "aaa_trust_root_cert_fingerprint");
  1020. upd = xml_node_create(ctx->xml, c, NULL, "SubscriptionUpdate");
  1021. add_text_node(ctx, upd, "UpdateInterval", "4294967295");
  1022. add_text_node(ctx, upd, "UpdateMethod", "ClientInitiated");
  1023. add_text_node(ctx, upd, "Restriction", "HomeSP");
  1024. add_text_node_conf(ctx, realm, upd, "URI", "spp_http_auth_url");
  1025. trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot");
  1026. add_text_node_conf(ctx, realm, trust, "CertURL", "trust_root_cert_url");
  1027. add_text_node_conf(ctx, realm, trust, "CertSHA256Fingerprint",
  1028. "trust_root_cert_fingerprint");
  1029. homesp = xml_node_create(ctx->xml, c, NULL, "HomeSP");
  1030. add_text_node_conf(ctx, realm, homesp, "FriendlyName", "friendly_name");
  1031. add_text_node_conf(ctx, realm, homesp, "FQDN", "fqdn");
  1032. xml_node_create(ctx->xml, c, NULL, "SubscriptionParameters");
  1033. cred = xml_node_create(ctx->xml, c, NULL, "Credential");
  1034. add_creation_date(ctx, cred);
  1035. if (cert) {
  1036. xml_node_t *dc;
  1037. dc = xml_node_create(ctx->xml, cred, NULL,
  1038. "DigitalCertificate");
  1039. add_text_node(ctx, dc, "CertificateType", "x509v3");
  1040. add_text_node(ctx, dc, "CertSHA256Fingerprint", cert);
  1041. } else {
  1042. userpw = build_username_password(ctx, cred, user, pw);
  1043. add_text_node(ctx, userpw, "MachineManaged",
  1044. machine_managed ? "TRUE" : "FALSE");
  1045. eap = xml_node_create(ctx->xml, userpw, NULL, "EAPMethod");
  1046. add_text_node(ctx, eap, "EAPType", "21");
  1047. add_text_node(ctx, eap, "InnerMethod", "MS-CHAP-V2");
  1048. }
  1049. add_text_node(ctx, cred, "Realm", realm);
  1050. return pps;
  1051. }
  1052. static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx,
  1053. const char *session_id,
  1054. const char *user,
  1055. const char *realm)
  1056. {
  1057. xml_namespace_t *ns;
  1058. xml_node_t *spp_node, *enroll, *exec_node;
  1059. char *val;
  1060. char password[11];
  1061. char *b64;
  1062. if (new_password(password, sizeof(password)) < 0)
  1063. return NULL;
  1064. spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK",
  1065. NULL);
  1066. if (spp_node == NULL)
  1067. return NULL;
  1068. exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec");
  1069. enroll = xml_node_create(ctx->xml, exec_node, ns, "getCertificate");
  1070. xml_node_add_attr(ctx->xml, enroll, NULL, "enrollmentProtocol", "EST");
  1071. val = db_get_osu_config_val(ctx, realm, "est_url");
  1072. xml_node_create_text(ctx->xml, enroll, ns, "enrollmentServerURI",
  1073. val ? val : "");
  1074. os_free(val);
  1075. xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user);
  1076. b64 = (char *) base64_encode((unsigned char *) password,
  1077. strlen(password), NULL);
  1078. if (b64 == NULL) {
  1079. xml_node_free(ctx->xml, spp_node);
  1080. return NULL;
  1081. }
  1082. xml_node_create_text(ctx->xml, enroll, ns, "estPassword", b64);
  1083. free(b64);
  1084. db_update_session_password(ctx, user, realm, session_id, password);
  1085. return spp_node;
  1086. }
  1087. static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx,
  1088. const char *session_id,
  1089. int enrollment_done)
  1090. {
  1091. xml_namespace_t *ns;
  1092. xml_node_t *spp_node, *node = NULL;
  1093. xml_node_t *pps, *tnds;
  1094. char buf[400];
  1095. char *str;
  1096. char *user, *realm, *pw, *type, *mm;
  1097. const char *status;
  1098. int cert = 0;
  1099. int machine_managed = 0;
  1100. char *fingerprint;
  1101. user = db_get_session_val(ctx, NULL, NULL, session_id, "user");
  1102. realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm");
  1103. pw = db_get_session_val(ctx, NULL, NULL, session_id, "password");
  1104. if (!user || !realm || !pw) {
  1105. debug_print(ctx, 1, "Could not find session info from DB for "
  1106. "the new subscription");
  1107. free(user);
  1108. free(realm);
  1109. free(pw);
  1110. return NULL;
  1111. }
  1112. mm = db_get_session_val(ctx, NULL, NULL, session_id, "machine_managed");
  1113. if (mm && atoi(mm))
  1114. machine_managed = 1;
  1115. free(mm);
  1116. type = db_get_session_val(ctx, NULL, NULL, session_id, "type");
  1117. if (type && strcmp(type, "cert") == 0)
  1118. cert = 1;
  1119. free(type);
  1120. if (cert && !enrollment_done) {
  1121. xml_node_t *ret;
  1122. hs20_eventlog(ctx, user, realm, session_id,
  1123. "request client certificate enrollment", NULL);
  1124. ret = spp_exec_get_certificate(ctx, session_id, user, realm);
  1125. free(user);
  1126. free(realm);
  1127. free(pw);
  1128. return ret;
  1129. }
  1130. if (!cert && strlen(pw) == 0) {
  1131. machine_managed = 1;
  1132. free(pw);
  1133. pw = malloc(11);
  1134. if (pw == NULL || new_password(pw, 11) < 0) {
  1135. free(user);
  1136. free(realm);
  1137. free(pw);
  1138. return NULL;
  1139. }
  1140. }
  1141. status = "Provisioning complete, request sppUpdateResponse";
  1142. spp_node = build_post_dev_data_response(ctx, &ns, session_id, status,
  1143. NULL);
  1144. if (spp_node == NULL)
  1145. return NULL;
  1146. fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert");
  1147. pps = build_pps(ctx, user, realm, pw,
  1148. fingerprint ? fingerprint : NULL, machine_managed);
  1149. free(fingerprint);
  1150. if (!pps) {
  1151. xml_node_free(ctx->xml, spp_node);
  1152. free(user);
  1153. free(realm);
  1154. free(pw);
  1155. return NULL;
  1156. }
  1157. debug_print(ctx, 1, "Request DB subscription registration on success "
  1158. "notification");
  1159. if (machine_managed) {
  1160. db_update_session_password(ctx, user, realm, session_id, pw);
  1161. db_update_session_machine_managed(ctx, user, realm, session_id,
  1162. machine_managed);
  1163. }
  1164. db_add_session_pps(ctx, user, realm, session_id, pps);
  1165. hs20_eventlog_node(ctx, user, realm, session_id,
  1166. "new subscription", pps);
  1167. free(user);
  1168. free(pw);
  1169. tnds = mo_to_tnds(ctx->xml, pps, 0, URN_HS20_PPS, NULL);
  1170. xml_node_free(ctx->xml, pps);
  1171. if (!tnds) {
  1172. xml_node_free(ctx->xml, spp_node);
  1173. free(realm);
  1174. return NULL;
  1175. }
  1176. str = xml_node_to_str(ctx->xml, tnds);
  1177. xml_node_free(ctx->xml, tnds);
  1178. if (str == NULL) {
  1179. xml_node_free(ctx->xml, spp_node);
  1180. free(realm);
  1181. return NULL;
  1182. }
  1183. node = xml_node_create_text(ctx->xml, spp_node, ns, "addMO", str);
  1184. free(str);
  1185. snprintf(buf, sizeof(buf), "./Wi-Fi/%s/PerProviderSubscription", realm);
  1186. free(realm);
  1187. xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", buf);
  1188. xml_node_add_attr(ctx->xml, node, ns, "moURN", URN_HS20_PPS);
  1189. return spp_node;
  1190. }
  1191. static xml_node_t * hs20_user_input_free_remediation(struct hs20_svc *ctx,
  1192. const char *user,
  1193. const char *realm,
  1194. const char *session_id)
  1195. {
  1196. xml_namespace_t *ns;
  1197. xml_node_t *spp_node;
  1198. xml_node_t *cred;
  1199. char buf[400];
  1200. char *status;
  1201. char *free_account, *pw;
  1202. free_account = db_get_osu_config_val(ctx, realm, "free_account");
  1203. if (free_account == NULL)
  1204. return NULL;
  1205. pw = db_get_val(ctx, free_account, realm, "password", 0);
  1206. if (pw == NULL) {
  1207. free(free_account);
  1208. return NULL;
  1209. }
  1210. cred = build_credential_pw(ctx, free_account, realm, pw);
  1211. free(free_account);
  1212. free(pw);
  1213. if (!cred) {
  1214. xml_node_free(ctx->xml, cred);
  1215. return NULL;
  1216. }
  1217. status = "Remediation complete, request sppUpdateResponse";
  1218. spp_node = build_post_dev_data_response(ctx, &ns, session_id, status,
  1219. NULL);
  1220. if (spp_node == NULL)
  1221. return NULL;
  1222. snprintf(buf, sizeof(buf),
  1223. "./Wi-Fi/%s/PerProviderSubscription/Credential1/Credential",
  1224. realm);
  1225. if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) {
  1226. xml_node_free(ctx->xml, spp_node);
  1227. return NULL;
  1228. }
  1229. hs20_eventlog_node(ctx, user, realm, session_id,
  1230. "free/public remediation", cred);
  1231. xml_node_free(ctx->xml, cred);
  1232. return spp_node;
  1233. }
  1234. static xml_node_t * hs20_user_input_complete(struct hs20_svc *ctx,
  1235. const char *user,
  1236. const char *realm, int dmacc,
  1237. const char *session_id)
  1238. {
  1239. char *val;
  1240. enum hs20_session_operation oper;
  1241. val = db_get_session_val(ctx, user, realm, session_id, "operation");
  1242. if (val == NULL) {
  1243. debug_print(ctx, 1, "No session %s found to continue",
  1244. session_id);
  1245. return NULL;
  1246. }
  1247. oper = atoi(val);
  1248. free(val);
  1249. if (oper == USER_REMEDIATION) {
  1250. return hs20_user_input_remediation(ctx, user, realm, dmacc,
  1251. session_id);
  1252. }
  1253. if (oper == FREE_REMEDIATION) {
  1254. return hs20_user_input_free_remediation(ctx, user, realm,
  1255. session_id);
  1256. }
  1257. if (oper == SUBSCRIPTION_REGISTRATION) {
  1258. return hs20_user_input_registration(ctx, session_id, 0);
  1259. }
  1260. debug_print(ctx, 1, "User session %s not in state for user input "
  1261. "completion", session_id);
  1262. return NULL;
  1263. }
  1264. static xml_node_t * hs20_cert_enroll_completed(struct hs20_svc *ctx,
  1265. const char *user,
  1266. const char *realm, int dmacc,
  1267. const char *session_id)
  1268. {
  1269. char *val;
  1270. enum hs20_session_operation oper;
  1271. val = db_get_session_val(ctx, user, realm, session_id, "operation");
  1272. if (val == NULL) {
  1273. debug_print(ctx, 1, "No session %s found to continue",
  1274. session_id);
  1275. return NULL;
  1276. }
  1277. oper = atoi(val);
  1278. free(val);
  1279. if (oper == SUBSCRIPTION_REGISTRATION)
  1280. return hs20_user_input_registration(ctx, session_id, 1);
  1281. debug_print(ctx, 1, "User session %s not in state for certificate "
  1282. "enrollment completion", session_id);
  1283. return NULL;
  1284. }
  1285. static xml_node_t * hs20_cert_enroll_failed(struct hs20_svc *ctx,
  1286. const char *user,
  1287. const char *realm, int dmacc,
  1288. const char *session_id)
  1289. {
  1290. char *val;
  1291. enum hs20_session_operation oper;
  1292. xml_node_t *spp_node, *node;
  1293. char *status;
  1294. xml_namespace_t *ns;
  1295. val = db_get_session_val(ctx, user, realm, session_id, "operation");
  1296. if (val == NULL) {
  1297. debug_print(ctx, 1, "No session %s found to continue",
  1298. session_id);
  1299. return NULL;
  1300. }
  1301. oper = atoi(val);
  1302. free(val);
  1303. if (oper != SUBSCRIPTION_REGISTRATION) {
  1304. debug_print(ctx, 1, "User session %s not in state for "
  1305. "enrollment failure", session_id);
  1306. return NULL;
  1307. }
  1308. status = "Error occurred";
  1309. spp_node = build_post_dev_data_response(ctx, &ns, session_id, status,
  1310. NULL);
  1311. if (spp_node == NULL)
  1312. return NULL;
  1313. node = xml_node_create(ctx->xml, spp_node, ns, "sppError");
  1314. xml_node_add_attr(ctx->xml, node, NULL, "errorCode",
  1315. "Credentials cannot be provisioned at this time");
  1316. db_remove_session(ctx, user, realm, session_id);
  1317. return spp_node;
  1318. }
  1319. static xml_node_t * hs20_spp_post_dev_data(struct hs20_svc *ctx,
  1320. xml_node_t *node,
  1321. const char *user,
  1322. const char *realm,
  1323. const char *session_id,
  1324. int dmacc)
  1325. {
  1326. const char *req_reason;
  1327. char *redirect_uri = NULL;
  1328. char *req_reason_buf = NULL;
  1329. char str[200];
  1330. xml_node_t *ret = NULL, *devinfo = NULL, *devdetail = NULL;
  1331. xml_node_t *mo;
  1332. char *version;
  1333. int valid;
  1334. char *supp, *pos;
  1335. char *err;
  1336. version = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI,
  1337. "sppVersion");
  1338. if (version == NULL || strstr(version, "1.0") == NULL) {
  1339. ret = build_post_dev_data_response(
  1340. ctx, NULL, session_id, "Error occurred",
  1341. "SPP version not supported");
  1342. hs20_eventlog_node(ctx, user, realm, session_id,
  1343. "Unsupported sppVersion", ret);
  1344. xml_node_get_attr_value_free(ctx->xml, version);
  1345. return ret;
  1346. }
  1347. xml_node_get_attr_value_free(ctx->xml, version);
  1348. mo = get_node(ctx->xml, node, "supportedMOList");
  1349. if (mo == NULL) {
  1350. ret = build_post_dev_data_response(
  1351. ctx, NULL, session_id, "Error occurred",
  1352. "Other");
  1353. hs20_eventlog_node(ctx, user, realm, session_id,
  1354. "No supportedMOList element", ret);
  1355. return ret;
  1356. }
  1357. supp = xml_node_get_text(ctx->xml, mo);
  1358. for (pos = supp; pos && *pos; pos++)
  1359. *pos = tolower(*pos);
  1360. if (supp == NULL ||
  1361. strstr(supp, URN_OMA_DM_DEVINFO) == NULL ||
  1362. strstr(supp, URN_OMA_DM_DEVDETAIL) == NULL ||
  1363. strstr(supp, URN_HS20_PPS) == NULL) {
  1364. xml_node_get_text_free(ctx->xml, supp);
  1365. ret = build_post_dev_data_response(
  1366. ctx, NULL, session_id, "Error occurred",
  1367. "One or more mandatory MOs not supported");
  1368. hs20_eventlog_node(ctx, user, realm, session_id,
  1369. "Unsupported MOs", ret);
  1370. return ret;
  1371. }
  1372. xml_node_get_text_free(ctx->xml, supp);
  1373. req_reason_buf = xml_node_get_attr_value(ctx->xml, node,
  1374. "requestReason");
  1375. if (req_reason_buf == NULL) {
  1376. debug_print(ctx, 1, "No requestReason attribute");
  1377. return NULL;
  1378. }
  1379. req_reason = req_reason_buf;
  1380. redirect_uri = xml_node_get_attr_value(ctx->xml, node, "redirectURI");
  1381. debug_print(ctx, 1, "requestReason: %s sessionID: %s redirectURI: %s",
  1382. req_reason, session_id, redirect_uri);
  1383. snprintf(str, sizeof(str), "sppPostDevData: requestReason=%s",
  1384. req_reason);
  1385. hs20_eventlog(ctx, user, realm, session_id, str, NULL);
  1386. devinfo = spp_get_mo(ctx, node, URN_OMA_DM_DEVINFO, &valid, &err);
  1387. if (devinfo == NULL) {
  1388. ret = build_post_dev_data_response(ctx, NULL, session_id,
  1389. "Error occurred", "Other");
  1390. hs20_eventlog_node(ctx, user, realm, session_id,
  1391. "No DevInfo moContainer in sppPostDevData",
  1392. ret);
  1393. os_free(err);
  1394. goto out;
  1395. }
  1396. hs20_eventlog_node(ctx, user, realm, session_id,
  1397. "Received DevInfo MO", devinfo);
  1398. if (valid == 0) {
  1399. hs20_eventlog(ctx, user, realm, session_id,
  1400. "OMA-DM DDF DTD validation errors in DevInfo MO",
  1401. err);
  1402. ret = build_post_dev_data_response(ctx, NULL, session_id,
  1403. "Error occurred", "Other");
  1404. os_free(err);
  1405. goto out;
  1406. }
  1407. os_free(err);
  1408. if (user)
  1409. db_update_mo(ctx, user, realm, "devinfo", devinfo);
  1410. devdetail = spp_get_mo(ctx, node, URN_OMA_DM_DEVDETAIL, &valid, &err);
  1411. if (devdetail == NULL) {
  1412. ret = build_post_dev_data_response(ctx, NULL, session_id,
  1413. "Error occurred", "Other");
  1414. hs20_eventlog_node(ctx, user, realm, session_id,
  1415. "No DevDetail moContainer in sppPostDevData",
  1416. ret);
  1417. os_free(err);
  1418. goto out;
  1419. }
  1420. hs20_eventlog_node(ctx, user, realm, session_id,
  1421. "Received DevDetail MO", devdetail);
  1422. if (valid == 0) {
  1423. hs20_eventlog(ctx, user, realm, session_id,
  1424. "OMA-DM DDF DTD validation errors "
  1425. "in DevDetail MO", err);
  1426. ret = build_post_dev_data_response(ctx, NULL, session_id,
  1427. "Error occurred", "Other");
  1428. os_free(err);
  1429. goto out;
  1430. }
  1431. os_free(err);
  1432. if (user)
  1433. db_update_mo(ctx, user, realm, "devdetail", devdetail);
  1434. if (user)
  1435. mo = spp_get_mo(ctx, node, URN_HS20_PPS, &valid, &err);
  1436. else {
  1437. mo = NULL;
  1438. err = NULL;
  1439. }
  1440. if (user && mo) {
  1441. hs20_eventlog_node(ctx, user, realm, session_id,
  1442. "Received PPS MO", mo);
  1443. if (valid == 0) {
  1444. hs20_eventlog(ctx, user, realm, session_id,
  1445. "OMA-DM DDF DTD validation errors "
  1446. "in PPS MO", err);
  1447. xml_node_get_attr_value_free(ctx->xml, redirect_uri);
  1448. os_free(err);
  1449. return build_post_dev_data_response(
  1450. ctx, NULL, session_id,
  1451. "Error occurred", "Other");
  1452. }
  1453. db_update_mo(ctx, user, realm, "pps", mo);
  1454. db_update_val(ctx, user, realm, "fetch_pps", "0", dmacc);
  1455. xml_node_free(ctx->xml, mo);
  1456. }
  1457. os_free(err);
  1458. if (user && !mo) {
  1459. char *fetch;
  1460. int fetch_pps;
  1461. fetch = db_get_val(ctx, user, realm, "fetch_pps", dmacc);
  1462. fetch_pps = fetch ? atoi(fetch) : 0;
  1463. free(fetch);
  1464. if (fetch_pps) {
  1465. enum hs20_session_operation oper;
  1466. if (strcasecmp(req_reason, "Subscription remediation")
  1467. == 0)
  1468. oper = CONTINUE_SUBSCRIPTION_REMEDIATION;
  1469. else if (strcasecmp(req_reason, "Policy update") == 0)
  1470. oper = CONTINUE_POLICY_UPDATE;
  1471. else
  1472. oper = NO_OPERATION;
  1473. if (db_add_session(ctx, user, realm, session_id, NULL,
  1474. NULL, oper) < 0)
  1475. goto out;
  1476. ret = spp_exec_upload_mo(ctx, session_id,
  1477. URN_HS20_PPS);
  1478. hs20_eventlog_node(ctx, user, realm, session_id,
  1479. "request PPS MO upload",
  1480. ret);
  1481. goto out;
  1482. }
  1483. }
  1484. if (user && strcasecmp(req_reason, "MO upload") == 0) {
  1485. char *val = db_get_session_val(ctx, user, realm, session_id,
  1486. "operation");
  1487. enum hs20_session_operation oper;
  1488. if (!val) {
  1489. debug_print(ctx, 1, "No session %s found to continue",
  1490. session_id);
  1491. goto out;
  1492. }
  1493. oper = atoi(val);
  1494. free(val);
  1495. if (oper == CONTINUE_SUBSCRIPTION_REMEDIATION)
  1496. req_reason = "Subscription remediation";
  1497. else if (oper == CONTINUE_POLICY_UPDATE)
  1498. req_reason = "Policy update";
  1499. else {
  1500. debug_print(ctx, 1,
  1501. "No pending operation in session %s",
  1502. session_id);
  1503. goto out;
  1504. }
  1505. }
  1506. if (strcasecmp(req_reason, "Subscription registration") == 0) {
  1507. ret = hs20_subscription_registration(ctx, realm, session_id,
  1508. redirect_uri);
  1509. hs20_eventlog_node(ctx, user, realm, session_id,
  1510. "subscription registration response",
  1511. ret);
  1512. goto out;
  1513. }
  1514. if (user && strcasecmp(req_reason, "Subscription remediation") == 0) {
  1515. ret = hs20_subscription_remediation(ctx, user, realm,
  1516. session_id, dmacc,
  1517. redirect_uri);
  1518. hs20_eventlog_node(ctx, user, realm, session_id,
  1519. "subscription remediation response",
  1520. ret);
  1521. goto out;
  1522. }
  1523. if (user && strcasecmp(req_reason, "Policy update") == 0) {
  1524. ret = hs20_policy_update(ctx, user, realm, session_id, dmacc);
  1525. hs20_eventlog_node(ctx, user, realm, session_id,
  1526. "policy update response",
  1527. ret);
  1528. goto out;
  1529. }
  1530. if (strcasecmp(req_reason, "User input completed") == 0) {
  1531. if (devinfo)
  1532. db_add_session_devinfo(ctx, session_id, devinfo);
  1533. if (devdetail)
  1534. db_add_session_devdetail(ctx, session_id, devdetail);
  1535. ret = hs20_user_input_complete(ctx, user, realm, dmacc,
  1536. session_id);
  1537. hs20_eventlog_node(ctx, user, realm, session_id,
  1538. "user input completed response", ret);
  1539. goto out;
  1540. }
  1541. if (strcasecmp(req_reason, "Certificate enrollment completed") == 0) {
  1542. ret = hs20_cert_enroll_completed(ctx, user, realm, dmacc,
  1543. session_id);
  1544. hs20_eventlog_node(ctx, user, realm, session_id,
  1545. "certificate enrollment response", ret);
  1546. goto out;
  1547. }
  1548. if (strcasecmp(req_reason, "Certificate enrollment failed") == 0) {
  1549. ret = hs20_cert_enroll_failed(ctx, user, realm, dmacc,
  1550. session_id);
  1551. hs20_eventlog_node(ctx, user, realm, session_id,
  1552. "certificate enrollment failed response",
  1553. ret);
  1554. goto out;
  1555. }
  1556. debug_print(ctx, 1, "Unsupported requestReason '%s' user '%s'",
  1557. req_reason, user);
  1558. out:
  1559. xml_node_get_attr_value_free(ctx->xml, req_reason_buf);
  1560. xml_node_get_attr_value_free(ctx->xml, redirect_uri);
  1561. if (devinfo)
  1562. xml_node_free(ctx->xml, devinfo);
  1563. if (devdetail)
  1564. xml_node_free(ctx->xml, devdetail);
  1565. return ret;
  1566. }
  1567. static xml_node_t * build_spp_exchange_complete(struct hs20_svc *ctx,
  1568. const char *session_id,
  1569. const char *status,
  1570. const char *error_code)
  1571. {
  1572. xml_namespace_t *ns;
  1573. xml_node_t *spp_node, *node;
  1574. spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns,
  1575. "sppExchangeComplete");
  1576. xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0");
  1577. xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id);
  1578. xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status);
  1579. if (error_code) {
  1580. node = xml_node_create(ctx->xml, spp_node, ns, "sppError");
  1581. xml_node_add_attr(ctx->xml, node, NULL, "errorCode",
  1582. error_code);
  1583. }
  1584. return spp_node;
  1585. }
  1586. static int add_subscription(struct hs20_svc *ctx, const char *session_id)
  1587. {
  1588. char *user, *realm, *pw, *pw_mm, *pps, *str;
  1589. char *sql;
  1590. int ret = -1;
  1591. char *free_account;
  1592. int free_acc;
  1593. char *type;
  1594. int cert = 0;
  1595. char *cert_pem, *fingerprint;
  1596. user = db_get_session_val(ctx, NULL, NULL, session_id, "user");
  1597. realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm");
  1598. pw = db_get_session_val(ctx, NULL, NULL, session_id, "password");
  1599. pw_mm = db_get_session_val(ctx, NULL, NULL, session_id,
  1600. "machine_managed");
  1601. pps = db_get_session_val(ctx, NULL, NULL, session_id, "pps");
  1602. cert_pem = db_get_session_val(ctx, NULL, NULL, session_id, "cert_pem");
  1603. fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert");
  1604. type = db_get_session_val(ctx, NULL, NULL, session_id, "type");
  1605. if (type && strcmp(type, "cert") == 0)
  1606. cert = 1;
  1607. free(type);
  1608. if (!user || !realm || !pw) {
  1609. debug_print(ctx, 1, "Could not find session info from DB for "
  1610. "the new subscription");
  1611. goto out;
  1612. }
  1613. free_account = db_get_osu_config_val(ctx, realm, "free_account");
  1614. free_acc = free_account && strcmp(free_account, user) == 0;
  1615. free(free_account);
  1616. debug_print(ctx, 1,
  1617. "New subscription: user='%s' realm='%s' free_acc=%d",
  1618. user, realm, free_acc);
  1619. debug_print(ctx, 1, "New subscription: pps='%s'", pps);
  1620. sql = sqlite3_mprintf("UPDATE eventlog SET user=%Q, realm=%Q WHERE "
  1621. "sessionid=%Q AND (user='' OR user IS NULL)",
  1622. user, realm, session_id);
  1623. if (sql) {
  1624. debug_print(ctx, 1, "DB: %s", sql);
  1625. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  1626. debug_print(ctx, 1, "Failed to update eventlog in "
  1627. "sqlite database: %s",
  1628. sqlite3_errmsg(ctx->db));
  1629. }
  1630. sqlite3_free(sql);
  1631. }
  1632. if (free_acc) {
  1633. hs20_eventlog(ctx, user, realm, session_id,
  1634. "completed shared free account registration",
  1635. NULL);
  1636. ret = 0;
  1637. goto out;
  1638. }
  1639. sql = sqlite3_mprintf("INSERT INTO users(identity,realm,phase2,"
  1640. "methods,cert,cert_pem,machine_managed) VALUES "
  1641. "(%Q,%Q,1,%Q,%Q,%Q,%d)",
  1642. user, realm, cert ? "TLS" : "TTLS-MSCHAPV2",
  1643. fingerprint ? fingerprint : "",
  1644. cert_pem ? cert_pem : "",
  1645. pw_mm && atoi(pw_mm) ? 1 : 0);
  1646. if (sql == NULL)
  1647. goto out;
  1648. debug_print(ctx, 1, "DB: %s", sql);
  1649. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  1650. debug_print(ctx, 1, "Failed to add user in sqlite database: %s",
  1651. sqlite3_errmsg(ctx->db));
  1652. sqlite3_free(sql);
  1653. goto out;
  1654. }
  1655. sqlite3_free(sql);
  1656. if (cert)
  1657. ret = 0;
  1658. else
  1659. ret = update_password(ctx, user, realm, pw, 0);
  1660. if (ret < 0) {
  1661. sql = sqlite3_mprintf("DELETE FROM users WHERE identity=%Q AND "
  1662. "realm=%Q AND phase2=1",
  1663. user, realm);
  1664. if (sql) {
  1665. debug_print(ctx, 1, "DB: %s", sql);
  1666. sqlite3_exec(ctx->db, sql, NULL, NULL, NULL);
  1667. sqlite3_free(sql);
  1668. }
  1669. }
  1670. if (pps)
  1671. db_update_mo_str(ctx, user, realm, "pps", pps);
  1672. str = db_get_session_val(ctx, NULL, NULL, session_id, "devinfo");
  1673. if (str) {
  1674. db_update_mo_str(ctx, user, realm, "devinfo", str);
  1675. free(str);
  1676. }
  1677. str = db_get_session_val(ctx, NULL, NULL, session_id, "devdetail");
  1678. if (str) {
  1679. db_update_mo_str(ctx, user, realm, "devdetail", str);
  1680. free(str);
  1681. }
  1682. if (ret == 0) {
  1683. hs20_eventlog(ctx, user, realm, session_id,
  1684. "completed subscription registration", NULL);
  1685. }
  1686. out:
  1687. free(user);
  1688. free(realm);
  1689. free(pw);
  1690. free(pw_mm);
  1691. free(pps);
  1692. free(cert_pem);
  1693. free(fingerprint);
  1694. return ret;
  1695. }
  1696. static xml_node_t * hs20_spp_update_response(struct hs20_svc *ctx,
  1697. xml_node_t *node,
  1698. const char *user,
  1699. const char *realm,
  1700. const char *session_id,
  1701. int dmacc)
  1702. {
  1703. char *status;
  1704. xml_node_t *ret;
  1705. char *val;
  1706. enum hs20_session_operation oper;
  1707. status = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI,
  1708. "sppStatus");
  1709. if (status == NULL) {
  1710. debug_print(ctx, 1, "No sppStatus attribute");
  1711. return NULL;
  1712. }
  1713. debug_print(ctx, 1, "sppUpdateResponse: sppStatus: %s sessionID: %s",
  1714. status, session_id);
  1715. val = db_get_session_val(ctx, user, realm, session_id, "operation");
  1716. if (!val) {
  1717. debug_print(ctx, 1,
  1718. "No session active for user: %s sessionID: %s",
  1719. user, session_id);
  1720. oper = NO_OPERATION;
  1721. } else
  1722. oper = atoi(val);
  1723. if (strcasecmp(status, "OK") == 0) {
  1724. char *new_pw = NULL;
  1725. xml_node_get_attr_value_free(ctx->xml, status);
  1726. if (oper == USER_REMEDIATION) {
  1727. new_pw = db_get_session_val(ctx, user, realm,
  1728. session_id, "password");
  1729. if (new_pw == NULL || strlen(new_pw) == 0) {
  1730. free(new_pw);
  1731. ret = build_spp_exchange_complete(
  1732. ctx, session_id, "Error occurred",
  1733. "Other");
  1734. hs20_eventlog_node(ctx, user, realm,
  1735. session_id, "No password "
  1736. "had been assigned for "
  1737. "session", ret);
  1738. db_remove_session(ctx, user, realm, session_id);
  1739. return ret;
  1740. }
  1741. oper = UPDATE_PASSWORD;
  1742. }
  1743. if (oper == UPDATE_PASSWORD) {
  1744. if (!new_pw) {
  1745. new_pw = db_get_session_val(ctx, user, realm,
  1746. session_id,
  1747. "password");
  1748. if (!new_pw) {
  1749. db_remove_session(ctx, user, realm,
  1750. session_id);
  1751. return NULL;
  1752. }
  1753. }
  1754. debug_print(ctx, 1, "Update user '%s' password in DB",
  1755. user);
  1756. if (update_password(ctx, user, realm, new_pw, dmacc) <
  1757. 0) {
  1758. debug_print(ctx, 1, "Failed to update user "
  1759. "'%s' password in DB", user);
  1760. ret = build_spp_exchange_complete(
  1761. ctx, session_id, "Error occurred",
  1762. "Other");
  1763. hs20_eventlog_node(ctx, user, realm,
  1764. session_id, "Failed to "
  1765. "update database", ret);
  1766. db_remove_session(ctx, user, realm, session_id);
  1767. return ret;
  1768. }
  1769. hs20_eventlog(ctx, user, realm,
  1770. session_id, "Updated user password "
  1771. "in database", NULL);
  1772. }
  1773. if (oper == SUBSCRIPTION_REGISTRATION) {
  1774. if (add_subscription(ctx, session_id) < 0) {
  1775. debug_print(ctx, 1, "Failed to add "
  1776. "subscription into DB");
  1777. ret = build_spp_exchange_complete(
  1778. ctx, session_id, "Error occurred",
  1779. "Other");
  1780. hs20_eventlog_node(ctx, user, realm,
  1781. session_id, "Failed to "
  1782. "update database", ret);
  1783. db_remove_session(ctx, user, realm, session_id);
  1784. return ret;
  1785. }
  1786. }
  1787. if (oper == POLICY_REMEDIATION || oper == POLICY_UPDATE) {
  1788. char *val;
  1789. val = db_get_val(ctx, user, realm, "remediation",
  1790. dmacc);
  1791. if (val && strcmp(val, "policy") == 0)
  1792. db_update_val(ctx, user, realm, "remediation",
  1793. "", dmacc);
  1794. free(val);
  1795. }
  1796. ret = build_spp_exchange_complete(
  1797. ctx, session_id,
  1798. "Exchange complete, release TLS connection", NULL);
  1799. hs20_eventlog_node(ctx, user, realm, session_id,
  1800. "Exchange completed", ret);
  1801. db_remove_session(ctx, user, realm, session_id);
  1802. return ret;
  1803. }
  1804. ret = build_spp_exchange_complete(ctx, session_id, "Error occurred",
  1805. "Other");
  1806. hs20_eventlog_node(ctx, user, realm, session_id, "Error occurred", ret);
  1807. db_remove_session(ctx, user, realm, session_id);
  1808. xml_node_get_attr_value_free(ctx->xml, status);
  1809. return ret;
  1810. }
  1811. #define SPP_SESSION_ID_LEN 16
  1812. static char * gen_spp_session_id(void)
  1813. {
  1814. FILE *f;
  1815. int i;
  1816. char *session;
  1817. session = os_malloc(SPP_SESSION_ID_LEN * 2 + 1);
  1818. if (session == NULL)
  1819. return NULL;
  1820. f = fopen("/dev/urandom", "r");
  1821. if (f == NULL) {
  1822. os_free(session);
  1823. return NULL;
  1824. }
  1825. for (i = 0; i < SPP_SESSION_ID_LEN; i++)
  1826. os_snprintf(session + i * 2, 3, "%02x", fgetc(f));
  1827. fclose(f);
  1828. return session;
  1829. }
  1830. xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node,
  1831. const char *auth_user,
  1832. const char *auth_realm, int dmacc)
  1833. {
  1834. xml_node_t *ret = NULL;
  1835. char *session_id;
  1836. const char *op_name;
  1837. char *xml_err;
  1838. char fname[200];
  1839. debug_dump_node(ctx, "received request", node);
  1840. if (!dmacc && auth_user && auth_realm) {
  1841. char *real;
  1842. real = db_get_val(ctx, auth_user, auth_realm, "identity", 0);
  1843. if (!real) {
  1844. real = db_get_val(ctx, auth_user, auth_realm,
  1845. "identity", 1);
  1846. if (real)
  1847. dmacc = 1;
  1848. }
  1849. os_free(real);
  1850. }
  1851. snprintf(fname, sizeof(fname), "%s/spp/spp.xsd", ctx->root_dir);
  1852. if (xml_validate(ctx->xml, node, fname, &xml_err) < 0) {
  1853. /*
  1854. * We may not be able to extract the sessionID from invalid
  1855. * input, but well, we can try.
  1856. */
  1857. session_id = xml_node_get_attr_value_ns(ctx->xml, node,
  1858. SPP_NS_URI,
  1859. "sessionID");
  1860. debug_print(ctx, 1,
  1861. "SPP message failed validation, xsd file: %s xml-error: %s",
  1862. fname, xml_err);
  1863. hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
  1864. "SPP message failed validation", node);
  1865. hs20_eventlog(ctx, auth_user, auth_realm, session_id,
  1866. "Validation errors", xml_err);
  1867. os_free(xml_err);
  1868. xml_node_get_attr_value_free(ctx->xml, session_id);
  1869. /* TODO: what to return here? */
  1870. ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
  1871. "SppValidationError");
  1872. return ret;
  1873. }
  1874. session_id = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI,
  1875. "sessionID");
  1876. if (session_id) {
  1877. char *tmp;
  1878. debug_print(ctx, 1, "Received sessionID %s", session_id);
  1879. tmp = os_strdup(session_id);
  1880. xml_node_get_attr_value_free(ctx->xml, session_id);
  1881. if (tmp == NULL)
  1882. return NULL;
  1883. session_id = tmp;
  1884. } else {
  1885. session_id = gen_spp_session_id();
  1886. if (session_id == NULL) {
  1887. debug_print(ctx, 1, "Failed to generate sessionID");
  1888. return NULL;
  1889. }
  1890. debug_print(ctx, 1, "Generated sessionID %s", session_id);
  1891. }
  1892. op_name = xml_node_get_localname(ctx->xml, node);
  1893. if (op_name == NULL) {
  1894. debug_print(ctx, 1, "Could not get op_name");
  1895. return NULL;
  1896. }
  1897. if (strcmp(op_name, "sppPostDevData") == 0) {
  1898. hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
  1899. "sppPostDevData received and validated",
  1900. node);
  1901. ret = hs20_spp_post_dev_data(ctx, node, auth_user, auth_realm,
  1902. session_id, dmacc);
  1903. } else if (strcmp(op_name, "sppUpdateResponse") == 0) {
  1904. hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
  1905. "sppUpdateResponse received and validated",
  1906. node);
  1907. ret = hs20_spp_update_response(ctx, node, auth_user,
  1908. auth_realm, session_id, dmacc);
  1909. } else {
  1910. hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
  1911. "Unsupported SPP message received and "
  1912. "validated", node);
  1913. debug_print(ctx, 1, "Unsupported operation '%s'", op_name);
  1914. /* TODO: what to return here? */
  1915. ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
  1916. "SppUnknownCommandError");
  1917. }
  1918. os_free(session_id);
  1919. if (ret == NULL) {
  1920. /* TODO: what to return here? */
  1921. ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
  1922. "SppInternalError");
  1923. }
  1924. return ret;
  1925. }
  1926. int hs20_spp_server_init(struct hs20_svc *ctx)
  1927. {
  1928. char fname[200];
  1929. ctx->db = NULL;
  1930. snprintf(fname, sizeof(fname), "%s/AS/DB/eap_user.db", ctx->root_dir);
  1931. if (sqlite3_open(fname, &ctx->db)) {
  1932. printf("Failed to open sqlite database: %s\n",
  1933. sqlite3_errmsg(ctx->db));
  1934. sqlite3_close(ctx->db);
  1935. return -1;
  1936. }
  1937. return 0;
  1938. }
  1939. void hs20_spp_server_deinit(struct hs20_svc *ctx)
  1940. {
  1941. sqlite3_close(ctx->db);
  1942. ctx->db = NULL;
  1943. }