spp_server.c 59 KB

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