spp_server.c 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290
  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. db_add_session_devinfo(ctx, session_id, devinfo);
  1532. db_add_session_devdetail(ctx, session_id, devdetail);
  1533. ret = hs20_user_input_complete(ctx, user, realm, dmacc,
  1534. session_id);
  1535. hs20_eventlog_node(ctx, user, realm, session_id,
  1536. "user input completed response", ret);
  1537. goto out;
  1538. }
  1539. if (strcasecmp(req_reason, "Certificate enrollment completed") == 0) {
  1540. ret = hs20_cert_enroll_completed(ctx, user, realm, dmacc,
  1541. session_id);
  1542. hs20_eventlog_node(ctx, user, realm, session_id,
  1543. "certificate enrollment response", ret);
  1544. goto out;
  1545. }
  1546. if (strcasecmp(req_reason, "Certificate enrollment failed") == 0) {
  1547. ret = hs20_cert_enroll_failed(ctx, user, realm, dmacc,
  1548. session_id);
  1549. hs20_eventlog_node(ctx, user, realm, session_id,
  1550. "certificate enrollment failed response",
  1551. ret);
  1552. goto out;
  1553. }
  1554. debug_print(ctx, 1, "Unsupported requestReason '%s' user '%s'",
  1555. req_reason, user);
  1556. out:
  1557. xml_node_get_attr_value_free(ctx->xml, req_reason_buf);
  1558. xml_node_get_attr_value_free(ctx->xml, redirect_uri);
  1559. if (devinfo)
  1560. xml_node_free(ctx->xml, devinfo);
  1561. if (devdetail)
  1562. xml_node_free(ctx->xml, devdetail);
  1563. return ret;
  1564. }
  1565. static xml_node_t * build_spp_exchange_complete(struct hs20_svc *ctx,
  1566. const char *session_id,
  1567. const char *status,
  1568. const char *error_code)
  1569. {
  1570. xml_namespace_t *ns;
  1571. xml_node_t *spp_node, *node;
  1572. spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns,
  1573. "sppExchangeComplete");
  1574. xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0");
  1575. xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id);
  1576. xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status);
  1577. if (error_code) {
  1578. node = xml_node_create(ctx->xml, spp_node, ns, "sppError");
  1579. xml_node_add_attr(ctx->xml, node, NULL, "errorCode",
  1580. error_code);
  1581. }
  1582. return spp_node;
  1583. }
  1584. static int add_subscription(struct hs20_svc *ctx, const char *session_id)
  1585. {
  1586. char *user, *realm, *pw, *pw_mm, *pps, *str;
  1587. char *sql;
  1588. int ret = -1;
  1589. char *free_account;
  1590. int free_acc;
  1591. char *type;
  1592. int cert = 0;
  1593. char *cert_pem, *fingerprint;
  1594. user = db_get_session_val(ctx, NULL, NULL, session_id, "user");
  1595. realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm");
  1596. pw = db_get_session_val(ctx, NULL, NULL, session_id, "password");
  1597. pw_mm = db_get_session_val(ctx, NULL, NULL, session_id,
  1598. "machine_managed");
  1599. pps = db_get_session_val(ctx, NULL, NULL, session_id, "pps");
  1600. cert_pem = db_get_session_val(ctx, NULL, NULL, session_id, "cert_pem");
  1601. fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert");
  1602. type = db_get_session_val(ctx, NULL, NULL, session_id, "type");
  1603. if (type && strcmp(type, "cert") == 0)
  1604. cert = 1;
  1605. free(type);
  1606. if (!user || !realm || !pw) {
  1607. debug_print(ctx, 1, "Could not find session info from DB for "
  1608. "the new subscription");
  1609. goto out;
  1610. }
  1611. free_account = db_get_osu_config_val(ctx, realm, "free_account");
  1612. free_acc = free_account && strcmp(free_account, user) == 0;
  1613. free(free_account);
  1614. debug_print(ctx, 1,
  1615. "New subscription: user='%s' realm='%s' free_acc=%d",
  1616. user, realm, free_acc);
  1617. debug_print(ctx, 1, "New subscription: pps='%s'", pps);
  1618. sql = sqlite3_mprintf("UPDATE eventlog SET user=%Q, realm=%Q WHERE "
  1619. "sessionid=%Q AND (user='' OR user IS NULL)",
  1620. user, realm, session_id);
  1621. if (sql) {
  1622. debug_print(ctx, 1, "DB: %s", sql);
  1623. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  1624. debug_print(ctx, 1, "Failed to update eventlog in "
  1625. "sqlite database: %s",
  1626. sqlite3_errmsg(ctx->db));
  1627. }
  1628. sqlite3_free(sql);
  1629. }
  1630. if (free_acc) {
  1631. hs20_eventlog(ctx, user, realm, session_id,
  1632. "completed shared free account registration",
  1633. NULL);
  1634. ret = 0;
  1635. goto out;
  1636. }
  1637. sql = sqlite3_mprintf("INSERT INTO users(identity,realm,phase2,"
  1638. "methods,cert,cert_pem,machine_managed) VALUES "
  1639. "(%Q,%Q,1,%Q,%Q,%Q,%d)",
  1640. user, realm, cert ? "TLS" : "TTLS-MSCHAPV2",
  1641. fingerprint ? fingerprint : "",
  1642. cert_pem ? cert_pem : "",
  1643. pw_mm && atoi(pw_mm) ? 1 : 0);
  1644. if (sql == NULL)
  1645. goto out;
  1646. debug_print(ctx, 1, "DB: %s", sql);
  1647. if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) {
  1648. debug_print(ctx, 1, "Failed to add user in sqlite database: %s",
  1649. sqlite3_errmsg(ctx->db));
  1650. sqlite3_free(sql);
  1651. goto out;
  1652. }
  1653. sqlite3_free(sql);
  1654. if (cert)
  1655. ret = 0;
  1656. else
  1657. ret = update_password(ctx, user, realm, pw, 0);
  1658. if (ret < 0) {
  1659. sql = sqlite3_mprintf("DELETE FROM users WHERE identity=%Q AND "
  1660. "realm=%Q AND phase2=1",
  1661. user, realm);
  1662. if (sql) {
  1663. debug_print(ctx, 1, "DB: %s", sql);
  1664. sqlite3_exec(ctx->db, sql, NULL, NULL, NULL);
  1665. sqlite3_free(sql);
  1666. }
  1667. }
  1668. if (pps)
  1669. db_update_mo_str(ctx, user, realm, "pps", pps);
  1670. str = db_get_session_val(ctx, NULL, NULL, session_id, "devinfo");
  1671. if (str) {
  1672. db_update_mo_str(ctx, user, realm, "devinfo", str);
  1673. free(str);
  1674. }
  1675. str = db_get_session_val(ctx, NULL, NULL, session_id, "devdetail");
  1676. if (str) {
  1677. db_update_mo_str(ctx, user, realm, "devdetail", str);
  1678. free(str);
  1679. }
  1680. if (ret == 0) {
  1681. hs20_eventlog(ctx, user, realm, session_id,
  1682. "completed subscription registration", NULL);
  1683. }
  1684. out:
  1685. free(user);
  1686. free(realm);
  1687. free(pw);
  1688. free(pw_mm);
  1689. free(pps);
  1690. free(cert_pem);
  1691. free(fingerprint);
  1692. return ret;
  1693. }
  1694. static xml_node_t * hs20_spp_update_response(struct hs20_svc *ctx,
  1695. xml_node_t *node,
  1696. const char *user,
  1697. const char *realm,
  1698. const char *session_id,
  1699. int dmacc)
  1700. {
  1701. char *status;
  1702. xml_node_t *ret;
  1703. char *val;
  1704. enum hs20_session_operation oper;
  1705. status = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI,
  1706. "sppStatus");
  1707. if (status == NULL) {
  1708. debug_print(ctx, 1, "No sppStatus attribute");
  1709. return NULL;
  1710. }
  1711. debug_print(ctx, 1, "sppUpdateResponse: sppStatus: %s sessionID: %s",
  1712. status, session_id);
  1713. val = db_get_session_val(ctx, user, realm, session_id, "operation");
  1714. if (!val) {
  1715. debug_print(ctx, 1,
  1716. "No session active for user: %s sessionID: %s",
  1717. user, session_id);
  1718. oper = NO_OPERATION;
  1719. } else
  1720. oper = atoi(val);
  1721. if (strcasecmp(status, "OK") == 0) {
  1722. char *new_pw = NULL;
  1723. xml_node_get_attr_value_free(ctx->xml, status);
  1724. if (oper == USER_REMEDIATION) {
  1725. new_pw = db_get_session_val(ctx, user, realm,
  1726. session_id, "password");
  1727. if (new_pw == NULL || strlen(new_pw) == 0) {
  1728. free(new_pw);
  1729. ret = build_spp_exchange_complete(
  1730. ctx, session_id, "Error occurred",
  1731. "Other");
  1732. hs20_eventlog_node(ctx, user, realm,
  1733. session_id, "No password "
  1734. "had been assigned for "
  1735. "session", ret);
  1736. db_remove_session(ctx, user, realm, session_id);
  1737. return ret;
  1738. }
  1739. oper = UPDATE_PASSWORD;
  1740. }
  1741. if (oper == UPDATE_PASSWORD) {
  1742. if (!new_pw) {
  1743. new_pw = db_get_session_val(ctx, user, realm,
  1744. session_id,
  1745. "password");
  1746. if (!new_pw) {
  1747. db_remove_session(ctx, user, realm,
  1748. session_id);
  1749. return NULL;
  1750. }
  1751. }
  1752. debug_print(ctx, 1, "Update user '%s' password in DB",
  1753. user);
  1754. if (update_password(ctx, user, realm, new_pw, dmacc) <
  1755. 0) {
  1756. debug_print(ctx, 1, "Failed to update user "
  1757. "'%s' password in DB", user);
  1758. ret = build_spp_exchange_complete(
  1759. ctx, session_id, "Error occurred",
  1760. "Other");
  1761. hs20_eventlog_node(ctx, user, realm,
  1762. session_id, "Failed to "
  1763. "update database", ret);
  1764. db_remove_session(ctx, user, realm, session_id);
  1765. return ret;
  1766. }
  1767. hs20_eventlog(ctx, user, realm,
  1768. session_id, "Updated user password "
  1769. "in database", NULL);
  1770. }
  1771. if (oper == SUBSCRIPTION_REGISTRATION) {
  1772. if (add_subscription(ctx, session_id) < 0) {
  1773. debug_print(ctx, 1, "Failed to add "
  1774. "subscription into DB");
  1775. ret = build_spp_exchange_complete(
  1776. ctx, session_id, "Error occurred",
  1777. "Other");
  1778. hs20_eventlog_node(ctx, user, realm,
  1779. session_id, "Failed to "
  1780. "update database", ret);
  1781. db_remove_session(ctx, user, realm, session_id);
  1782. return ret;
  1783. }
  1784. }
  1785. if (oper == POLICY_REMEDIATION || oper == POLICY_UPDATE) {
  1786. char *val;
  1787. val = db_get_val(ctx, user, realm, "remediation",
  1788. dmacc);
  1789. if (val && strcmp(val, "policy") == 0)
  1790. db_update_val(ctx, user, realm, "remediation",
  1791. "", dmacc);
  1792. free(val);
  1793. }
  1794. ret = build_spp_exchange_complete(
  1795. ctx, session_id,
  1796. "Exchange complete, release TLS connection", NULL);
  1797. hs20_eventlog_node(ctx, user, realm, session_id,
  1798. "Exchange completed", ret);
  1799. db_remove_session(ctx, user, realm, session_id);
  1800. return ret;
  1801. }
  1802. ret = build_spp_exchange_complete(ctx, session_id, "Error occurred",
  1803. "Other");
  1804. hs20_eventlog_node(ctx, user, realm, session_id, "Error occurred", ret);
  1805. db_remove_session(ctx, user, realm, session_id);
  1806. xml_node_get_attr_value_free(ctx->xml, status);
  1807. return ret;
  1808. }
  1809. #define SPP_SESSION_ID_LEN 16
  1810. static char * gen_spp_session_id(void)
  1811. {
  1812. FILE *f;
  1813. int i;
  1814. char *session;
  1815. session = os_malloc(SPP_SESSION_ID_LEN * 2 + 1);
  1816. if (session == NULL)
  1817. return NULL;
  1818. f = fopen("/dev/urandom", "r");
  1819. if (f == NULL) {
  1820. os_free(session);
  1821. return NULL;
  1822. }
  1823. for (i = 0; i < SPP_SESSION_ID_LEN; i++)
  1824. os_snprintf(session + i * 2, 3, "%02x", fgetc(f));
  1825. fclose(f);
  1826. return session;
  1827. }
  1828. xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node,
  1829. const char *auth_user,
  1830. const char *auth_realm, int dmacc)
  1831. {
  1832. xml_node_t *ret = NULL;
  1833. char *session_id;
  1834. const char *op_name;
  1835. char *xml_err;
  1836. char fname[200];
  1837. debug_dump_node(ctx, "received request", node);
  1838. if (!dmacc && auth_user && auth_realm) {
  1839. char *real;
  1840. real = db_get_val(ctx, auth_user, auth_realm, "identity", 0);
  1841. if (!real) {
  1842. real = db_get_val(ctx, auth_user, auth_realm,
  1843. "identity", 1);
  1844. if (real)
  1845. dmacc = 1;
  1846. }
  1847. os_free(real);
  1848. }
  1849. snprintf(fname, sizeof(fname), "%s/spp/spp.xsd", ctx->root_dir);
  1850. if (xml_validate(ctx->xml, node, fname, &xml_err) < 0) {
  1851. /*
  1852. * We may not be able to extract the sessionID from invalid
  1853. * input, but well, we can try.
  1854. */
  1855. session_id = xml_node_get_attr_value_ns(ctx->xml, node,
  1856. SPP_NS_URI,
  1857. "sessionID");
  1858. debug_print(ctx, 1,
  1859. "SPP message failed validation, xsd file: %s xml-error: %s",
  1860. fname, xml_err);
  1861. hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
  1862. "SPP message failed validation", node);
  1863. hs20_eventlog(ctx, auth_user, auth_realm, session_id,
  1864. "Validation errors", xml_err);
  1865. os_free(xml_err);
  1866. xml_node_get_attr_value_free(ctx->xml, session_id);
  1867. /* TODO: what to return here? */
  1868. ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
  1869. "SppValidationError");
  1870. return ret;
  1871. }
  1872. session_id = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI,
  1873. "sessionID");
  1874. if (session_id) {
  1875. char *tmp;
  1876. debug_print(ctx, 1, "Received sessionID %s", session_id);
  1877. tmp = os_strdup(session_id);
  1878. xml_node_get_attr_value_free(ctx->xml, session_id);
  1879. if (tmp == NULL)
  1880. return NULL;
  1881. session_id = tmp;
  1882. } else {
  1883. session_id = gen_spp_session_id();
  1884. if (session_id == NULL) {
  1885. debug_print(ctx, 1, "Failed to generate sessionID");
  1886. return NULL;
  1887. }
  1888. debug_print(ctx, 1, "Generated sessionID %s", session_id);
  1889. }
  1890. op_name = xml_node_get_localname(ctx->xml, node);
  1891. if (op_name == NULL) {
  1892. debug_print(ctx, 1, "Could not get op_name");
  1893. return NULL;
  1894. }
  1895. if (strcmp(op_name, "sppPostDevData") == 0) {
  1896. hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
  1897. "sppPostDevData received and validated",
  1898. node);
  1899. ret = hs20_spp_post_dev_data(ctx, node, auth_user, auth_realm,
  1900. session_id, dmacc);
  1901. } else if (strcmp(op_name, "sppUpdateResponse") == 0) {
  1902. hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
  1903. "sppUpdateResponse received and validated",
  1904. node);
  1905. ret = hs20_spp_update_response(ctx, node, auth_user,
  1906. auth_realm, session_id, dmacc);
  1907. } else {
  1908. hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
  1909. "Unsupported SPP message received and "
  1910. "validated", node);
  1911. debug_print(ctx, 1, "Unsupported operation '%s'", op_name);
  1912. /* TODO: what to return here? */
  1913. ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
  1914. "SppUnknownCommandError");
  1915. }
  1916. os_free(session_id);
  1917. if (ret == NULL) {
  1918. /* TODO: what to return here? */
  1919. ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
  1920. "SppInternalError");
  1921. }
  1922. return ret;
  1923. }
  1924. int hs20_spp_server_init(struct hs20_svc *ctx)
  1925. {
  1926. char fname[200];
  1927. ctx->db = NULL;
  1928. snprintf(fname, sizeof(fname), "%s/AS/DB/eap_user.db", ctx->root_dir);
  1929. if (sqlite3_open(fname, &ctx->db)) {
  1930. printf("Failed to open sqlite database: %s\n",
  1931. sqlite3_errmsg(ctx->db));
  1932. sqlite3_close(ctx->db);
  1933. return -1;
  1934. }
  1935. return 0;
  1936. }
  1937. void hs20_spp_server_deinit(struct hs20_svc *ctx)
  1938. {
  1939. sqlite3_close(ctx->db);
  1940. ctx->db = NULL;
  1941. }