xref: /freebsd/contrib/wpa/hs20/client/oma_dm_client.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
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