15b9c547cSRui Paulo /*
25b9c547cSRui Paulo * Hotspot 2.0 - OMA DM client
35b9c547cSRui Paulo * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
45b9c547cSRui Paulo *
55b9c547cSRui Paulo * This software may be distributed under the terms of the BSD license.
65b9c547cSRui Paulo * See README for more details.
75b9c547cSRui Paulo */
85b9c547cSRui Paulo
95b9c547cSRui Paulo #include "includes.h"
105b9c547cSRui Paulo
115b9c547cSRui Paulo #include "common.h"
125b9c547cSRui Paulo #include "wpa_helpers.h"
135b9c547cSRui Paulo #include "xml-utils.h"
145b9c547cSRui Paulo #include "http-utils.h"
155b9c547cSRui Paulo #include "utils/browser.h"
165b9c547cSRui Paulo #include "osu_client.h"
175b9c547cSRui Paulo
185b9c547cSRui Paulo
195b9c547cSRui Paulo #define DM_SERVER_INITIATED_MGMT 1200
205b9c547cSRui Paulo #define DM_CLIENT_INITIATED_MGMT 1201
215b9c547cSRui Paulo #define DM_GENERIC_ALERT 1226
225b9c547cSRui Paulo
235b9c547cSRui Paulo /* OMA-TS-SyncML-RepPro-V1_2_2 - 10. Response Status Codes */
245b9c547cSRui Paulo #define DM_RESP_OK 200
255b9c547cSRui Paulo #define DM_RESP_AUTH_ACCEPTED 212
265b9c547cSRui Paulo #define DM_RESP_CHUNKED_ITEM_ACCEPTED 213
275b9c547cSRui Paulo #define DM_RESP_NOT_EXECUTED 215
285b9c547cSRui Paulo #define DM_RESP_ATOMIC_ROLL_BACK_OK 216
295b9c547cSRui Paulo #define DM_RESP_NOT_MODIFIED 304
305b9c547cSRui Paulo #define DM_RESP_BAD_REQUEST 400
315b9c547cSRui Paulo #define DM_RESP_UNAUTHORIZED 401
325b9c547cSRui Paulo #define DM_RESP_FORBIDDEN 403
335b9c547cSRui Paulo #define DM_RESP_NOT_FOUND 404
345b9c547cSRui Paulo #define DM_RESP_COMMAND_NOT_ALLOWED 405
355b9c547cSRui Paulo #define DM_RESP_OPTIONAL_FEATURE_NOT_SUPPORTED 406
365b9c547cSRui Paulo #define DM_RESP_MISSING_CREDENTIALS 407
375b9c547cSRui Paulo #define DM_RESP_CONFLICT 409
385b9c547cSRui Paulo #define DM_RESP_GONE 410
395b9c547cSRui Paulo #define DM_RESP_INCOMPLETE_COMMAND 412
405b9c547cSRui Paulo #define DM_RESP_REQ_ENTITY_TOO_LARGE 413
415b9c547cSRui Paulo #define DM_RESP_URI_TOO_LONG 414
425b9c547cSRui Paulo #define DM_RESP_UNSUPPORTED_MEDIA_TYPE_OR_FORMAT 415
435b9c547cSRui Paulo #define DM_RESP_REQ_TOO_BIG 416
445b9c547cSRui Paulo #define DM_RESP_ALREADY_EXISTS 418
455b9c547cSRui Paulo #define DM_RESP_DEVICE_FULL 420
465b9c547cSRui Paulo #define DM_RESP_SIZE_MISMATCH 424
475b9c547cSRui Paulo #define DM_RESP_PERMISSION_DENIED 425
485b9c547cSRui Paulo #define DM_RESP_COMMAND_FAILED 500
495b9c547cSRui Paulo #define DM_RESP_COMMAND_NOT_IMPLEMENTED 501
505b9c547cSRui Paulo #define DM_RESP_ATOMIC_ROLL_BACK_FAILED 516
515b9c547cSRui Paulo
525b9c547cSRui Paulo #define DM_HS20_SUBSCRIPTION_CREATION \
535b9c547cSRui Paulo "org.wi-fi.hotspot2dot0.SubscriptionCreation"
545b9c547cSRui Paulo #define DM_HS20_SUBSCRIPTION_PROVISIONING \
555b9c547cSRui Paulo "org.wi-fi.hotspot2dot0.SubscriptionProvisioning"
565b9c547cSRui Paulo #define DM_HS20_SUBSCRIPTION_REMEDIATION \
575b9c547cSRui Paulo "org.wi-fi.hotspot2dot0.SubscriptionRemediation"
585b9c547cSRui Paulo #define DM_HS20_POLICY_UPDATE \
595b9c547cSRui Paulo "org.wi-fi.hotspot2dot0.PolicyUpdate"
605b9c547cSRui Paulo
615b9c547cSRui Paulo #define DM_URI_PPS "./Wi-Fi/org.wi-fi/PerProviderSubscription"
625b9c547cSRui Paulo #define DM_URI_LAUNCH_BROWSER \
635b9c547cSRui Paulo "./DevDetail/Ext/org.wi-fi/Wi-Fi/Ops/launchBrowserToURI"
645b9c547cSRui Paulo
655b9c547cSRui Paulo
665b9c547cSRui Paulo static void add_item(struct hs20_osu_client *ctx, xml_node_t *parent,
675b9c547cSRui Paulo const char *locuri, const char *data);
685b9c547cSRui Paulo
695b9c547cSRui Paulo
int2str(int val)705b9c547cSRui Paulo static const char * int2str(int val)
715b9c547cSRui Paulo {
725b9c547cSRui Paulo static char buf[20];
735b9c547cSRui Paulo snprintf(buf, sizeof(buf), "%d", val);
745b9c547cSRui Paulo return buf;
755b9c547cSRui Paulo }
765b9c547cSRui Paulo
775b9c547cSRui Paulo
oma_dm_get_target_locuri(struct hs20_osu_client * ctx,xml_node_t * node)785b9c547cSRui Paulo static char * oma_dm_get_target_locuri(struct hs20_osu_client *ctx,
795b9c547cSRui Paulo xml_node_t *node)
805b9c547cSRui Paulo {
815b9c547cSRui Paulo xml_node_t *locuri;
825b9c547cSRui Paulo char *uri, *ret = NULL;
835b9c547cSRui Paulo
845b9c547cSRui Paulo locuri = get_node(ctx->xml, node, "Item/Target/LocURI");
855b9c547cSRui Paulo if (locuri == NULL)
865b9c547cSRui Paulo return NULL;
875b9c547cSRui Paulo
885b9c547cSRui Paulo uri = xml_node_get_text(ctx->xml, locuri);
895b9c547cSRui Paulo if (uri)
905b9c547cSRui Paulo ret = os_strdup(uri);
915b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, uri);
925b9c547cSRui Paulo return ret;
935b9c547cSRui Paulo }
945b9c547cSRui Paulo
955b9c547cSRui Paulo
oma_dm_add_locuri(struct hs20_osu_client * ctx,xml_node_t * parent,const char * element,const char * uri)965b9c547cSRui Paulo static void oma_dm_add_locuri(struct hs20_osu_client *ctx, xml_node_t *parent,
975b9c547cSRui Paulo const char *element, const char *uri)
985b9c547cSRui Paulo {
995b9c547cSRui Paulo xml_node_t *node;
1005b9c547cSRui Paulo
1015b9c547cSRui Paulo node = xml_node_create(ctx->xml, parent, NULL, element);
1025b9c547cSRui Paulo if (node == NULL)
1035b9c547cSRui Paulo return;
1045b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "LocURI", uri);
1055b9c547cSRui Paulo }
1065b9c547cSRui Paulo
1075b9c547cSRui Paulo
oma_dm_build_hdr(struct hs20_osu_client * ctx,const char * url,int msgid)1085b9c547cSRui Paulo static xml_node_t * oma_dm_build_hdr(struct hs20_osu_client *ctx,
1095b9c547cSRui Paulo const char *url, int msgid)
1105b9c547cSRui Paulo {
1115b9c547cSRui Paulo xml_node_t *syncml, *synchdr;
1125b9c547cSRui Paulo xml_namespace_t *ns;
1135b9c547cSRui Paulo
11485732ac8SCy Schubert if (!ctx->devid) {
11585732ac8SCy Schubert wpa_printf(MSG_ERROR,
11685732ac8SCy Schubert "DevId from devinfo.xml is not available - cannot use OMA DM");
11785732ac8SCy Schubert return NULL;
11885732ac8SCy Schubert }
11985732ac8SCy Schubert
1205b9c547cSRui Paulo syncml = xml_node_create_root(ctx->xml, "SYNCML:SYNCML1.2", NULL, &ns,
1215b9c547cSRui Paulo "SyncML");
1225b9c547cSRui Paulo
1235b9c547cSRui Paulo synchdr = xml_node_create(ctx->xml, syncml, NULL, "SyncHdr");
1245b9c547cSRui Paulo xml_node_create_text(ctx->xml, synchdr, NULL, "VerDTD", "1.2");
1255b9c547cSRui Paulo xml_node_create_text(ctx->xml, synchdr, NULL, "VerProto", "DM/1.2");
1265b9c547cSRui Paulo xml_node_create_text(ctx->xml, synchdr, NULL, "SessionID", "1");
1275b9c547cSRui Paulo xml_node_create_text(ctx->xml, synchdr, NULL, "MsgID", int2str(msgid));
1285b9c547cSRui Paulo
1295b9c547cSRui Paulo oma_dm_add_locuri(ctx, synchdr, "Target", url);
1305b9c547cSRui Paulo oma_dm_add_locuri(ctx, synchdr, "Source", ctx->devid);
1315b9c547cSRui Paulo
1325b9c547cSRui Paulo return syncml;
1335b9c547cSRui Paulo }
1345b9c547cSRui Paulo
1355b9c547cSRui Paulo
oma_dm_add_cmdid(struct hs20_osu_client * ctx,xml_node_t * parent,int cmdid)1365b9c547cSRui Paulo static void oma_dm_add_cmdid(struct hs20_osu_client *ctx, xml_node_t *parent,
1375b9c547cSRui Paulo int cmdid)
1385b9c547cSRui Paulo {
1395b9c547cSRui Paulo xml_node_create_text(ctx->xml, parent, NULL, "CmdID", int2str(cmdid));
1405b9c547cSRui Paulo }
1415b9c547cSRui Paulo
1425b9c547cSRui Paulo
add_alert(struct hs20_osu_client * ctx,xml_node_t * parent,int cmdid,int data)1435b9c547cSRui Paulo static xml_node_t * add_alert(struct hs20_osu_client *ctx, xml_node_t *parent,
1445b9c547cSRui Paulo int cmdid, int data)
1455b9c547cSRui Paulo {
1465b9c547cSRui Paulo xml_node_t *node;
1475b9c547cSRui Paulo
1485b9c547cSRui Paulo node = xml_node_create(ctx->xml, parent, NULL, "Alert");
1495b9c547cSRui Paulo if (node == NULL)
1505b9c547cSRui Paulo return NULL;
1515b9c547cSRui Paulo oma_dm_add_cmdid(ctx, node, cmdid);
1525b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "Data", int2str(data));
1535b9c547cSRui Paulo
1545b9c547cSRui Paulo return node;
1555b9c547cSRui Paulo }
1565b9c547cSRui Paulo
1575b9c547cSRui Paulo
add_status(struct hs20_osu_client * ctx,xml_node_t * parent,int msgref,int cmdref,int cmdid,const char * cmd,int data,const char * targetref)1585b9c547cSRui Paulo static xml_node_t * add_status(struct hs20_osu_client *ctx, xml_node_t *parent,
1595b9c547cSRui Paulo int msgref, int cmdref, int cmdid,
1605b9c547cSRui Paulo const char *cmd, int data, const char *targetref)
1615b9c547cSRui Paulo {
1625b9c547cSRui Paulo xml_node_t *node;
1635b9c547cSRui Paulo
1645b9c547cSRui Paulo node = xml_node_create(ctx->xml, parent, NULL, "Status");
1655b9c547cSRui Paulo if (node == NULL)
1665b9c547cSRui Paulo return NULL;
1675b9c547cSRui Paulo oma_dm_add_cmdid(ctx, node, cmdid);
1685b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "MsgRef", int2str(msgref));
1695b9c547cSRui Paulo if (cmdref)
1705b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "CmdRef",
1715b9c547cSRui Paulo int2str(cmdref));
1725b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "Cmd", cmd);
1735b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "Data", int2str(data));
1745b9c547cSRui Paulo if (targetref) {
1755b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "TargetRef",
1765b9c547cSRui Paulo targetref);
1775b9c547cSRui Paulo }
1785b9c547cSRui Paulo
1795b9c547cSRui Paulo return node;
1805b9c547cSRui Paulo }
1815b9c547cSRui Paulo
1825b9c547cSRui Paulo
add_results(struct hs20_osu_client * ctx,xml_node_t * parent,int msgref,int cmdref,int cmdid,const char * locuri,const char * data)1835b9c547cSRui Paulo static xml_node_t * add_results(struct hs20_osu_client *ctx, xml_node_t *parent,
1845b9c547cSRui Paulo int msgref, int cmdref, int cmdid,
1855b9c547cSRui Paulo const char *locuri, const char *data)
1865b9c547cSRui Paulo {
1875b9c547cSRui Paulo xml_node_t *node;
1885b9c547cSRui Paulo
1895b9c547cSRui Paulo node = xml_node_create(ctx->xml, parent, NULL, "Results");
1905b9c547cSRui Paulo if (node == NULL)
1915b9c547cSRui Paulo return NULL;
1925b9c547cSRui Paulo
1935b9c547cSRui Paulo oma_dm_add_cmdid(ctx, node, cmdid);
1945b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "MsgRef", int2str(msgref));
1955b9c547cSRui Paulo xml_node_create_text(ctx->xml, node, NULL, "CmdRef", int2str(cmdref));
1965b9c547cSRui Paulo add_item(ctx, node, locuri, data);
1975b9c547cSRui Paulo
1985b9c547cSRui Paulo return node;
1995b9c547cSRui Paulo }
2005b9c547cSRui Paulo
2015b9c547cSRui Paulo
mo_str(struct hs20_osu_client * ctx,const char * urn,const char * fname)2025b9c547cSRui Paulo static char * mo_str(struct hs20_osu_client *ctx, const char *urn,
2035b9c547cSRui Paulo const char *fname)
2045b9c547cSRui Paulo {
2055b9c547cSRui Paulo xml_node_t *fnode, *tnds;
2065b9c547cSRui Paulo char *str;
2075b9c547cSRui Paulo
2085b9c547cSRui Paulo fnode = node_from_file(ctx->xml, fname);
2095b9c547cSRui Paulo if (!fnode)
2105b9c547cSRui Paulo return NULL;
2115b9c547cSRui Paulo tnds = mo_to_tnds(ctx->xml, fnode, 0, urn, "syncml:dmddf1.2");
2125b9c547cSRui Paulo xml_node_free(ctx->xml, fnode);
2135b9c547cSRui Paulo if (!tnds)
2145b9c547cSRui Paulo return NULL;
2155b9c547cSRui Paulo
2165b9c547cSRui Paulo str = xml_node_to_str(ctx->xml, tnds);
2175b9c547cSRui Paulo xml_node_free(ctx->xml, tnds);
2185b9c547cSRui Paulo if (str == NULL)
2195b9c547cSRui Paulo return NULL;
2205b9c547cSRui Paulo wpa_printf(MSG_INFO, "MgmtTree: %s", str);
2215b9c547cSRui Paulo
2225b9c547cSRui Paulo return str;
2235b9c547cSRui Paulo }
2245b9c547cSRui Paulo
2255b9c547cSRui Paulo
add_item(struct hs20_osu_client * ctx,xml_node_t * parent,const char * locuri,const char * data)2265b9c547cSRui Paulo static void add_item(struct hs20_osu_client *ctx, xml_node_t *parent,
2275b9c547cSRui Paulo const char *locuri, const char *data)
2285b9c547cSRui Paulo {
2295b9c547cSRui Paulo xml_node_t *item, *node;
2305b9c547cSRui Paulo
2315b9c547cSRui Paulo item = xml_node_create(ctx->xml, parent, NULL, "Item");
2325b9c547cSRui Paulo oma_dm_add_locuri(ctx, item, "Source", locuri);
2335b9c547cSRui Paulo node = xml_node_create(ctx->xml, item, NULL, "Meta");
2345b9c547cSRui Paulo xml_node_create_text_ns(ctx->xml, node, "syncml:metinf", "Format",
2355b9c547cSRui Paulo "Chr");
2365b9c547cSRui Paulo xml_node_create_text_ns(ctx->xml, node, "syncml:metinf", "Type",
2375b9c547cSRui Paulo "text/plain");
2385b9c547cSRui Paulo xml_node_create_text(ctx->xml, item, NULL, "Data", data);
2395b9c547cSRui Paulo }
2405b9c547cSRui Paulo
2415b9c547cSRui Paulo
add_replace_devinfo(struct hs20_osu_client * ctx,xml_node_t * parent,int cmdid)2425b9c547cSRui Paulo static void add_replace_devinfo(struct hs20_osu_client *ctx, xml_node_t *parent,
2435b9c547cSRui Paulo int cmdid)
2445b9c547cSRui Paulo {
2455b9c547cSRui Paulo xml_node_t *info, *child, *replace;
2465b9c547cSRui Paulo const char *name;
2475b9c547cSRui Paulo char locuri[200], *txt;
2485b9c547cSRui Paulo
2495b9c547cSRui Paulo info = node_from_file(ctx->xml, "devinfo.xml");
2505b9c547cSRui Paulo if (info == NULL) {
2515b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not read devinfo.xml");
2525b9c547cSRui Paulo return;
2535b9c547cSRui Paulo }
2545b9c547cSRui Paulo
2555b9c547cSRui Paulo replace = xml_node_create(ctx->xml, parent, NULL, "Replace");
2565b9c547cSRui Paulo if (replace == NULL) {
2575b9c547cSRui Paulo xml_node_free(ctx->xml, info);
2585b9c547cSRui Paulo return;
2595b9c547cSRui Paulo }
2605b9c547cSRui Paulo oma_dm_add_cmdid(ctx, replace, cmdid);
2615b9c547cSRui Paulo
2625b9c547cSRui Paulo xml_node_for_each_child(ctx->xml, child, info) {
2635b9c547cSRui Paulo xml_node_for_each_check(ctx->xml, child);
2645b9c547cSRui Paulo name = xml_node_get_localname(ctx->xml, child);
2655b9c547cSRui Paulo os_snprintf(locuri, sizeof(locuri), "./DevInfo/%s", name);
2665b9c547cSRui Paulo txt = xml_node_get_text(ctx->xml, child);
2675b9c547cSRui Paulo if (txt) {
2685b9c547cSRui Paulo add_item(ctx, replace, locuri, txt);
2695b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, txt);
2705b9c547cSRui Paulo }
2715b9c547cSRui Paulo }
2725b9c547cSRui Paulo
2735b9c547cSRui Paulo xml_node_free(ctx->xml, info);
2745b9c547cSRui Paulo }
2755b9c547cSRui Paulo
2765b9c547cSRui Paulo
oma_dm_add_hs20_generic_alert(struct hs20_osu_client * ctx,xml_node_t * syncbody,int cmdid,const char * oper,const char * data)2775b9c547cSRui Paulo static void oma_dm_add_hs20_generic_alert(struct hs20_osu_client *ctx,
2785b9c547cSRui Paulo xml_node_t *syncbody,
2795b9c547cSRui Paulo int cmdid, const char *oper,
2805b9c547cSRui Paulo const char *data)
2815b9c547cSRui Paulo {
2825b9c547cSRui Paulo xml_node_t *node, *item;
2835b9c547cSRui Paulo char buf[200];
2845b9c547cSRui Paulo
2855b9c547cSRui Paulo node = add_alert(ctx, syncbody, cmdid, DM_GENERIC_ALERT);
2865b9c547cSRui Paulo
2875b9c547cSRui Paulo item = xml_node_create(ctx->xml, node, NULL, "Item");
2885b9c547cSRui Paulo oma_dm_add_locuri(ctx, item, "Source", DM_URI_PPS);
2895b9c547cSRui Paulo node = xml_node_create(ctx->xml, item, NULL, "Meta");
2905b9c547cSRui Paulo snprintf(buf, sizeof(buf), "Reversed-Domain-Name: %s", oper);
2915b9c547cSRui Paulo xml_node_create_text_ns(ctx->xml, node, "syncml:metinf", "Type", buf);
2925b9c547cSRui Paulo xml_node_create_text_ns(ctx->xml, node, "syncml:metinf", "Format",
2935b9c547cSRui Paulo "xml");
2945b9c547cSRui Paulo xml_node_create_text(ctx->xml, item, NULL, "Data", data);
2955b9c547cSRui Paulo }
2965b9c547cSRui Paulo
2975b9c547cSRui Paulo
build_oma_dm_1(struct hs20_osu_client * ctx,const char * url,int msgid,const char * oper)2985b9c547cSRui Paulo static xml_node_t * build_oma_dm_1(struct hs20_osu_client *ctx,
2995b9c547cSRui Paulo const char *url, int msgid, const char *oper)
3005b9c547cSRui Paulo {
3015b9c547cSRui Paulo xml_node_t *syncml, *syncbody;
3025b9c547cSRui Paulo char *str;
3035b9c547cSRui Paulo int cmdid = 0;
3045b9c547cSRui Paulo
3055b9c547cSRui Paulo syncml = oma_dm_build_hdr(ctx, url, msgid);
3065b9c547cSRui Paulo if (syncml == NULL)
3075b9c547cSRui Paulo return NULL;
3085b9c547cSRui Paulo
3095b9c547cSRui Paulo syncbody = xml_node_create(ctx->xml, syncml, NULL, "SyncBody");
3105b9c547cSRui Paulo if (syncbody == NULL) {
3115b9c547cSRui Paulo xml_node_free(ctx->xml, syncml);
3125b9c547cSRui Paulo return NULL;
3135b9c547cSRui Paulo }
3145b9c547cSRui Paulo
3155b9c547cSRui Paulo cmdid++;
3165b9c547cSRui Paulo add_alert(ctx, syncbody, cmdid, DM_CLIENT_INITIATED_MGMT);
3175b9c547cSRui Paulo
3185b9c547cSRui Paulo str = mo_str(ctx, NULL, "devdetail.xml");
3195b9c547cSRui Paulo if (str == NULL) {
3205b9c547cSRui Paulo xml_node_free(ctx->xml, syncml);
3215b9c547cSRui Paulo return NULL;
3225b9c547cSRui Paulo }
3235b9c547cSRui Paulo cmdid++;
3245b9c547cSRui Paulo oma_dm_add_hs20_generic_alert(ctx, syncbody, cmdid, oper, str);
3255b9c547cSRui Paulo os_free(str);
3265b9c547cSRui Paulo
3275b9c547cSRui Paulo cmdid++;
3285b9c547cSRui Paulo add_replace_devinfo(ctx, syncbody, cmdid);
3295b9c547cSRui Paulo
3305b9c547cSRui Paulo xml_node_create(ctx->xml, syncbody, NULL, "Final");
3315b9c547cSRui Paulo
3325b9c547cSRui Paulo return syncml;
3335b9c547cSRui Paulo }
3345b9c547cSRui Paulo
3355b9c547cSRui Paulo
build_oma_dm_1_sub_reg(struct hs20_osu_client * ctx,const char * url,int msgid)3365b9c547cSRui Paulo static xml_node_t * build_oma_dm_1_sub_reg(struct hs20_osu_client *ctx,
3375b9c547cSRui Paulo const char *url, int msgid)
3385b9c547cSRui Paulo {
3395b9c547cSRui Paulo xml_node_t *syncml;
3405b9c547cSRui Paulo
3415b9c547cSRui Paulo syncml = build_oma_dm_1(ctx, url, msgid, DM_HS20_SUBSCRIPTION_CREATION);
3425b9c547cSRui Paulo if (syncml)
3435b9c547cSRui Paulo debug_dump_node(ctx, "OMA-DM Package 1 (sub reg)", syncml);
3445b9c547cSRui Paulo
3455b9c547cSRui Paulo return syncml;
3465b9c547cSRui Paulo }
3475b9c547cSRui Paulo
3485b9c547cSRui Paulo
build_oma_dm_1_sub_prov(struct hs20_osu_client * ctx,const char * url,int msgid)3495b9c547cSRui Paulo static xml_node_t * build_oma_dm_1_sub_prov(struct hs20_osu_client *ctx,
3505b9c547cSRui Paulo const char *url, int msgid)
3515b9c547cSRui Paulo {
3525b9c547cSRui Paulo xml_node_t *syncml;
3535b9c547cSRui Paulo
3545b9c547cSRui Paulo syncml = build_oma_dm_1(ctx, url, msgid,
3555b9c547cSRui Paulo DM_HS20_SUBSCRIPTION_PROVISIONING);
3565b9c547cSRui Paulo if (syncml)
3575b9c547cSRui Paulo debug_dump_node(ctx, "OMA-DM Package 1 (sub prov)", syncml);
3585b9c547cSRui Paulo
3595b9c547cSRui Paulo return syncml;
3605b9c547cSRui Paulo }
3615b9c547cSRui Paulo
3625b9c547cSRui Paulo
build_oma_dm_1_pol_upd(struct hs20_osu_client * ctx,const char * url,int msgid)3635b9c547cSRui Paulo static xml_node_t * build_oma_dm_1_pol_upd(struct hs20_osu_client *ctx,
3645b9c547cSRui Paulo const char *url, int msgid)
3655b9c547cSRui Paulo {
3665b9c547cSRui Paulo xml_node_t *syncml;
3675b9c547cSRui Paulo
3685b9c547cSRui Paulo syncml = build_oma_dm_1(ctx, url, msgid, DM_HS20_POLICY_UPDATE);
3695b9c547cSRui Paulo if (syncml)
3705b9c547cSRui Paulo debug_dump_node(ctx, "OMA-DM Package 1 (pol upd)", syncml);
3715b9c547cSRui Paulo
3725b9c547cSRui Paulo return syncml;
3735b9c547cSRui Paulo }
3745b9c547cSRui Paulo
3755b9c547cSRui Paulo
build_oma_dm_1_sub_rem(struct hs20_osu_client * ctx,const char * url,int msgid)3765b9c547cSRui Paulo static xml_node_t * build_oma_dm_1_sub_rem(struct hs20_osu_client *ctx,
3775b9c547cSRui Paulo const char *url, int msgid)
3785b9c547cSRui Paulo {
3795b9c547cSRui Paulo xml_node_t *syncml;
3805b9c547cSRui Paulo
3815b9c547cSRui Paulo syncml = build_oma_dm_1(ctx, url, msgid,
3825b9c547cSRui Paulo DM_HS20_SUBSCRIPTION_REMEDIATION);
3835b9c547cSRui Paulo if (syncml)
3845b9c547cSRui Paulo debug_dump_node(ctx, "OMA-DM Package 1 (sub rem)", syncml);
3855b9c547cSRui Paulo
3865b9c547cSRui Paulo return syncml;
3875b9c547cSRui Paulo }
3885b9c547cSRui Paulo
3895b9c547cSRui Paulo
oma_dm_exec_browser(struct hs20_osu_client * ctx,xml_node_t * exec)3905b9c547cSRui Paulo static int oma_dm_exec_browser(struct hs20_osu_client *ctx, xml_node_t *exec)
3915b9c547cSRui Paulo {
3925b9c547cSRui Paulo xml_node_t *node;
3935b9c547cSRui Paulo char *data;
3945b9c547cSRui Paulo int res;
3955b9c547cSRui Paulo
3965b9c547cSRui Paulo node = get_node(ctx->xml, exec, "Item/Data");
3975b9c547cSRui Paulo if (node == NULL) {
3985b9c547cSRui Paulo wpa_printf(MSG_INFO, "No Data node found");
3995b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
4005b9c547cSRui Paulo }
4015b9c547cSRui Paulo
4025b9c547cSRui Paulo data = xml_node_get_text(ctx->xml, node);
4035b9c547cSRui Paulo if (data == NULL) {
4045b9c547cSRui Paulo wpa_printf(MSG_INFO, "Invalid data");
4055b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
4065b9c547cSRui Paulo }
4075b9c547cSRui Paulo wpa_printf(MSG_INFO, "Data: %s", data);
4085b9c547cSRui Paulo wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data);
4095b9c547cSRui Paulo write_summary(ctx, "Launch browser to URI '%s'", data);
410*c1d255d3SCy Schubert res = hs20_web_browser(data, 1);
4115b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, data);
4125b9c547cSRui Paulo if (res > 0) {
4135b9c547cSRui Paulo wpa_printf(MSG_INFO, "User response in browser completed successfully");
4145b9c547cSRui Paulo write_summary(ctx, "User response in browser completed successfully");
4155b9c547cSRui Paulo return DM_RESP_OK;
4165b9c547cSRui Paulo } else {
4175b9c547cSRui Paulo wpa_printf(MSG_INFO, "Failed to receive user response");
4185b9c547cSRui Paulo write_summary(ctx, "Failed to receive user response");
4195b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
4205b9c547cSRui Paulo }
4215b9c547cSRui Paulo }
4225b9c547cSRui Paulo
4235b9c547cSRui Paulo
oma_dm_exec_get_cert(struct hs20_osu_client * ctx,xml_node_t * exec)4245b9c547cSRui Paulo static int oma_dm_exec_get_cert(struct hs20_osu_client *ctx, xml_node_t *exec)
4255b9c547cSRui Paulo {
4265b9c547cSRui Paulo xml_node_t *node, *getcert;
4275b9c547cSRui Paulo char *data;
4285b9c547cSRui Paulo const char *name;
4295b9c547cSRui Paulo int res;
4305b9c547cSRui Paulo
4315b9c547cSRui Paulo wpa_printf(MSG_INFO, "Client certificate enrollment");
4325b9c547cSRui Paulo write_summary(ctx, "Client certificate enrollment");
4335b9c547cSRui Paulo
4345b9c547cSRui Paulo node = get_node(ctx->xml, exec, "Item/Data");
4355b9c547cSRui Paulo if (node == NULL) {
4365b9c547cSRui Paulo wpa_printf(MSG_INFO, "No Data node found");
4375b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
4385b9c547cSRui Paulo }
4395b9c547cSRui Paulo
4405b9c547cSRui Paulo data = xml_node_get_text(ctx->xml, node);
4415b9c547cSRui Paulo if (data == NULL) {
4425b9c547cSRui Paulo wpa_printf(MSG_INFO, "Invalid data");
4435b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
4445b9c547cSRui Paulo }
4455b9c547cSRui Paulo wpa_printf(MSG_INFO, "Data: %s", data);
4465b9c547cSRui Paulo getcert = xml_node_from_buf(ctx->xml, data);
4475b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, data);
4485b9c547cSRui Paulo
4495b9c547cSRui Paulo if (getcert == NULL) {
4505b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not parse Item/Data node contents");
4515b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
4525b9c547cSRui Paulo }
4535b9c547cSRui Paulo
4545b9c547cSRui Paulo debug_dump_node(ctx, "OMA-DM getCertificate", getcert);
4555b9c547cSRui Paulo
4565b9c547cSRui Paulo name = xml_node_get_localname(ctx->xml, getcert);
4575b9c547cSRui Paulo if (name == NULL || os_strcasecmp(name, "getCertificate") != 0) {
4585b9c547cSRui Paulo wpa_printf(MSG_INFO, "Unexpected getCertificate node name '%s'",
4595b9c547cSRui Paulo name);
4605b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
4615b9c547cSRui Paulo }
4625b9c547cSRui Paulo
4635b9c547cSRui Paulo res = osu_get_certificate(ctx, getcert);
4645b9c547cSRui Paulo
4655b9c547cSRui Paulo xml_node_free(ctx->xml, getcert);
4665b9c547cSRui Paulo
4675b9c547cSRui Paulo return res == 0 ? DM_RESP_OK : DM_RESP_COMMAND_FAILED;
4685b9c547cSRui Paulo }
4695b9c547cSRui Paulo
4705b9c547cSRui Paulo
oma_dm_exec(struct hs20_osu_client * ctx,xml_node_t * exec)4715b9c547cSRui Paulo static int oma_dm_exec(struct hs20_osu_client *ctx, xml_node_t *exec)
4725b9c547cSRui Paulo {
4735b9c547cSRui Paulo char *locuri;
4745b9c547cSRui Paulo int ret;
4755b9c547cSRui Paulo
4765b9c547cSRui Paulo locuri = oma_dm_get_target_locuri(ctx, exec);
4775b9c547cSRui Paulo if (locuri == NULL) {
4785b9c547cSRui Paulo wpa_printf(MSG_INFO, "No Target LocURI node found");
4795b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
4805b9c547cSRui Paulo }
4815b9c547cSRui Paulo
4825b9c547cSRui Paulo wpa_printf(MSG_INFO, "Target LocURI: %s", locuri);
4835b9c547cSRui Paulo
4845b9c547cSRui Paulo if (os_strcasecmp(locuri, "./DevDetail/Ext/org.wi-fi/Wi-Fi/Ops/"
4855b9c547cSRui Paulo "launchBrowserToURI") == 0) {
4865b9c547cSRui Paulo ret = oma_dm_exec_browser(ctx, exec);
4875b9c547cSRui Paulo } else if (os_strcasecmp(locuri, "./DevDetail/Ext/org.wi-fi/Wi-Fi/Ops/"
4885b9c547cSRui Paulo "getCertificate") == 0) {
4895b9c547cSRui Paulo ret = oma_dm_exec_get_cert(ctx, exec);
4905b9c547cSRui Paulo } else {
4915b9c547cSRui Paulo wpa_printf(MSG_INFO, "Unsupported exec Target LocURI");
4925b9c547cSRui Paulo ret = DM_RESP_NOT_FOUND;
4935b9c547cSRui Paulo }
4945b9c547cSRui Paulo os_free(locuri);
4955b9c547cSRui Paulo
4965b9c547cSRui Paulo return ret;
4975b9c547cSRui Paulo }
4985b9c547cSRui Paulo
4995b9c547cSRui Paulo
oma_dm_run_add(struct hs20_osu_client * ctx,const char * locuri,xml_node_t * add,xml_node_t * pps,const char * pps_fname)5005b9c547cSRui Paulo static int oma_dm_run_add(struct hs20_osu_client *ctx, const char *locuri,
5015b9c547cSRui Paulo xml_node_t *add, xml_node_t *pps,
5025b9c547cSRui Paulo const char *pps_fname)
5035b9c547cSRui Paulo {
5045b9c547cSRui Paulo const char *pos;
5055b9c547cSRui Paulo size_t fqdn_len;
5065b9c547cSRui Paulo xml_node_t *node, *tnds, *unode, *pps_node;
5075b9c547cSRui Paulo char *data, *uri, *upos, *end;
5085b9c547cSRui Paulo int use_tnds = 0;
5095b9c547cSRui Paulo size_t uri_len;
5105b9c547cSRui Paulo
5115b9c547cSRui Paulo wpa_printf(MSG_INFO, "Add command target LocURI: %s", locuri);
5125b9c547cSRui Paulo
5135b9c547cSRui Paulo if (os_strncasecmp(locuri, "./Wi-Fi/", 8) != 0) {
5145b9c547cSRui Paulo wpa_printf(MSG_INFO, "Do not allow Add outside ./Wi-Fi");
5155b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
5165b9c547cSRui Paulo }
5175b9c547cSRui Paulo pos = locuri + 8;
5185b9c547cSRui Paulo
5195b9c547cSRui Paulo if (ctx->fqdn == NULL)
5205b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
5215b9c547cSRui Paulo fqdn_len = os_strlen(ctx->fqdn);
5225b9c547cSRui Paulo if (os_strncasecmp(pos, ctx->fqdn, fqdn_len) != 0 ||
5235b9c547cSRui Paulo pos[fqdn_len] != '/') {
5245b9c547cSRui Paulo wpa_printf(MSG_INFO, "Do not allow Add outside ./Wi-Fi/%s",
5255b9c547cSRui Paulo ctx->fqdn);
5265b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
5275b9c547cSRui Paulo }
5285b9c547cSRui Paulo pos += fqdn_len + 1;
5295b9c547cSRui Paulo
5305b9c547cSRui Paulo if (os_strncasecmp(pos, "PerProviderSubscription/", 24) != 0) {
5315b9c547cSRui Paulo wpa_printf(MSG_INFO,
5325b9c547cSRui Paulo "Do not allow Add outside ./Wi-Fi/%s/PerProviderSubscription",
5335b9c547cSRui Paulo ctx->fqdn);
5345b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
5355b9c547cSRui Paulo }
5365b9c547cSRui Paulo pos += 24;
5375b9c547cSRui Paulo
5385b9c547cSRui Paulo wpa_printf(MSG_INFO, "Add command for PPS node %s", pos);
5395b9c547cSRui Paulo
5405b9c547cSRui Paulo pps_node = get_node(ctx->xml, pps, pos);
5415b9c547cSRui Paulo if (pps_node) {
5425b9c547cSRui Paulo wpa_printf(MSG_INFO, "Specified PPS node exists already");
5435b9c547cSRui Paulo return DM_RESP_ALREADY_EXISTS;
5445b9c547cSRui Paulo }
5455b9c547cSRui Paulo
5465b9c547cSRui Paulo uri = os_strdup(pos);
5475b9c547cSRui Paulo if (uri == NULL)
5485b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
5495b9c547cSRui Paulo while (!pps_node) {
5505b9c547cSRui Paulo upos = os_strrchr(uri, '/');
5515b9c547cSRui Paulo if (!upos)
5525b9c547cSRui Paulo break;
5535b9c547cSRui Paulo upos[0] = '\0';
5545b9c547cSRui Paulo pps_node = get_node(ctx->xml, pps, uri);
5555b9c547cSRui Paulo wpa_printf(MSG_INFO, "Node %s %s", uri,
5565b9c547cSRui Paulo pps_node ? "exists" : "does not exist");
5575b9c547cSRui Paulo }
5585b9c547cSRui Paulo
5595b9c547cSRui Paulo wpa_printf(MSG_INFO, "Parent URI: %s", uri);
5605b9c547cSRui Paulo
5615b9c547cSRui Paulo if (!pps_node) {
5625b9c547cSRui Paulo /* Add at root of PPS MO */
5635b9c547cSRui Paulo pps_node = pps;
5645b9c547cSRui Paulo }
5655b9c547cSRui Paulo
5665b9c547cSRui Paulo uri_len = os_strlen(uri);
5675b9c547cSRui Paulo os_strlcpy(uri, pos + uri_len, os_strlen(pos));
5685b9c547cSRui Paulo upos = uri;
5695b9c547cSRui Paulo while (*upos == '/')
5705b9c547cSRui Paulo upos++;
5715b9c547cSRui Paulo wpa_printf(MSG_INFO, "Nodes to add: %s", upos);
5725b9c547cSRui Paulo
5735b9c547cSRui Paulo for (;;) {
5745b9c547cSRui Paulo end = os_strchr(upos, '/');
5755b9c547cSRui Paulo if (!end)
5765b9c547cSRui Paulo break;
5775b9c547cSRui Paulo *end = '\0';
5785b9c547cSRui Paulo wpa_printf(MSG_INFO, "Adding interim node %s", upos);
5795b9c547cSRui Paulo pps_node = xml_node_create(ctx->xml, pps_node, NULL, upos);
5805b9c547cSRui Paulo if (pps_node == NULL) {
5815b9c547cSRui Paulo os_free(uri);
5825b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
5835b9c547cSRui Paulo }
5845b9c547cSRui Paulo upos = end + 1;
5855b9c547cSRui Paulo }
5865b9c547cSRui Paulo
5875b9c547cSRui Paulo wpa_printf(MSG_INFO, "Adding node %s", upos);
5885b9c547cSRui Paulo
5895b9c547cSRui Paulo node = get_node(ctx->xml, add, "Item/Meta/Type");
5905b9c547cSRui Paulo if (node) {
5915b9c547cSRui Paulo char *type;
5925b9c547cSRui Paulo type = xml_node_get_text(ctx->xml, node);
5935b9c547cSRui Paulo if (type == NULL) {
5945b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Could not find type text");
5955b9c547cSRui Paulo os_free(uri);
5965b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
5975b9c547cSRui Paulo }
5985b9c547cSRui Paulo use_tnds = node &&
5995b9c547cSRui Paulo os_strstr(type, "application/vnd.syncml.dmtnds+xml");
6005b9c547cSRui Paulo }
6015b9c547cSRui Paulo
6025b9c547cSRui Paulo node = get_node(ctx->xml, add, "Item/Data");
6035b9c547cSRui Paulo if (node == NULL) {
6045b9c547cSRui Paulo wpa_printf(MSG_INFO, "No Add/Item/Data found");
6055b9c547cSRui Paulo os_free(uri);
6065b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
6075b9c547cSRui Paulo }
6085b9c547cSRui Paulo
6095b9c547cSRui Paulo data = xml_node_get_text(ctx->xml, node);
6105b9c547cSRui Paulo if (data == NULL) {
6115b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not get Add/Item/Data text");
6125b9c547cSRui Paulo os_free(uri);
6135b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
6145b9c547cSRui Paulo }
6155b9c547cSRui Paulo
6165b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "Add/Item/Data: %s", data);
6175b9c547cSRui Paulo
6185b9c547cSRui Paulo if (use_tnds) {
6195b9c547cSRui Paulo tnds = xml_node_from_buf(ctx->xml, data);
6205b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, data);
6215b9c547cSRui Paulo if (tnds == NULL) {
6225b9c547cSRui Paulo wpa_printf(MSG_INFO,
6235b9c547cSRui Paulo "Could not parse Add/Item/Data text");
6245b9c547cSRui Paulo os_free(uri);
6255b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
6265b9c547cSRui Paulo }
6275b9c547cSRui Paulo
6285b9c547cSRui Paulo unode = tnds_to_mo(ctx->xml, tnds);
6295b9c547cSRui Paulo xml_node_free(ctx->xml, tnds);
6305b9c547cSRui Paulo if (unode == NULL) {
6315b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not parse TNDS text");
6325b9c547cSRui Paulo os_free(uri);
6335b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
6345b9c547cSRui Paulo }
6355b9c547cSRui Paulo
6365b9c547cSRui Paulo debug_dump_node(ctx, "Parsed TNDS", unode);
6375b9c547cSRui Paulo
6385b9c547cSRui Paulo xml_node_add_child(ctx->xml, pps_node, unode);
6395b9c547cSRui Paulo } else {
6405b9c547cSRui Paulo /* TODO: What to do here? */
6415b9c547cSRui Paulo os_free(uri);
6425b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
6435b9c547cSRui Paulo }
6445b9c547cSRui Paulo
6455b9c547cSRui Paulo os_free(uri);
6465b9c547cSRui Paulo
6475b9c547cSRui Paulo if (update_pps_file(ctx, pps_fname, pps) < 0)
6485b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
6495b9c547cSRui Paulo
6505b9c547cSRui Paulo ctx->pps_updated = 1;
6515b9c547cSRui Paulo
6525b9c547cSRui Paulo return DM_RESP_OK;
6535b9c547cSRui Paulo }
6545b9c547cSRui Paulo
6555b9c547cSRui Paulo
oma_dm_add(struct hs20_osu_client * ctx,xml_node_t * add,xml_node_t * pps,const char * pps_fname)6565b9c547cSRui Paulo static int oma_dm_add(struct hs20_osu_client *ctx, xml_node_t *add,
6575b9c547cSRui Paulo xml_node_t *pps, const char *pps_fname)
6585b9c547cSRui Paulo {
6595b9c547cSRui Paulo xml_node_t *node;
6605b9c547cSRui Paulo char *locuri;
6615b9c547cSRui Paulo char fname[300];
6625b9c547cSRui Paulo int ret;
6635b9c547cSRui Paulo
6645b9c547cSRui Paulo node = get_node(ctx->xml, add, "Item/Target/LocURI");
6655b9c547cSRui Paulo if (node == NULL) {
6665b9c547cSRui Paulo wpa_printf(MSG_INFO, "No Target LocURI node found");
6675b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
6685b9c547cSRui Paulo }
6695b9c547cSRui Paulo locuri = xml_node_get_text(ctx->xml, node);
6705b9c547cSRui Paulo if (locuri == NULL) {
6715b9c547cSRui Paulo wpa_printf(MSG_ERROR, "No LocURI node text found");
6725b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
6735b9c547cSRui Paulo }
6745b9c547cSRui Paulo wpa_printf(MSG_INFO, "Target LocURI: %s", locuri);
6755b9c547cSRui Paulo if (os_strncasecmp(locuri, "./Wi-Fi/", 8) != 0) {
6765b9c547cSRui Paulo wpa_printf(MSG_INFO, "Unsupported Add Target LocURI");
6775b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, locuri);
6785b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
6795b9c547cSRui Paulo }
6805b9c547cSRui Paulo
6815b9c547cSRui Paulo node = get_node(ctx->xml, add, "Item/Data");
6825b9c547cSRui Paulo if (node == NULL) {
6835b9c547cSRui Paulo wpa_printf(MSG_INFO, "No Data node found");
6845b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, locuri);
6855b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
6865b9c547cSRui Paulo }
6875b9c547cSRui Paulo
6885b9c547cSRui Paulo if (pps_fname && os_file_exists(pps_fname)) {
6895b9c547cSRui Paulo ret = oma_dm_run_add(ctx, locuri, add, pps, pps_fname);
6905b9c547cSRui Paulo if (ret != DM_RESP_OK) {
6915b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, locuri);
6925b9c547cSRui Paulo return ret;
6935b9c547cSRui Paulo }
6945b9c547cSRui Paulo ret = 0;
6955b9c547cSRui Paulo os_strlcpy(fname, pps_fname, sizeof(fname));
6965b9c547cSRui Paulo } else
6975b9c547cSRui Paulo ret = hs20_add_pps_mo(ctx, locuri, node, fname, sizeof(fname));
6985b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, locuri);
6995b9c547cSRui Paulo if (ret < 0)
7005b9c547cSRui Paulo return ret == -2 ? DM_RESP_ALREADY_EXISTS :
7015b9c547cSRui Paulo DM_RESP_COMMAND_FAILED;
7025b9c547cSRui Paulo
7035b9c547cSRui Paulo if (ctx->no_reconnect == 2) {
7045b9c547cSRui Paulo os_snprintf(ctx->pps_fname, sizeof(ctx->pps_fname), "%s",
7055b9c547cSRui Paulo fname);
7065b9c547cSRui Paulo ctx->pps_cred_set = 1;
7075b9c547cSRui Paulo return DM_RESP_OK;
7085b9c547cSRui Paulo }
7095b9c547cSRui Paulo
7105b9c547cSRui Paulo wpa_printf(MSG_INFO, "Updating wpa_supplicant credentials");
7115b9c547cSRui Paulo cmd_set_pps(ctx, fname);
7125b9c547cSRui Paulo
7135b9c547cSRui Paulo if (ctx->no_reconnect)
7145b9c547cSRui Paulo return DM_RESP_OK;
7155b9c547cSRui Paulo
7165b9c547cSRui Paulo wpa_printf(MSG_INFO, "Requesting reconnection with updated configuration");
7175b9c547cSRui Paulo if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0)
7185b9c547cSRui Paulo wpa_printf(MSG_INFO, "Failed to request wpa_supplicant to reconnect");
7195b9c547cSRui Paulo
7205b9c547cSRui Paulo return DM_RESP_OK;
7215b9c547cSRui Paulo }
7225b9c547cSRui Paulo
7235b9c547cSRui Paulo
oma_dm_replace(struct hs20_osu_client * ctx,xml_node_t * replace,xml_node_t * pps,const char * pps_fname)7245b9c547cSRui Paulo static int oma_dm_replace(struct hs20_osu_client *ctx, xml_node_t *replace,
7255b9c547cSRui Paulo xml_node_t *pps, const char *pps_fname)
7265b9c547cSRui Paulo {
7275b9c547cSRui Paulo char *locuri, *pos;
7285b9c547cSRui Paulo size_t fqdn_len;
7295b9c547cSRui Paulo xml_node_t *node, *tnds, *unode, *pps_node, *parent;
7305b9c547cSRui Paulo char *data;
7315b9c547cSRui Paulo int use_tnds = 0;
7325b9c547cSRui Paulo
7335b9c547cSRui Paulo locuri = oma_dm_get_target_locuri(ctx, replace);
7345b9c547cSRui Paulo if (locuri == NULL)
7355b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
7365b9c547cSRui Paulo
7375b9c547cSRui Paulo wpa_printf(MSG_INFO, "Replace command target LocURI: %s", locuri);
7385b9c547cSRui Paulo if (os_strncasecmp(locuri, "./Wi-Fi/", 8) != 0) {
7395b9c547cSRui Paulo wpa_printf(MSG_INFO, "Do not allow Replace outside ./Wi-Fi");
7405b9c547cSRui Paulo os_free(locuri);
7415b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
7425b9c547cSRui Paulo }
7435b9c547cSRui Paulo pos = locuri + 8;
7445b9c547cSRui Paulo
7455b9c547cSRui Paulo if (ctx->fqdn == NULL) {
7465b9c547cSRui Paulo os_free(locuri);
7475b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
7485b9c547cSRui Paulo }
7495b9c547cSRui Paulo fqdn_len = os_strlen(ctx->fqdn);
7505b9c547cSRui Paulo if (os_strncasecmp(pos, ctx->fqdn, fqdn_len) != 0 ||
7515b9c547cSRui Paulo pos[fqdn_len] != '/') {
7525b9c547cSRui Paulo wpa_printf(MSG_INFO, "Do not allow Replace outside ./Wi-Fi/%s",
7535b9c547cSRui Paulo ctx->fqdn);
7545b9c547cSRui Paulo os_free(locuri);
7555b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
7565b9c547cSRui Paulo }
7575b9c547cSRui Paulo pos += fqdn_len + 1;
7585b9c547cSRui Paulo
7595b9c547cSRui Paulo if (os_strncasecmp(pos, "PerProviderSubscription/", 24) != 0) {
7605b9c547cSRui Paulo wpa_printf(MSG_INFO,
7615b9c547cSRui Paulo "Do not allow Replace outside ./Wi-Fi/%s/PerProviderSubscription",
7625b9c547cSRui Paulo ctx->fqdn);
7635b9c547cSRui Paulo os_free(locuri);
7645b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
7655b9c547cSRui Paulo }
7665b9c547cSRui Paulo pos += 24;
7675b9c547cSRui Paulo
7685b9c547cSRui Paulo wpa_printf(MSG_INFO, "Replace command for PPS node %s", pos);
7695b9c547cSRui Paulo
7705b9c547cSRui Paulo pps_node = get_node(ctx->xml, pps, pos);
7715b9c547cSRui Paulo if (pps_node == NULL) {
7725b9c547cSRui Paulo wpa_printf(MSG_INFO, "Specified PPS node not found");
7735b9c547cSRui Paulo os_free(locuri);
7745b9c547cSRui Paulo return DM_RESP_NOT_FOUND;
7755b9c547cSRui Paulo }
7765b9c547cSRui Paulo
7775b9c547cSRui Paulo node = get_node(ctx->xml, replace, "Item/Meta/Type");
7785b9c547cSRui Paulo if (node) {
7795b9c547cSRui Paulo char *type;
7805b9c547cSRui Paulo type = xml_node_get_text(ctx->xml, node);
7815b9c547cSRui Paulo if (type == NULL) {
7825b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not find type text");
7835b9c547cSRui Paulo os_free(locuri);
7845b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
7855b9c547cSRui Paulo }
7865b9c547cSRui Paulo use_tnds = node &&
7875b9c547cSRui Paulo os_strstr(type, "application/vnd.syncml.dmtnds+xml");
7885b9c547cSRui Paulo }
7895b9c547cSRui Paulo
7905b9c547cSRui Paulo node = get_node(ctx->xml, replace, "Item/Data");
7915b9c547cSRui Paulo if (node == NULL) {
7925b9c547cSRui Paulo wpa_printf(MSG_INFO, "No Replace/Item/Data found");
7935b9c547cSRui Paulo os_free(locuri);
7945b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
7955b9c547cSRui Paulo }
7965b9c547cSRui Paulo
7975b9c547cSRui Paulo data = xml_node_get_text(ctx->xml, node);
7985b9c547cSRui Paulo if (data == NULL) {
7995b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not get Replace/Item/Data text");
8005b9c547cSRui Paulo os_free(locuri);
8015b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
8025b9c547cSRui Paulo }
8035b9c547cSRui Paulo
8045b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "Replace/Item/Data: %s", data);
8055b9c547cSRui Paulo
8065b9c547cSRui Paulo if (use_tnds) {
8075b9c547cSRui Paulo tnds = xml_node_from_buf(ctx->xml, data);
8085b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, data);
8095b9c547cSRui Paulo if (tnds == NULL) {
8105b9c547cSRui Paulo wpa_printf(MSG_INFO,
8115b9c547cSRui Paulo "Could not parse Replace/Item/Data text");
8125b9c547cSRui Paulo os_free(locuri);
8135b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
8145b9c547cSRui Paulo }
8155b9c547cSRui Paulo
8165b9c547cSRui Paulo unode = tnds_to_mo(ctx->xml, tnds);
8175b9c547cSRui Paulo xml_node_free(ctx->xml, tnds);
8185b9c547cSRui Paulo if (unode == NULL) {
8195b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not parse TNDS text");
8205b9c547cSRui Paulo os_free(locuri);
8215b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
8225b9c547cSRui Paulo }
8235b9c547cSRui Paulo
8245b9c547cSRui Paulo debug_dump_node(ctx, "Parsed TNDS", unode);
8255b9c547cSRui Paulo
8265b9c547cSRui Paulo parent = xml_node_get_parent(ctx->xml, pps_node);
8275b9c547cSRui Paulo xml_node_detach(ctx->xml, pps_node);
8285b9c547cSRui Paulo xml_node_add_child(ctx->xml, parent, unode);
8295b9c547cSRui Paulo } else {
8305b9c547cSRui Paulo xml_node_set_text(ctx->xml, pps_node, data);
8315b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, data);
8325b9c547cSRui Paulo }
8335b9c547cSRui Paulo
8345b9c547cSRui Paulo os_free(locuri);
8355b9c547cSRui Paulo
8365b9c547cSRui Paulo if (update_pps_file(ctx, pps_fname, pps) < 0)
8375b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
8385b9c547cSRui Paulo
8395b9c547cSRui Paulo ctx->pps_updated = 1;
8405b9c547cSRui Paulo
8415b9c547cSRui Paulo return DM_RESP_OK;
8425b9c547cSRui Paulo }
8435b9c547cSRui Paulo
8445b9c547cSRui Paulo
oma_dm_get(struct hs20_osu_client * ctx,xml_node_t * get,xml_node_t * pps,const char * pps_fname,char ** value)8455b9c547cSRui Paulo static int oma_dm_get(struct hs20_osu_client *ctx, xml_node_t *get,
8465b9c547cSRui Paulo xml_node_t *pps, const char *pps_fname, char **value)
8475b9c547cSRui Paulo {
8485b9c547cSRui Paulo char *locuri, *pos;
8495b9c547cSRui Paulo size_t fqdn_len;
8505b9c547cSRui Paulo xml_node_t *pps_node;
8515b9c547cSRui Paulo const char *name;
8525b9c547cSRui Paulo
8535b9c547cSRui Paulo *value = NULL;
8545b9c547cSRui Paulo
8555b9c547cSRui Paulo locuri = oma_dm_get_target_locuri(ctx, get);
8565b9c547cSRui Paulo if (locuri == NULL)
8575b9c547cSRui Paulo return DM_RESP_BAD_REQUEST;
8585b9c547cSRui Paulo
8595b9c547cSRui Paulo wpa_printf(MSG_INFO, "Get command target LocURI: %s", locuri);
8605b9c547cSRui Paulo if (os_strncasecmp(locuri, "./Wi-Fi/", 8) != 0) {
8615b9c547cSRui Paulo wpa_printf(MSG_INFO, "Do not allow Get outside ./Wi-Fi");
8625b9c547cSRui Paulo os_free(locuri);
8635b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
8645b9c547cSRui Paulo }
8655b9c547cSRui Paulo pos = locuri + 8;
8665b9c547cSRui Paulo
8675b9c547cSRui Paulo if (ctx->fqdn == NULL)
8685b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
8695b9c547cSRui Paulo fqdn_len = os_strlen(ctx->fqdn);
8705b9c547cSRui Paulo if (os_strncasecmp(pos, ctx->fqdn, fqdn_len) != 0 ||
8715b9c547cSRui Paulo pos[fqdn_len] != '/') {
8725b9c547cSRui Paulo wpa_printf(MSG_INFO, "Do not allow Get outside ./Wi-Fi/%s",
8735b9c547cSRui Paulo ctx->fqdn);
8745b9c547cSRui Paulo os_free(locuri);
8755b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
8765b9c547cSRui Paulo }
8775b9c547cSRui Paulo pos += fqdn_len + 1;
8785b9c547cSRui Paulo
8795b9c547cSRui Paulo if (os_strncasecmp(pos, "PerProviderSubscription/", 24) != 0) {
8805b9c547cSRui Paulo wpa_printf(MSG_INFO,
8815b9c547cSRui Paulo "Do not allow Get outside ./Wi-Fi/%s/PerProviderSubscription",
8825b9c547cSRui Paulo ctx->fqdn);
8835b9c547cSRui Paulo os_free(locuri);
8845b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
8855b9c547cSRui Paulo }
8865b9c547cSRui Paulo pos += 24;
8875b9c547cSRui Paulo
8885b9c547cSRui Paulo wpa_printf(MSG_INFO, "Get command for PPS node %s", pos);
8895b9c547cSRui Paulo
8905b9c547cSRui Paulo pps_node = get_node(ctx->xml, pps, pos);
8915b9c547cSRui Paulo if (pps_node == NULL) {
8925b9c547cSRui Paulo wpa_printf(MSG_INFO, "Specified PPS node not found");
8935b9c547cSRui Paulo os_free(locuri);
8945b9c547cSRui Paulo return DM_RESP_NOT_FOUND;
8955b9c547cSRui Paulo }
8965b9c547cSRui Paulo
8975b9c547cSRui Paulo name = xml_node_get_localname(ctx->xml, pps_node);
8985b9c547cSRui Paulo wpa_printf(MSG_INFO, "Get command returned node with name '%s'", name);
8995b9c547cSRui Paulo if (os_strcasecmp(name, "Password") == 0) {
9005b9c547cSRui Paulo wpa_printf(MSG_INFO, "Do not allow Get for Password node");
9015b9c547cSRui Paulo os_free(locuri);
9025b9c547cSRui Paulo return DM_RESP_PERMISSION_DENIED;
9035b9c547cSRui Paulo }
9045b9c547cSRui Paulo
9055b9c547cSRui Paulo /*
9065b9c547cSRui Paulo * TODO: No support for DMTNDS, so if interior node, reply with a
9075b9c547cSRui Paulo * list of children node names in Results element. The child list type is
9085b9c547cSRui Paulo * defined in [DMTND].
9095b9c547cSRui Paulo */
9105b9c547cSRui Paulo
9115b9c547cSRui Paulo *value = xml_node_get_text(ctx->xml, pps_node);
9125b9c547cSRui Paulo if (*value == NULL)
9135b9c547cSRui Paulo return DM_RESP_COMMAND_FAILED;
9145b9c547cSRui Paulo
9155b9c547cSRui Paulo return DM_RESP_OK;
9165b9c547cSRui Paulo }
9175b9c547cSRui Paulo
9185b9c547cSRui Paulo
oma_dm_get_cmdid(struct hs20_osu_client * ctx,xml_node_t * node)9195b9c547cSRui Paulo static int oma_dm_get_cmdid(struct hs20_osu_client *ctx, xml_node_t *node)
9205b9c547cSRui Paulo {
9215b9c547cSRui Paulo xml_node_t *cnode;
9225b9c547cSRui Paulo char *str;
9235b9c547cSRui Paulo int ret;
9245b9c547cSRui Paulo
9255b9c547cSRui Paulo cnode = get_node(ctx->xml, node, "CmdID");
9265b9c547cSRui Paulo if (cnode == NULL)
9275b9c547cSRui Paulo return 0;
9285b9c547cSRui Paulo
9295b9c547cSRui Paulo str = xml_node_get_text(ctx->xml, cnode);
9305b9c547cSRui Paulo if (str == NULL)
9315b9c547cSRui Paulo return 0;
9325b9c547cSRui Paulo ret = atoi(str);
9335b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, str);
9345b9c547cSRui Paulo return ret;
9355b9c547cSRui Paulo }
9365b9c547cSRui Paulo
9375b9c547cSRui Paulo
oma_dm_send_recv(struct hs20_osu_client * ctx,const char * url,xml_node_t * syncml,const char * ext_hdr,const char * username,const char * password,const char * client_cert,const char * client_key)9385b9c547cSRui Paulo static xml_node_t * oma_dm_send_recv(struct hs20_osu_client *ctx,
9395b9c547cSRui Paulo const char *url, xml_node_t *syncml,
9405b9c547cSRui Paulo const char *ext_hdr,
9415b9c547cSRui Paulo const char *username, const char *password,
9425b9c547cSRui Paulo const char *client_cert,
9435b9c547cSRui Paulo const char *client_key)
9445b9c547cSRui Paulo {
9455b9c547cSRui Paulo xml_node_t *resp;
9465b9c547cSRui Paulo char *str, *res;
9475b9c547cSRui Paulo char *resp_uri = NULL;
9485b9c547cSRui Paulo
9495b9c547cSRui Paulo str = xml_node_to_str(ctx->xml, syncml);
9505b9c547cSRui Paulo xml_node_free(ctx->xml, syncml);
9515b9c547cSRui Paulo if (str == NULL)
9525b9c547cSRui Paulo return NULL;
9535b9c547cSRui Paulo
9545b9c547cSRui Paulo wpa_printf(MSG_INFO, "Send OMA DM Package");
9555b9c547cSRui Paulo write_summary(ctx, "Send OMA DM Package");
9565b9c547cSRui Paulo os_free(ctx->server_url);
9575b9c547cSRui Paulo ctx->server_url = os_strdup(url);
9585b9c547cSRui Paulo res = http_post(ctx->http, url, str, "application/vnd.syncml.dm+xml",
9595b9c547cSRui Paulo ext_hdr, ctx->ca_fname, username, password,
9605b9c547cSRui Paulo client_cert, client_key, NULL);
9615b9c547cSRui Paulo os_free(str);
9625b9c547cSRui Paulo os_free(resp_uri);
9635b9c547cSRui Paulo resp_uri = NULL;
9645b9c547cSRui Paulo
9655b9c547cSRui Paulo if (res == NULL) {
9665b9c547cSRui Paulo const char *err = http_get_err(ctx->http);
9675b9c547cSRui Paulo if (err) {
9685b9c547cSRui Paulo wpa_printf(MSG_INFO, "HTTP error: %s", err);
9695b9c547cSRui Paulo write_result(ctx, "HTTP error: %s", err);
9705b9c547cSRui Paulo } else {
9715b9c547cSRui Paulo write_summary(ctx, "Failed to send OMA DM Package");
9725b9c547cSRui Paulo }
9735b9c547cSRui Paulo return NULL;
9745b9c547cSRui Paulo }
9755b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "Server response: %s", res);
9765b9c547cSRui Paulo
9775b9c547cSRui Paulo wpa_printf(MSG_INFO, "Process OMA DM Package");
9785b9c547cSRui Paulo write_summary(ctx, "Process received OMA DM Package");
9795b9c547cSRui Paulo resp = xml_node_from_buf(ctx->xml, res);
9805b9c547cSRui Paulo os_free(res);
9815b9c547cSRui Paulo if (resp == NULL) {
9825b9c547cSRui Paulo wpa_printf(MSG_INFO, "Failed to parse OMA DM response");
9835b9c547cSRui Paulo return NULL;
9845b9c547cSRui Paulo }
9855b9c547cSRui Paulo
9865b9c547cSRui Paulo debug_dump_node(ctx, "OMA DM Package", resp);
9875b9c547cSRui Paulo
9885b9c547cSRui Paulo return resp;
9895b9c547cSRui Paulo }
9905b9c547cSRui Paulo
9915b9c547cSRui Paulo
oma_dm_process(struct hs20_osu_client * ctx,const char * url,xml_node_t * resp,int msgid,char ** ret_resp_uri,xml_node_t * pps,const char * pps_fname)9925b9c547cSRui Paulo static xml_node_t * oma_dm_process(struct hs20_osu_client *ctx, const char *url,
9935b9c547cSRui Paulo xml_node_t *resp, int msgid,
9945b9c547cSRui Paulo char **ret_resp_uri,
9955b9c547cSRui Paulo xml_node_t *pps, const char *pps_fname)
9965b9c547cSRui Paulo {
9975b9c547cSRui Paulo xml_node_t *syncml, *syncbody, *hdr, *body, *child;
9985b9c547cSRui Paulo const char *name;
9995b9c547cSRui Paulo char *resp_uri = NULL;
10005b9c547cSRui Paulo int server_msgid = 0;
10015b9c547cSRui Paulo int cmdid = 0;
10025b9c547cSRui Paulo int server_cmdid;
10035b9c547cSRui Paulo int resp_needed = 0;
10045b9c547cSRui Paulo char *tmp;
10055b9c547cSRui Paulo int final = 0;
10065b9c547cSRui Paulo char *locuri;
10075b9c547cSRui Paulo
10085b9c547cSRui Paulo *ret_resp_uri = NULL;
10095b9c547cSRui Paulo
10105b9c547cSRui Paulo name = xml_node_get_localname(ctx->xml, resp);
10115b9c547cSRui Paulo if (name == NULL || os_strcasecmp(name, "SyncML") != 0) {
10125b9c547cSRui Paulo wpa_printf(MSG_INFO, "SyncML node not found");
10135b9c547cSRui Paulo return NULL;
10145b9c547cSRui Paulo }
10155b9c547cSRui Paulo
10165b9c547cSRui Paulo hdr = get_node(ctx->xml, resp, "SyncHdr");
10175b9c547cSRui Paulo body = get_node(ctx->xml, resp, "SyncBody");
10185b9c547cSRui Paulo if (hdr == NULL || body == NULL) {
10195b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not find SyncHdr or SyncBody");
10205b9c547cSRui Paulo return NULL;
10215b9c547cSRui Paulo }
10225b9c547cSRui Paulo
10235b9c547cSRui Paulo xml_node_for_each_child(ctx->xml, child, hdr) {
10245b9c547cSRui Paulo xml_node_for_each_check(ctx->xml, child);
10255b9c547cSRui Paulo name = xml_node_get_localname(ctx->xml, child);
10265b9c547cSRui Paulo wpa_printf(MSG_INFO, "SyncHdr %s", name);
10275b9c547cSRui Paulo if (os_strcasecmp(name, "RespURI") == 0) {
10285b9c547cSRui Paulo tmp = xml_node_get_text(ctx->xml, child);
10295b9c547cSRui Paulo if (tmp)
10305b9c547cSRui Paulo resp_uri = os_strdup(tmp);
10315b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, tmp);
10325b9c547cSRui Paulo } else if (os_strcasecmp(name, "MsgID") == 0) {
10335b9c547cSRui Paulo tmp = xml_node_get_text(ctx->xml, child);
10345b9c547cSRui Paulo if (tmp)
10355b9c547cSRui Paulo server_msgid = atoi(tmp);
10365b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, tmp);
10375b9c547cSRui Paulo }
10385b9c547cSRui Paulo }
10395b9c547cSRui Paulo
10405b9c547cSRui Paulo wpa_printf(MSG_INFO, "Server MsgID: %d", server_msgid);
10415b9c547cSRui Paulo if (resp_uri)
10425b9c547cSRui Paulo wpa_printf(MSG_INFO, "RespURI: %s", resp_uri);
10435b9c547cSRui Paulo
10445b9c547cSRui Paulo syncml = oma_dm_build_hdr(ctx, resp_uri ? resp_uri : url, msgid);
10455b9c547cSRui Paulo if (syncml == NULL) {
10465b9c547cSRui Paulo os_free(resp_uri);
10475b9c547cSRui Paulo return NULL;
10485b9c547cSRui Paulo }
10495b9c547cSRui Paulo
10505b9c547cSRui Paulo syncbody = xml_node_create(ctx->xml, syncml, NULL, "SyncBody");
10515b9c547cSRui Paulo cmdid++;
10525b9c547cSRui Paulo add_status(ctx, syncbody, server_msgid, 0, cmdid, "SyncHdr",
10535b9c547cSRui Paulo DM_RESP_AUTH_ACCEPTED, NULL);
10545b9c547cSRui Paulo
10555b9c547cSRui Paulo xml_node_for_each_child(ctx->xml, child, body) {
10565b9c547cSRui Paulo xml_node_for_each_check(ctx->xml, child);
10575b9c547cSRui Paulo server_cmdid = oma_dm_get_cmdid(ctx, child);
10585b9c547cSRui Paulo name = xml_node_get_localname(ctx->xml, child);
10595b9c547cSRui Paulo wpa_printf(MSG_INFO, "SyncBody CmdID=%d - %s",
10605b9c547cSRui Paulo server_cmdid, name);
10615b9c547cSRui Paulo if (os_strcasecmp(name, "Exec") == 0) {
10625b9c547cSRui Paulo int res = oma_dm_exec(ctx, child);
10635b9c547cSRui Paulo cmdid++;
10645b9c547cSRui Paulo locuri = oma_dm_get_target_locuri(ctx, child);
10655b9c547cSRui Paulo if (locuri == NULL)
10665b9c547cSRui Paulo res = DM_RESP_BAD_REQUEST;
10675b9c547cSRui Paulo add_status(ctx, syncbody, server_msgid, server_cmdid,
10685b9c547cSRui Paulo cmdid, name, res, locuri);
10695b9c547cSRui Paulo os_free(locuri);
10705b9c547cSRui Paulo resp_needed = 1;
10715b9c547cSRui Paulo } else if (os_strcasecmp(name, "Add") == 0) {
10725b9c547cSRui Paulo int res = oma_dm_add(ctx, child, pps, pps_fname);
10735b9c547cSRui Paulo cmdid++;
10745b9c547cSRui Paulo locuri = oma_dm_get_target_locuri(ctx, child);
10755b9c547cSRui Paulo if (locuri == NULL)
10765b9c547cSRui Paulo res = DM_RESP_BAD_REQUEST;
10775b9c547cSRui Paulo add_status(ctx, syncbody, server_msgid, server_cmdid,
10785b9c547cSRui Paulo cmdid, name, res, locuri);
10795b9c547cSRui Paulo os_free(locuri);
10805b9c547cSRui Paulo resp_needed = 1;
10815b9c547cSRui Paulo } else if (os_strcasecmp(name, "Replace") == 0) {
10825b9c547cSRui Paulo int res;
10835b9c547cSRui Paulo res = oma_dm_replace(ctx, child, pps, pps_fname);
10845b9c547cSRui Paulo cmdid++;
10855b9c547cSRui Paulo locuri = oma_dm_get_target_locuri(ctx, child);
10865b9c547cSRui Paulo if (locuri == NULL)
10875b9c547cSRui Paulo res = DM_RESP_BAD_REQUEST;
10885b9c547cSRui Paulo add_status(ctx, syncbody, server_msgid, server_cmdid,
10895b9c547cSRui Paulo cmdid, name, res, locuri);
10905b9c547cSRui Paulo os_free(locuri);
10915b9c547cSRui Paulo resp_needed = 1;
10925b9c547cSRui Paulo } else if (os_strcasecmp(name, "Status") == 0) {
10935b9c547cSRui Paulo /* TODO: Verify success */
10945b9c547cSRui Paulo } else if (os_strcasecmp(name, "Get") == 0) {
10955b9c547cSRui Paulo int res;
10965b9c547cSRui Paulo char *value;
10975b9c547cSRui Paulo res = oma_dm_get(ctx, child, pps, pps_fname, &value);
10985b9c547cSRui Paulo cmdid++;
10995b9c547cSRui Paulo locuri = oma_dm_get_target_locuri(ctx, child);
11005b9c547cSRui Paulo if (locuri == NULL)
11015b9c547cSRui Paulo res = DM_RESP_BAD_REQUEST;
11025b9c547cSRui Paulo add_status(ctx, syncbody, server_msgid, server_cmdid,
11035b9c547cSRui Paulo cmdid, name, res, locuri);
11045b9c547cSRui Paulo if (res == DM_RESP_OK && value) {
11055b9c547cSRui Paulo cmdid++;
11065b9c547cSRui Paulo add_results(ctx, syncbody, server_msgid,
11075b9c547cSRui Paulo server_cmdid, cmdid, locuri, value);
11085b9c547cSRui Paulo }
11095b9c547cSRui Paulo os_free(locuri);
11105b9c547cSRui Paulo xml_node_get_text_free(ctx->xml, value);
11115b9c547cSRui Paulo resp_needed = 1;
11125b9c547cSRui Paulo #if 0 /* TODO: MUST support */
11135b9c547cSRui Paulo } else if (os_strcasecmp(name, "Delete") == 0) {
11145b9c547cSRui Paulo #endif
11155b9c547cSRui Paulo #if 0 /* TODO: MUST support */
11165b9c547cSRui Paulo } else if (os_strcasecmp(name, "Sequence") == 0) {
11175b9c547cSRui Paulo #endif
11185b9c547cSRui Paulo } else if (os_strcasecmp(name, "Final") == 0) {
11195b9c547cSRui Paulo final = 1;
11205b9c547cSRui Paulo break;
11215b9c547cSRui Paulo } else {
11225b9c547cSRui Paulo locuri = oma_dm_get_target_locuri(ctx, child);
11235b9c547cSRui Paulo add_status(ctx, syncbody, server_msgid, server_cmdid,
11245b9c547cSRui Paulo cmdid, name, DM_RESP_COMMAND_NOT_IMPLEMENTED,
11255b9c547cSRui Paulo locuri);
11265b9c547cSRui Paulo os_free(locuri);
11275b9c547cSRui Paulo resp_needed = 1;
11285b9c547cSRui Paulo }
11295b9c547cSRui Paulo }
11305b9c547cSRui Paulo
11315b9c547cSRui Paulo if (!final) {
11325b9c547cSRui Paulo wpa_printf(MSG_INFO, "Final node not found");
11335b9c547cSRui Paulo xml_node_free(ctx->xml, syncml);
11345b9c547cSRui Paulo os_free(resp_uri);
11355b9c547cSRui Paulo return NULL;
11365b9c547cSRui Paulo }
11375b9c547cSRui Paulo
11385b9c547cSRui Paulo if (!resp_needed) {
11395b9c547cSRui Paulo wpa_printf(MSG_INFO, "Exchange completed - no response needed");
11405b9c547cSRui Paulo xml_node_free(ctx->xml, syncml);
11415b9c547cSRui Paulo os_free(resp_uri);
11425b9c547cSRui Paulo return NULL;
11435b9c547cSRui Paulo }
11445b9c547cSRui Paulo
11455b9c547cSRui Paulo xml_node_create(ctx->xml, syncbody, NULL, "Final");
11465b9c547cSRui Paulo
11475b9c547cSRui Paulo debug_dump_node(ctx, "OMA-DM Package 3", syncml);
11485b9c547cSRui Paulo
11495b9c547cSRui Paulo *ret_resp_uri = resp_uri;
11505b9c547cSRui Paulo return syncml;
11515b9c547cSRui Paulo }
11525b9c547cSRui Paulo
11535b9c547cSRui Paulo
cmd_oma_dm_prov(struct hs20_osu_client * ctx,const char * url)11545b9c547cSRui Paulo int cmd_oma_dm_prov(struct hs20_osu_client *ctx, const char *url)
11555b9c547cSRui Paulo {
11565b9c547cSRui Paulo xml_node_t *syncml, *resp;
11575b9c547cSRui Paulo char *resp_uri = NULL;
11585b9c547cSRui Paulo int msgid = 0;
11595b9c547cSRui Paulo
11605b9c547cSRui Paulo if (url == NULL) {
11615b9c547cSRui Paulo wpa_printf(MSG_INFO, "Invalid prov command (missing URL)");
11625b9c547cSRui Paulo return -1;
11635b9c547cSRui Paulo }
11645b9c547cSRui Paulo
11655b9c547cSRui Paulo wpa_printf(MSG_INFO, "OMA-DM credential provisioning requested");
11665b9c547cSRui Paulo write_summary(ctx, "OMA-DM credential provisioning");
11675b9c547cSRui Paulo
11685b9c547cSRui Paulo msgid++;
11695b9c547cSRui Paulo syncml = build_oma_dm_1_sub_reg(ctx, url, msgid);
11705b9c547cSRui Paulo if (syncml == NULL)
11715b9c547cSRui Paulo return -1;
11725b9c547cSRui Paulo
11735b9c547cSRui Paulo while (syncml) {
11745b9c547cSRui Paulo resp = oma_dm_send_recv(ctx, resp_uri ? resp_uri : url,
11755b9c547cSRui Paulo syncml, NULL, NULL, NULL, NULL, NULL);
11765b9c547cSRui Paulo if (resp == NULL)
11775b9c547cSRui Paulo return -1;
11785b9c547cSRui Paulo
11795b9c547cSRui Paulo msgid++;
11805b9c547cSRui Paulo syncml = oma_dm_process(ctx, url, resp, msgid, &resp_uri,
11815b9c547cSRui Paulo NULL, NULL);
11825b9c547cSRui Paulo xml_node_free(ctx->xml, resp);
11835b9c547cSRui Paulo }
11845b9c547cSRui Paulo
11855b9c547cSRui Paulo os_free(resp_uri);
11865b9c547cSRui Paulo
11875b9c547cSRui Paulo return ctx->pps_cred_set ? 0 : -1;
11885b9c547cSRui Paulo }
11895b9c547cSRui Paulo
11905b9c547cSRui Paulo
cmd_oma_dm_sim_prov(struct hs20_osu_client * ctx,const char * url)11915b9c547cSRui Paulo int cmd_oma_dm_sim_prov(struct hs20_osu_client *ctx, const char *url)
11925b9c547cSRui Paulo {
11935b9c547cSRui Paulo xml_node_t *syncml, *resp;
11945b9c547cSRui Paulo char *resp_uri = NULL;
11955b9c547cSRui Paulo int msgid = 0;
11965b9c547cSRui Paulo
11975b9c547cSRui Paulo if (url == NULL) {
11985b9c547cSRui Paulo wpa_printf(MSG_INFO, "Invalid prov command (missing URL)");
11995b9c547cSRui Paulo return -1;
12005b9c547cSRui Paulo }
12015b9c547cSRui Paulo
12025b9c547cSRui Paulo wpa_printf(MSG_INFO, "OMA-DM SIM provisioning requested");
12035b9c547cSRui Paulo ctx->no_reconnect = 2;
12045b9c547cSRui Paulo
12055b9c547cSRui Paulo wpa_printf(MSG_INFO, "Wait for IP address before starting SIM provisioning");
12065b9c547cSRui Paulo write_summary(ctx, "Wait for IP address before starting SIM provisioning");
12075b9c547cSRui Paulo
12085b9c547cSRui Paulo if (wait_ip_addr(ctx->ifname, 15) < 0) {
12095b9c547cSRui Paulo wpa_printf(MSG_INFO, "Could not get IP address for WLAN - try connection anyway");
12105b9c547cSRui Paulo }
12115b9c547cSRui Paulo write_summary(ctx, "OMA-DM SIM provisioning");
12125b9c547cSRui Paulo
12135b9c547cSRui Paulo msgid++;
12145b9c547cSRui Paulo syncml = build_oma_dm_1_sub_prov(ctx, url, msgid);
12155b9c547cSRui Paulo if (syncml == NULL)
12165b9c547cSRui Paulo return -1;
12175b9c547cSRui Paulo
12185b9c547cSRui Paulo while (syncml) {
12195b9c547cSRui Paulo resp = oma_dm_send_recv(ctx, resp_uri ? resp_uri : url,
12205b9c547cSRui Paulo syncml, NULL, NULL, NULL, NULL, NULL);
12215b9c547cSRui Paulo if (resp == NULL)
12225b9c547cSRui Paulo return -1;
12235b9c547cSRui Paulo
12245b9c547cSRui Paulo msgid++;
12255b9c547cSRui Paulo syncml = oma_dm_process(ctx, url, resp, msgid, &resp_uri,
12265b9c547cSRui Paulo NULL, NULL);
12275b9c547cSRui Paulo xml_node_free(ctx->xml, resp);
12285b9c547cSRui Paulo }
12295b9c547cSRui Paulo
12305b9c547cSRui Paulo os_free(resp_uri);
12315b9c547cSRui Paulo
12325b9c547cSRui Paulo if (ctx->pps_cred_set) {
12335b9c547cSRui Paulo wpa_printf(MSG_INFO, "Updating wpa_supplicant credentials");
12345b9c547cSRui Paulo cmd_set_pps(ctx, ctx->pps_fname);
12355b9c547cSRui Paulo
12365b9c547cSRui Paulo wpa_printf(MSG_INFO, "Requesting reconnection with updated configuration");
12375b9c547cSRui Paulo write_summary(ctx, "Requesting reconnection with updated configuration");
12385b9c547cSRui Paulo if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) {
12395b9c547cSRui Paulo wpa_printf(MSG_INFO, "Failed to request wpa_supplicant to reconnect");
12405b9c547cSRui Paulo write_summary(ctx, "Failed to request wpa_supplicant to reconnect");
12415b9c547cSRui Paulo return -1;
12425b9c547cSRui Paulo }
12435b9c547cSRui Paulo }
12445b9c547cSRui Paulo
12455b9c547cSRui Paulo return ctx->pps_cred_set ? 0 : -1;
12465b9c547cSRui Paulo }
12475b9c547cSRui Paulo
12485b9c547cSRui Paulo
oma_dm_pol_upd(struct hs20_osu_client * ctx,const char * address,const char * pps_fname,const char * client_cert,const char * client_key,const char * cred_username,const char * cred_password,xml_node_t * pps)12495b9c547cSRui Paulo void oma_dm_pol_upd(struct hs20_osu_client *ctx, const char *address,
12505b9c547cSRui Paulo const char *pps_fname,
12515b9c547cSRui Paulo const char *client_cert, const char *client_key,
12525b9c547cSRui Paulo const char *cred_username, const char *cred_password,
12535b9c547cSRui Paulo xml_node_t *pps)
12545b9c547cSRui Paulo {
12555b9c547cSRui Paulo xml_node_t *syncml, *resp;
12565b9c547cSRui Paulo char *resp_uri = NULL;
12575b9c547cSRui Paulo int msgid = 0;
12585b9c547cSRui Paulo
12595b9c547cSRui Paulo wpa_printf(MSG_INFO, "OMA-DM policy update");
12605b9c547cSRui Paulo write_summary(ctx, "OMA-DM policy update");
12615b9c547cSRui Paulo
12625b9c547cSRui Paulo msgid++;
12635b9c547cSRui Paulo syncml = build_oma_dm_1_pol_upd(ctx, address, msgid);
12645b9c547cSRui Paulo if (syncml == NULL)
12655b9c547cSRui Paulo return;
12665b9c547cSRui Paulo
12675b9c547cSRui Paulo while (syncml) {
12685b9c547cSRui Paulo resp = oma_dm_send_recv(ctx, resp_uri ? resp_uri : address,
12695b9c547cSRui Paulo syncml, NULL, cred_username,
12705b9c547cSRui Paulo cred_password, client_cert, client_key);
12715b9c547cSRui Paulo if (resp == NULL)
12725b9c547cSRui Paulo return;
12735b9c547cSRui Paulo
12745b9c547cSRui Paulo msgid++;
12755b9c547cSRui Paulo syncml = oma_dm_process(ctx, address, resp, msgid, &resp_uri,
12765b9c547cSRui Paulo pps, pps_fname);
12775b9c547cSRui Paulo xml_node_free(ctx->xml, resp);
12785b9c547cSRui Paulo }
12795b9c547cSRui Paulo
12805b9c547cSRui Paulo os_free(resp_uri);
12815b9c547cSRui Paulo
12825b9c547cSRui Paulo if (ctx->pps_updated) {
12835b9c547cSRui Paulo wpa_printf(MSG_INFO, "Update wpa_supplicant credential based on updated PPS MO");
12845b9c547cSRui Paulo write_summary(ctx, "Update wpa_supplicant credential based on updated PPS MO and request connection");
12855b9c547cSRui Paulo cmd_set_pps(ctx, pps_fname);
12865b9c547cSRui Paulo if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) {
12875b9c547cSRui Paulo wpa_printf(MSG_INFO,
12885b9c547cSRui Paulo "Failed to request wpa_supplicant to reconnect");
12895b9c547cSRui Paulo write_summary(ctx,
12905b9c547cSRui Paulo "Failed to request wpa_supplicant to reconnect");
12915b9c547cSRui Paulo }
12925b9c547cSRui Paulo }
12935b9c547cSRui Paulo }
12945b9c547cSRui Paulo
12955b9c547cSRui Paulo
oma_dm_sub_rem(struct hs20_osu_client * ctx,const char * address,const char * pps_fname,const char * client_cert,const char * client_key,const char * cred_username,const char * cred_password,xml_node_t * pps)12965b9c547cSRui Paulo void oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
12975b9c547cSRui Paulo const char *pps_fname,
12985b9c547cSRui Paulo const char *client_cert, const char *client_key,
12995b9c547cSRui Paulo const char *cred_username, const char *cred_password,
13005b9c547cSRui Paulo xml_node_t *pps)
13015b9c547cSRui Paulo {
13025b9c547cSRui Paulo xml_node_t *syncml, *resp;
13035b9c547cSRui Paulo char *resp_uri = NULL;
13045b9c547cSRui Paulo int msgid = 0;
13055b9c547cSRui Paulo
13065b9c547cSRui Paulo wpa_printf(MSG_INFO, "OMA-DM subscription remediation");
13075b9c547cSRui Paulo write_summary(ctx, "OMA-DM subscription remediation");
13085b9c547cSRui Paulo
13095b9c547cSRui Paulo msgid++;
13105b9c547cSRui Paulo syncml = build_oma_dm_1_sub_rem(ctx, address, msgid);
13115b9c547cSRui Paulo if (syncml == NULL)
13125b9c547cSRui Paulo return;
13135b9c547cSRui Paulo
13145b9c547cSRui Paulo while (syncml) {
13155b9c547cSRui Paulo resp = oma_dm_send_recv(ctx, resp_uri ? resp_uri : address,
13165b9c547cSRui Paulo syncml, NULL, cred_username,
13175b9c547cSRui Paulo cred_password, client_cert, client_key);
13185b9c547cSRui Paulo if (resp == NULL)
13195b9c547cSRui Paulo return;
13205b9c547cSRui Paulo
13215b9c547cSRui Paulo msgid++;
13225b9c547cSRui Paulo syncml = oma_dm_process(ctx, address, resp, msgid, &resp_uri,
13235b9c547cSRui Paulo pps, pps_fname);
13245b9c547cSRui Paulo xml_node_free(ctx->xml, resp);
13255b9c547cSRui Paulo }
13265b9c547cSRui Paulo
13275b9c547cSRui Paulo os_free(resp_uri);
13285b9c547cSRui Paulo
13295b9c547cSRui Paulo wpa_printf(MSG_INFO, "Update wpa_supplicant credential based on updated PPS MO and request reconnection");
13305b9c547cSRui Paulo write_summary(ctx, "Update wpa_supplicant credential based on updated PPS MO and request reconnection");
13315b9c547cSRui Paulo cmd_set_pps(ctx, pps_fname);
13325b9c547cSRui Paulo if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) {
13335b9c547cSRui Paulo wpa_printf(MSG_INFO, "Failed to request wpa_supplicant to reconnect");
13345b9c547cSRui Paulo write_summary(ctx, "Failed to request wpa_supplicant to reconnect");
13355b9c547cSRui Paulo }
13365b9c547cSRui Paulo }
13375b9c547cSRui Paulo
13385b9c547cSRui Paulo
cmd_oma_dm_add(struct hs20_osu_client * ctx,const char * pps_fname,const char * add_fname)13395b9c547cSRui Paulo void cmd_oma_dm_add(struct hs20_osu_client *ctx, const char *pps_fname,
13405b9c547cSRui Paulo const char *add_fname)
13415b9c547cSRui Paulo {
13425b9c547cSRui Paulo xml_node_t *pps, *add;
13435b9c547cSRui Paulo int res;
13445b9c547cSRui Paulo
13455b9c547cSRui Paulo ctx->fqdn = os_strdup("wi-fi.org");
13465b9c547cSRui Paulo
13475b9c547cSRui Paulo pps = node_from_file(ctx->xml, pps_fname);
13485b9c547cSRui Paulo if (pps == NULL) {
13495b9c547cSRui Paulo wpa_printf(MSG_INFO, "PPS file %s could not be parsed",
13505b9c547cSRui Paulo pps_fname);
13515b9c547cSRui Paulo return;
13525b9c547cSRui Paulo }
13535b9c547cSRui Paulo
13545b9c547cSRui Paulo add = node_from_file(ctx->xml, add_fname);
13555b9c547cSRui Paulo if (add == NULL) {
13565b9c547cSRui Paulo wpa_printf(MSG_INFO, "Add file %s could not be parsed",
13575b9c547cSRui Paulo add_fname);
13585b9c547cSRui Paulo xml_node_free(ctx->xml, pps);
13595b9c547cSRui Paulo return;
13605b9c547cSRui Paulo }
13615b9c547cSRui Paulo
13625b9c547cSRui Paulo res = oma_dm_add(ctx, add, pps, pps_fname);
13635b9c547cSRui Paulo wpa_printf(MSG_INFO, "oma_dm_add --> %d", res);
13645b9c547cSRui Paulo
13655b9c547cSRui Paulo xml_node_free(ctx->xml, pps);
13665b9c547cSRui Paulo xml_node_free(ctx->xml, add);
13675b9c547cSRui Paulo }
13685b9c547cSRui Paulo
13695b9c547cSRui Paulo
cmd_oma_dm_replace(struct hs20_osu_client * ctx,const char * pps_fname,const char * replace_fname)13705b9c547cSRui Paulo void cmd_oma_dm_replace(struct hs20_osu_client *ctx, const char *pps_fname,
13715b9c547cSRui Paulo const char *replace_fname)
13725b9c547cSRui Paulo {
13735b9c547cSRui Paulo xml_node_t *pps, *replace;
13745b9c547cSRui Paulo int res;
13755b9c547cSRui Paulo
13765b9c547cSRui Paulo ctx->fqdn = os_strdup("wi-fi.org");
13775b9c547cSRui Paulo
13785b9c547cSRui Paulo pps = node_from_file(ctx->xml, pps_fname);
13795b9c547cSRui Paulo if (pps == NULL) {
13805b9c547cSRui Paulo wpa_printf(MSG_INFO, "PPS file %s could not be parsed",
13815b9c547cSRui Paulo pps_fname);
13825b9c547cSRui Paulo return;
13835b9c547cSRui Paulo }
13845b9c547cSRui Paulo
13855b9c547cSRui Paulo replace = node_from_file(ctx->xml, replace_fname);
13865b9c547cSRui Paulo if (replace == NULL) {
13875b9c547cSRui Paulo wpa_printf(MSG_INFO, "Replace file %s could not be parsed",
13885b9c547cSRui Paulo replace_fname);
13895b9c547cSRui Paulo xml_node_free(ctx->xml, pps);
13905b9c547cSRui Paulo return;
13915b9c547cSRui Paulo }
13925b9c547cSRui Paulo
13935b9c547cSRui Paulo res = oma_dm_replace(ctx, replace, pps, pps_fname);
13945b9c547cSRui Paulo wpa_printf(MSG_INFO, "oma_dm_replace --> %d", res);
13955b9c547cSRui Paulo
13965b9c547cSRui Paulo xml_node_free(ctx->xml, pps);
13975b9c547cSRui Paulo xml_node_free(ctx->xml, replace);
13985b9c547cSRui Paulo }
1399