[FAST 5688S] Unable to login
Model information
| Key | Value |
|---|---|
| Model name | FAST 5688S |
| Hardware Version | 1.0 |
| Software Version | SG_SIB2_05.008 |
Describe the bug
I used the quickstart script. I have tried both encryptions and I receive the usual error "Request timed-out. This is mainly due to using the wrong encryption method."
To Reproduce
Steps to reproduce the behavior:
- Copy the quickstart script. Fill out the necessary details
- Run it, observe error
- Change encryption method to MD5
- Run it, observe error
Expected behavior
Login would be succesfull and script would print additional inforamtion
Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
This device is not supported in your page, however I would be happy to work with you to make it supported. I suspect the encryption is sha1 because of the following payload when logging in (Note the ha1 field)
session={"req_id":80,"sess_id":1605671195,"basic":false,"user":"admin","dataModel":{"name":"Internal","nss":[{"name":"gtw","uri":"http://sagemcom.com/gateway-data"}]},"ha1":"REDACTED","nonce":"1890188387"}'
Running $.xmo.getValuesTree("Device/DeviceInfo") yields:
$.xmo.getValuesTree("Device/DeviceInfo")
{
"DeviceInfo": {
"DeviceCategory": "",
"Manufacturer": "Sagemcom",
"ManufacturerOUI": "001556",
"ModelName": "SIB2",
"ModelNumber": "Fast5688s_Sunrise",
"Description": "",
"ProductClass": "FAST5688s",
"SerialNumber": "REDACTED",
"HardwareVersion": "1.0",
"SoftwareVersion": "SG_SIB2_05.008",
"AdditionalHardwareVersion": "1.0",
"AdditionalSoftwareVersion": "",
"ExternalFirmwareVersion": "SG_SIB2_05.008",
"InternalFirmwareVersion": "F5688s_RC5_v5.0.71",
"GUIFirmwareVersion": "",
"GUIAPIVersion": "",
"ProvisioningCode": "LM-PONA0000004288.120",
"UpTime": 598238,
"FirstUseDate": "2021-01-29T12:58:28+0100",
"MACAddress": "REDACTED",
"Mode": "GW",
"Country": "fr",
"RebootCount": 33,
"NodesToRestore": "",
"VendorConfigFiles": [
{
"uid": 1,
"Alias": "DEVICE_CONFIG",
"Name": "device.cfg",
"Version": "",
"Date": "1-01-01T01:00:00+0100",
"Description": "Gateway device configuration",
"UseForBackupRestore": false
}
],
"MemoryStatus": {
"Total": 457276,
"Free": 137444
},
"TemperatureStatus": {
"TemperatureSensors": []
},
"NetworkProperties": {
"MaxTCPWindowSize": 0,
"TCPImplementation": "",
"EthernetWanType": "XGS\n"
},
"RouterName": "Sunrise_Wi-Fi_REDACTED",
"RebootStatus": 0,
"ResetStatus": 0,
"UpdateStatus": 0,
"SNMP": false,
"FirstConnection": false,
"SimpleLogs": {
"SystemLog": "",
"FirewallLog": "",
"CallLog": ""
},
"BuildDate": "2023-07-11T20:51:02+0200",
"SpecVersion": "1.0",
"CLID": "",
"FlushDeviceLog": false,
"Processors": [],
"VendorLogFiles": [
{
"uid": 1,
"Alias": "operator_log_X",
"Name": "",
"MaximumSize": 0,
"Persistent": false,
"LogData": "",
"DiagnosticState": "NONE",
"ReverseChronological": true
}
],
"ProxierInfo": {
"ManufacturerOUI": "",
"ProductClass": "",
"SerialNumber": "",
"ProxyProtocol": ""
},
"Locations": [],
"APIVersion": "",
"Logging": {
"LogLevel": "Warning",
"ResetLogOper": false
},
"BackupTimeStamp": "2024-04-11T00:47:05+0200",
"ConfigBackupRestoreEnable": false,
"LastBackupDate": "2024-04-11T00:47:05+0200",
"LastRestoreDate": "1-01-01T01:00:00+0100",
"EventLog": "",
"BackupSoftwareVersion": "SG_SIB2_04.038",
"BootloaderVersion": "3.12.6-sec",
"FlashMemoryStatus": {
"Total": 0,
"Free": 0
},
"CustomerModelName": "",
"UserConfigFiles": []
}
}
[bug]
Check if GUI_PASSWORD_SALT has a value in /gui/js/gui-core.js. If so, the _password_hash variable will need to hash password:salt rather than just password. This python library doesn't appear to handle that possibility.
Also see if there's another key like GUI_ACTIVATE_SHA512ENCODE_OPT defined in that same file. At least based on the code from the F5689E on GUI 7.3.28, this would mean SHA512 is used if 1, and MD5 otherwise.
GUI_PASSWORD_SALT and GUI_ACTIVATE_SHA512ENCODE_OPT don't exist in /gui/js/gui-core.js. Looking for SHA, PASS, SALT in this file yields 0 results.
I see some functions and variables with password in file gui/js/gui-api.js
The file is actually quite small:
/*!
* Copyright : (C) 2008,2009 SAGEM Communications - URD2
*
* This JavaScript file is the property of Sagem Communications
* and may not be copied or used without prior written consent.
*
* vim: set fileencoding=utf-8
*/
jQuery.gui = {};
jQuery.gui.api = {};
jQuery.gui.opt = {
GUI_VERSION_OPT: "0.1",
GUI_LANGUAGES_OPT: "en:fr",
GUI_DEFAULT_DATAMODEL_OPT: "gtw",
GUI_DEFAULT_LANG_OPT: "fr",
GUI_I18N_CGI_OPT: false,
GUI_SAVE_LOGIN_OPT: true,
XMO_REMOTE_HOST: "",
GUI_AJAX_TIMEOUT_OPT: 30,
GUI_ACTIVATE_GUI_CONSOLE_OPT: false,
};
(function (b, a) {
a.i18n = b.extend(
{},
{
files: [],
add: function (c) {
this.files.push.apply(this.files, arguments);
},
load: function (f, e) {
var c = function (j) {
var g = j.catalog;
for (var h in g) {
if (g.hasOwnProperty(h)) {
a.i18n[h] = g[h];
}
}
};
for (i = 0; i < this.files.length; i++) {
var d = this.files[i];
if (e !== undefined) {
d = d.replace(/%P/g, e);
}
d = d.replace(/%L/g, f);
b.ajax({ async: false, type: "GET", url: d, success: c, dataType: "json" });
}
},
msg: function (f, d) {
var e = this[f];
if (e !== undefined) {
var c = arguments;
if (c.length > 1) {
c[0] = e;
return b.sprintf.apply(b, c);
} else {
return e;
}
} else {
return b.sprintf(this.GUI_UNDEFINED_I18N_MSG, f);
}
},
alert: function (e, d) {
var c = arguments;
c[0] = this.msg(e);
a.alert.apply(a, c);
},
}
);
b.fn.guiTranslate = function () {
return this.each(function (c) {
b(this)
.find("*[xmsg]")
.each(function (d) {
var e = b(this);
e.html(a.i18n.msg(e.attr("xmsg")));
})
.end()
.find("*[xtitle]")
.each(function (d) {
var e = b(this);
e.attr("title", a.i18n.msg(e.attr("xtitle")));
})
.end()
.find("*[xhref]")
.each(function (d) {
var e = b(this);
e.attr("href", a.i18n.msg(e.attr("xhref")));
})
.end()
.find("*[xvalue]")
.each(function (d) {
var e = b(this);
e.attr("value", a.i18n.msg(e.attr("xvalue")));
});
});
};
b.extend(a.i18n, { GUI_UNDEFINED_I18N_MSG: "Undefined (%s)" });
})(jQuery, jQuery.gui);
(function (b, a) {
b.extend(
a,
{
INTMIN: -2147483648,
INTMAX: 2147483647,
UINTMIN: 0,
UINTMAX: 4294967295,
cnf: function (c) {
c.forceExtend = true;
c.isGuiConf = true;
return c;
},
array: function (d, c) {
if (arguments.length === 1 && a.isArray(d)) {
c = d;
d = null;
}
c.forceExtend = true;
c.isGuiArray = true;
c.elementConf = a.cnf(d);
c.compareElement = function (f, e) {
return e.id === f.id;
};
return c;
},
max: function (d, c) {
return d > c ? d : c;
},
min: function (d, c) {
return d < c ? d : c;
},
url: function (c) {
return c === undefined ? "" : 'url("/' + a.opt.GUI_VERSION_OPT + "/" + c + '")';
},
slice: function (f, j, d) {
var e = [],
h = arguments.length;
if (d !== undefined && d < h) {
h = d;
}
for (var g = j; g < h; g++) {
var c = f[g];
if (a.isArray(c)) {
e = e.concat(c);
} else {
e.push(c);
}
}
return e;
},
concat: function () {
var d = [],
f = arguments.length;
for (var e = 0; e < f; e++) {
var c = arguments[e];
if (a.isArray(c)) {
d = d.concat(c);
} else {
d.push(c);
}
}
return d;
},
typeOf: function (d) {
var c = typeof d;
if (c === "object") {
if (d) {
if (typeof d.length === "number" && !d.propertyIsEnumerable("length") && typeof d.splice === "function") {
c = "array";
}
} else {
c = "null";
}
}
return c;
},
isNull: function (c) {
return this.typeOf(c) === "null";
},
isString: function (c) {
return this.typeOf(c) === "string";
},
isNumber: function (c) {
return this.typeOf(c) === "number" && !isNaN(c);
},
isBoolean: function (c) {
return this.typeOf(c) === "boolean";
},
isArray: function (c) {
return this.typeOf(c) === "array";
},
isObject: function (d, c) {
return this.typeOf(d) === "object" && (c === undefined || d.constructor === c);
},
isFunction: function (c) {
return this.typeOf(c) === "function";
},
dump: function (c) {},
callTrace: function (c, d) {},
getMsg: function (c, d) {
if (a.isObject(c)) {
d = c.msg;
c = c.type;
}
if (c === "user") {
return d;
} else {
var e = a.messages[c];
if (e !== undefined && a.isString(e[d])) {
return e[d];
} else {
return a.messages.error.unknownMsg;
}
}
},
alert: function (d, c) {
alert(b.sprintf.apply(b, arguments));
},
messages: {
error: { unknownMsg: "Unknown GUI message !", noLoginForm: "You must define a login form !", noRefreshPage: "You must define a refresh function" },
warning: {},
info: { loading: "Loading '%s'. Please wait..." },
label: {},
},
pathValue: function (g, f, d) {
var e = f.split(".");
var h = g;
while (e.length) {
for (var c in h) {
if (c === e[0]) {
if (e.length === 1) {
if (d !== undefined) {
h[c] = d;
return;
} else {
return h[c];
}
}
h = h[c];
break;
}
}
e.shift();
}
},
uiNamespace: "gui",
uiWidget: function (e) {
var j = { uiClasses: "", prototype: {}, widgetDef: { setter: "", getter: "", getterSetter: "" } },
k,
h,
d,
c = function (o, p) {
var l,
n = { setter: "", getter: "", getterSetter: "" };
for (l in n) {
if (n.hasOwnProperty(l)) {
n[l] = o[l] + (p[l] ? " " + p[l] : "");
}
}
return n;
};
for (var f = 1; b.isFunction(arguments[f]); f++) {
b.extend(j.prototype, arguments[f].prototype);
if (j.uiClasses) {
j.uiClasses += " ";
}
j.uiClasses += arguments[f].uiClasses;
d = c(j.widgetDef, arguments[f].widgetDef);
b.extend(j.widgetDef, arguments[f].widgetDef, d);
}
h = arguments[f + 1];
k = arguments[f];
b.widget(this.uiNamespace + "." + e, b.extend(j.prototype, h));
var g = b[this.uiNamespace][e];
if (j.uiClasses) {
g.uiClasses = j.uiClasses + " " + e;
} else {
g.uiClasses = e;
}
d = c(g, j.widgetDef);
d = c(d, k);
g.widgetDef = b.extend(j.widgetDef, k, d);
b.extend(g, g.widgetDef);
},
access: function (c, d) {
if (d.check === undefined) {
d.check = function (e) {
return true;
};
}
b.fn[c] = function (e) {
if (e !== undefined) {
if (d.check(e)) {
return this.each(function (g) {
if (this.gui && b.isFunction(this.gui[d.set])) {
this.gui[d.set](e);
}
});
} else {
return this;
}
} else {
if (this.length === 1) {
var f = this.get(0);
if (f.gui && b.isFunction(f.gui[d.get])) {
return f.gui[d.get]();
}
}
}
};
},
formatTime: function (k, e, f) {
var n = Math.floor(k / 86400),
j = Math.floor(k / 3600) % 24,
c = Math.floor(k / 60) % 60,
g = k % 60,
l;
if (n > 0) {
l = f.replace("%j", String(n)).replace("%H", b.sprintf("%02d", j)).replace("%M", b.sprintf("%02d", c)).replace("%S", b.sprintf("%02d", g));
} else {
l = e.replace("%H", b.sprintf("%02d", j)).replace("%M", b.sprintf("%02d", c)).replace("%S", b.sprintf("%02d", g));
}
return l;
},
},
{
itemPath: [],
init: function (d) {
if (this.isString(d)) {
d = { language: arguments[0], dataModel: arguments[1] };
}
var e = b.extend({ language: this.opt.GUI_DEFAULT_LANG_OPT, dataModel: this.opt.GUI_DEFAULT_DATAMODEL_OPT, refreshPage: true }, d);
this.dataModel = this.dataModels[e.dataModel];
this.defaultClient = new this.api.Client();
if (e.language !== null) {
var g = b.cookie("lang", { path: "/" }) || e.language;
if (g) {
this.setLanguage(g, e.refreshPage);
} else {
if (navigator.userLanguage) {
this.setLanguage(navigator.userLanguage, e.refreshPage);
} else {
if (navigator.language) {
this.setLanguage(navigator.language, e.refreshPage);
} else {
this.setLanguage(e.refreshPage);
}
}
}
}
var c = this,
f = window.location.search.slice(1, window.location.search.length).split("&");
b.each(f, function () {
var h = this.split("=");
if (h[0] === "item") {
c.itemPath = h[1].split("/");
}
});
},
dataModels: [],
dataModel: null,
languages: [],
language: null,
setLanguage: function (d, c) {
if (!a.isString(d)) {
c = d;
d = undefined;
}
var e = this.languages[0];
for (i = 0; i < this.languages.length; i++) {
if (d === this.languages[i].lang) {
e = this.languages[i];
break;
}
}
c = (c === undefined ? true : c) && this.language && this.language.lang !== e.lang;
b.cookie("lang", e.lang, { path: "/", expires: 365 });
if (this.language === null || this.language.lang !== e.lang) {
this.i18n.load(e.lang);
}
this.language = e;
if (c) {
a.refreshPage();
}
},
openLoginForm: function () {},
refreshPage: function () {
a.i18n.alert("noRefreshPage");
},
}
);
b.ajaxSetup({ timeout: a.opt.GUI_AJAX_TIMEOUT_OPT * 1000 });
a.loadURL = function (d, c) {
if (!a.isBoolean(d)) {
c = d;
d = true;
}
if (c !== undefined && !a.isString(c)) {
c = b(c).attr("url");
}
return this.each(function (e) {
var g = this;
var f = c;
if (f === undefined) {
f = b(this).attr("url");
}
if (f === undefined) {
f = this.id.toLowerCase() + ".gtpl";
}
if (a.opt.GUI_I18N_CGI_OPT) {
f = "tpl/" + a.language.lang + "/" + f;
} else {
f = "tpl/src/" + f;
}
b(g).html("<div class='pageLoader'/>");
b.ajax({
async: d,
url: f,
success: function (h) {
a.currentTarget = g;
if (a.opt.GUI_I18N_CGI_OPT) {
b(g).html(h);
} else {
var j = '<script type="text/javascript">jQuery(function($){$($.gui.currentTarget).guiTranslate();});</script>';
b(g).html(j + h);
}
a.currentTarget = undefined;
},
error: function (h, j, k) {
b(g).html("<div id='errorBox'><div id='errorMsg'>" + a.i18n.msg("ERROR_TPL_LABEL") + "</div></div>");
},
});
});
};
jQuery.fn.guiLoadURL = a.loadURL;
b.fn.guiResize = function (d, c) {
if (b.browser.msie && b.browser.version < 7) {
this.each(function (g) {
var l = null;
var k = null;
if (d !== undefined) {
var j = b(this).css("left");
var f = b(this).css("right");
if (j !== "auto" && f !== "auto") {
l = d - (Number(j.replace("px", "")) + Number(f.replace("px", "")));
b(this).width(l);
}
}
if (c !== undefined) {
var h = b(this).css("top");
var e = b(this).css("bottom");
if (h !== "auto" && e !== "auto") {
k = c - (Number(h.replace("px", "")) + Number(e.replace("px", "")));
b(this).height(k);
}
}
if (l !== null || k !== null) {
b(this).children("div").guiResize(l, k);
}
});
}
return this;
};
a.isConf = function (c) {
return a.isObject(c) && c.isGuiConf;
};
a.isConfArray = function (c) {
return a.isArray(c) && c.isGuiArray;
};
a.extendFromDiv = function (d, f) {
if (f) {
var e = function (k) {
if (k !== undefined) {
var g = b(f).attr(c);
var h = b(f).children("div." + c + ", div#" + c);
if (g === undefined && h.length === 1) {
g = b(h).text();
}
var j = a.typeOf(k);
if (k === null) {
if (h.length) {
d[c] = h;
} else {
if (typeof g === "string") {
d[c] = g;
}
}
} else {
if (j === "string") {
if (h.length) {
d[c] = h.html();
} else {
if (typeof g === "string") {
d[c] = g;
} else {
if (c === "text" && d.text.length === 0) {
d.text = b(f).text();
}
}
}
} else {
if (j === "boolean") {
if (typeof g === "string") {
if (g.toLowerCase() === "true") {
d[c] = true;
} else {
if (g.toLowerCase() === "false") {
d[c] = false;
} else {
d[c] = Boolean(g);
}
}
}
} else {
if (j === "number") {
if (typeof g === "string") {
d[c] = Number(g);
}
} else {
if (a.isConf(k)) {
if (h.length === 1) {
a.extendFromDiv(d[c], h);
}
} else {
if (a.isConfArray(k)) {
b(h)
.children("div")
.each(function (m) {
var l,
n = k.length;
for (l = 0; l < n; l++) {
if (k.compareElement(this, k[l])) {
a.extendFromDiv(k[l], this);
break;
}
}
if (l === n) {
k.push(a.extend(this, k.elementConf));
}
});
}
}
}
}
}
}
h.remove();
}
};
for (var c in d) {
if (d.hasOwnProperty(c)) {
e(d[c]);
}
}
}
return d;
};
a.extend = function (d) {
var r = [],
l = arguments.length,
u;
var q, s;
var n, m, h;
for (n = 1; n < l; n++) {
s = a.typeOf((u = arguments[n]));
if (s === "object") {
r.push(u);
} else {
if (s === "array") {
for (m in u) {
if (u.hasOwnProperty(m)) {
q = u[m];
if (a.typeOf(q) === "object") {
r.push(q);
}
}
}
}
}
}
q = a.isConf(this) ? this : a.cnf({});
for (n in r) {
if (r.hasOwnProperty(n)) {
u = r[n];
for (var c in u) {
if (u.hasOwnProperty(c)) {
var g = u[c];
s = a.typeOf(g);
if (a.isConf(g)) {
if (a.isConf(q[c])) {
a.extend.call(q[c], null, g);
} else {
if (q[c] === undefined) {
q[c] = a.extend(null, g);
}
}
} else {
if (a.isArray(g)) {
var o = q[c];
var f = 0,
p,
t;
if (a.isArray(o)) {
f = o.length;
p = o.elementConf;
t = o.compareElement;
} else {
if (o === undefined) {
p = g.elementConf;
t = g.compareElement;
o = q[c] = a.array(p, []);
o.compareElement = t;
}
}
var e = g.length;
for (m = 0; m < e; m++) {
for (h = 0; h < f; h++) {
if (t(o[h], g[m])) {
a.extend.call(o[h], null, g[m]);
break;
}
}
if (h === f && a.typeOf(g[m]) === "object") {
o.push(a.extend(null, p, g[m]));
}
}
} else {
if (s === "null") {
q[c] = null;
} else {
if (c !== "isGuiConfig" && g !== undefined) {
q[c] = g;
}
}
}
}
}
}
}
}
return a.extendFromDiv(q, d);
};
b.fn.guiCookie = function (c, e) {
if (e) {
return this.each(function (h) {
if (this.id) {
var g = this.id + "." + c;
b.cookie(g, e);
}
});
} else {
if (this.length === 1) {
var f = this.get(0);
if (f.id) {
var d = f.id + "." + c;
return b.cookie(d);
}
}
}
};
b.QueryString = function (e) {
var g,
c = null,
d,
j = {};
if (e === undefined) {
c = window.location.search.substr(1);
} else {
d = e.indexOf("?");
if (d === -1) {
return {};
}
c = e.substring(d + 1);
}
g = c.split("&");
if (g === "") {
return {};
}
for (var f = 0; f < g.length; ++f) {
var h = g[f].split("=");
if (h.length !== 2) {
continue;
}
j[h[0]] = decodeURIComponent(h[1].replace(/\+/g, " "));
}
return j;
};
a.fval = function (c) {
if (c !== undefined) {
if (typeof c === "string") {
if (!(c.indexOf("http") === 0)) {
c = b("<div>").text(c).html();
}
} else {
b.each(c, function (d, e) {
c[d] = a.fval(e);
});
}
}
return c;
};
a.fec = function (c) {
if (c !== undefined && typeof c === "string") {
c = c.replace(/`|"|;|\$\(/g, "");
}
return c;
};
})(jQuery, jQuery.gui);
if (!window.console) {
var console = {};
}
$.each(["log", "error", "warn", "info", "debug", "assert", "count", "dir", "dirxml", "trace", "group", "groupEnd", "time", "timeEnd", "profile", "profileEnd"], function (a, b) {
if (!console[b]) {
console[b] = function () {};
}
});
(function (a) {
a.languages.push({ lang: "en", name: "English" });
})(jQuery.gui);
(function (a) {
a.languages.push({ lang: "fr", name: "Français" });
})(jQuery.gui);
jQuery.gui.dataModels.gtw = { name: "Internal", nss: [{ name: "gtw", uri: "http://sagemcom.com/gateway-data" }] };
jQuery.gui.dataModels.push(jQuery.gui.dataModels.gtw);
jQuery.gui.dataModels.tr181 = { name: "TR-181", nss: [{ name: "tr181", uri: "http://sagemcom.com/tr181-data" }] };
jQuery.gui.dataModels.push(jQuery.gui.dataModels.tr181);
jQuery.gui.dataModels.tr181sunrise = {
name: "TR-181 Sunrise",
nss: [
{ name: "tr181", uri: "http://sagemcom.com/tr181-data" },
{ name: "tr181sunrise", uri: "http://sagemcom.com/tr181sunrise-data" },
],
};
jQuery.gui.dataModels.push(jQuery.gui.dataModels.tr181sunrise);
Hmm, that seems pretty different than the HH4000 and GH4000, which are the only ones I've personally used. There's no hashEncoder function in gui-core in yours.
I'd probably look at gui-api.js and search for :JSON:/cgi/json-req, and see what the code to build the auth token looks like there.
Some relevant snippets from the GH4000:
n=c.random(a.UINTMAX);lNonce="";if(g._nonce!=undefined&&g._nonce!=""){lNonce=g._nonce}g._ha1=a.hashEncoder(g.user+":"+lNonce+":"+g._hashEncoderPass);e=a.hashEncoder(g._ha1+":"+f+":"+n+":JSON:/cgi/json-req");c.extend(t.request,{cnonce:n,"auth-key":e})
if(a.opt.GUI_PASSWORD_SALT!==""){l._hashEncoderPass=a.hashEncoder(k+":"+a.opt.GUI_PASSWORD_SALT)}else{l._hashEncoderPass=a.hashEncoder(k)}}l._nonce="";l._ha1=a.hashEncoder(l.user+"::"+l._hashEncoderPass)
Another observation: GUI_VERSION_OPT is pretty old...
Jquery library used is from April 2012
// jQuery Form Plugin
//version: 3.09 (16-APR-2012)
// @requires jQuery v1.3.2 or later
With your hints I was able to figure out the way the password encryption is done. I have created a simple HTML page that will perform this math, basically its just a bunch of md5's together with a nounce. The request payload will then look like this, relevant fields are cnonce and auth-key.
{"request":{"id":0,"session-id":"0","priority":true,"actions":[{"id":0,"method":"logIn","parameters":{"user":"admin","persistent":"true","session-options":{"nss":[{"name":"gtw","uri":"http://sagemcom.com/gateway-data"}],"language":"ident","context-flags":{"get-content-name":true,"local-time":true},"capability-depth":2,"capability-flags":{"name":true,"default-value":false,"restriction":true,"description":false},"time-format":"ISO_8601"}}}],"cnonce":3557024231,"auth-key":"8e84346a12415de0a87c85851c8bfa77"}}
The HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MD5 Hash Example</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.18.0/js/md5.min.js"></script>
</head>
<body>
<h1>MD5 Hash Calculation</h1>
<form id="hashForm">
<label for="username">User:</label>
<input type="text" id="username" name="username" required>
<label for="md5password">Password:</label>
<input type="text" id="md5password" name="md5password" required>
<button type="button" onclick="calculateHash()">Calculate Hash</button>
</form>
<p>Nonce: <span id="nonce"></span></p>
<p>Random Number (n): <span id="randomNumber"></span></p>
<p>Hash (e): <span id="hashValue"></span></p>
<script>
function calculateHash() {
const UINTMAX = 4294967295;
function random(max) {
return Math.floor(Math.random() * max);
}
const user = document.getElementById('username').value;
const md5Pass = md5(document.getElementById('md5password').value);
let n = random(UINTMAX);
//n=3557024231
let f = 0;
let lNonce = ""; // Initialize lNonce if needed
function hex_md5(input) {
return md5(input);
}
let ha1 = hex_md5(user + ":" + lNonce + ":" + md5Pass);
let e = hex_md5(ha1 + ":" + f + ":" + n + ":JSON:/cgi/json-req");
// Output to HTML
$('#nonce').text(n);
document.getElementById('randomNumber').textContent = n;
document.getElementById('hashValue').textContent = e;
}
</script>
</body>
</html>
Great research all!
@bunnis would you be open to do a PR to add this to this repository? Otherwise I am happy to have a look, but would be great to understand in more detail what is currently missing.
I was able to implement the new encryption method and associated password hash with #352, but now I get thrown some other errors I did not have time to review. Could you maybe take a look?
Traceback (with my branch):
Traceback (most recent call last): File "sunrise.py", line 44, in <module> asyncio.run(main()) File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete return future.result() File "sunrise.py", line 21, in main device_info = await client.get_device_info() File "/home/bunnis/.local/lib/python3.8/site-packages/backoff/_async.py", line 151, in retry ret = await target(*args, **kwargs) File "/home/bunnis/python-sagemcom-api/sagemcom_api/client.py", line 505, in get_device_info return DeviceInfo(**data["device_info"]) TypeError: string indices must be integers
Here is one of the response payloads that will have the skeleton you are traversing:
{ "reply": { "uid": 0, "id": 2, "error": { "code": 16777236, "description": "XMO_REQUEST_ACTION_ERR" }, "actions": [ { "uid": 1, "id": 0, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/UserInterface\/CurrentLanguage", "parameters": { "value": "EN", "capability": { "name": "CurrentLanguage", "type": "userifc:UserInterface:CurrentLanguage xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "", "restrictions": { "max-length": 16 } } } } ] }, { "uid": 2, "id": 1, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DeviceInfo\/ModelName", "parameters": { "value": "SIB2", "capability": { "name": "ModelName", "type": "devinfo:DeviceInfo:ModelName xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 64 } } } } ] }, { "uid": 3, "id": 2, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DNS\/Client\/HostName", "parameters": { "value": "sunrise", "capability": { "name": "HostName", "type": "dns:DNS:Client:HostName xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 256 } } } } ] }, { "uid": 4, "id": 3, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DNS\/Client\/LocalDomains", "parameters": { "value": "box", "capability": { "name": "LocalDomains", "type": "dns:DNS:Client:LocalDomains types:domains xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 1024, "reg-exp": { "pattern": "^[-_A-Za-z0-9.,]*$" } } } } } ] }, { "uid": 5, "id": 4, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/IP\/Interfaces\/Interface[@uid='1']\/IPv4Addresses\/IPv4Address[@uid='1']\/IPAddress", "parameters": { "value": "192.168.200.1", "capability": { "name": "IPAddress", "type": "types:IPv4Address xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 15, "reg-exp": { "pattern": "^(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9]))?$" } } } } } ] }, { "uid": 6, "id": 5, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/IP\/Interfaces\/Interface[@uid='1']\/IPv6Addresses", "parameters": { "value": [ { "uid": 1, "Enable": true, "Status": "DISABLED", "IPAddressStatus": "UNKNOWN", "Alias": "LINK_LOCAL", "IPAddress": "", "Origin": "STATIC", "Prefix": "Device\/IP\/Interfaces\/Interface[IP_BR_LAN]\/IPv6Prefixes\/IPv6Prefix[LINK_LOCAL]", "PreferredLifetime": "-72-06-20T23:55:59+0100", "ValidLifetime": "-72-06-20T23:55:59+0100", "Anycast": false }, { "uid": 2, "Enable": true, "Status": "DISABLED", "IPAddressStatus": "UNKNOWN", "Alias": "ULA_LAN", "IPAddress": "fdaa:bbcc:ddee:0:12d7:b0ff:fed5:59f5", "Origin": "STATIC", "Prefix": "Device\/IP\/Interfaces\/Interface[IP_BR_LAN]\/IPv6Prefixes\/IPv6Prefix[@uid=2]", "PreferredLifetime": "1-01-01T00:59:59+0100", "ValidLifetime": "1-01-01T00:59:59+0100", "Anycast": false }, { "uid": 3, "Enable": true, "Status": "DISABLED", "IPAddressStatus": "UNKNOWN", "Alias": "SCOPE_GLOBAL_LAN", "IPAddress": "", "Origin": "STATIC", "Prefix": "Device\/IP\/Interfaces\/Interface[IP_BR_LAN]\/IPv6Prefixes\/IPv6Prefix[SCOPE_GLOBAL_LAN]", "PreferredLifetime": "-72-06-20T23:55:59+0100", "ValidLifetime": "-72-06-20T23:55:59+0100", "Anycast": false } ], "capability": { "name": "IPv6Addresses", "type": "ip:Interface:IPv6Addresses xmo:list xmo:container", "flags": { "list": true, "config": true, "xml-child": true }, "children": [ { "name": "IPv6Address", "type": "ip:Interface:IPv6Addresses:IPv6Address xmo:list-node xmo:uid-node xmo:extended-node xmo:child-node xmo:node", "flags": { "node": true, "config": true, "capability": true, "xml-child": true }, "attributes": [ { "name": "uid", "type": "xmo:uint32 xmo:number xmo:value", "flags": { "value": true, "read-only": true, "key": true, "xml-attribute": true } }, { "name": "Enable", "type": "ip:Interface:IPv6Addresses:IPv6Address:Enable xmo:boolean xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "false" }, { "name": "Status", "type": "ip:Interface:IPv6Addresses:IPv6Address:Status xmo:int32 xmo:number xmo:value", "flags": { "value": true, "status": true, "xml-child": true }, "default-value": "Disabled", "restrictions": { "enum-values": [ { "name": "DISABLED", "value": "0" }, { "name": "ENABLED", "value": "1" }, { "name": "ERROR_MISCONFIGURED", "value": "2" }, { "name": "ERROR", "value": "3" } ] } }, { "name": "IPAddressStatus", "type": "ip:Interface:IPv6Addresses:IPv6Address:IPAddressStatus xmo:int32 xmo:number xmo:value", "flags": { "value": true, "status": true, "xml-child": true }, "default-value": "Invalid", "restrictions": { "enum-values": [ { "name": "PREFERRED", "value": "0" }, { "name": "DEPRECATED", "value": "1" }, { "name": "INVALID", "value": "2" }, { "name": "INACCESSIBLE", "value": "3" }, { "name": "UNKNOWN", "value": "4" }, { "name": "TENTATIVE", "value": "5" }, { "name": "DUPLICATE", "value": "6" }, { "name": "OPTIMISTIC", "value": "7" } ] } }, { "name": "Alias", "type": "ip:Interface:IPv6Addresses:IPv6Address:Alias xmo:str xmo:value", "flags": { "value": true, "key": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 64 } }, { "name": "IPAddress", "type": "ip:Interface:IPv6Addresses:IPv6Address:IPAddress types:IPv6Address xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "" }, { "name": "Origin", "type": "ip:Interface:IPv6Addresses:IPv6Address:Origin xmo:int32 xmo:number xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "STATIC", "restrictions": { "enum-values": [ { "name": "AUTOCONFIGURED", "value": "0" }, { "name": "DHCPV6", "value": "1" }, { "name": "WELLKNOWN", "value": "2" }, { "name": "STATIC", "value": "3" } ] } }, { "name": "Prefix", "type": "ip:Interface:IPv6Addresses:IPv6Address:Prefix xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "" }, { "name": "PreferredLifetime", "type": "ip:Interface:IPv6Addresses:IPv6Address:PreferredLifetime xmo:time xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "9999-12-31T23:59:59Z" }, { "name": "ValidLifetime", "type": "ip:Interface:IPv6Addresses:IPv6Address:ValidLifetime xmo:time xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "9999-12-31T23:59:59Z" }, { "name": "Anycast", "type": "ip:Interface:IPv6Addresses:IPv6Address:Anycast xmo:boolean xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "false" } ] } ], "attributes": [ { "name": "element-count", "type": "xmo:list:element-count xmo:value", "flags": { "value": true, "read-only": true, "element-count": true, "xml-attribute": true }, "default-value": "0" }, { "name": "new-id", "type": "xmo:list:alloc-index xmo:uint32 xmo:number xmo:value", "flags": { "value": true, "alloc-index": true, "xml-attribute": true }, "default-value": "1" } ] } } } ] }, { "uid": 7, "id": 6, "error": { "code": 16777242, "description": "XMO_UNKNOWN_PATH_ERR" }, "callbacks": [] }, { "uid": 8, "id": 7, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/IP\/Interfaces\/Interface[@uid='3']\/IPv4Addresses\/IPv4Address[@uid='1']\/IPAddress", "parameters": { "value": "188.154.121.21", "capability": { "name": "IPAddress", "type": "types:IPv4Address xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 15, "reg-exp": { "pattern": "^(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9]))?$" } } } } } ] }, { "uid": 9, "id": 8, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/IP\/Interfaces\/Interface[@uid='3']\/IPv6Addresses", "parameters": { "value": [ { "uid": 1, "Enable": true, "Status": "DISABLED", "IPAddressStatus": "UNKNOWN", "Alias": "LINK_LOCAL", "IPAddress": "", "Origin": "STATIC", "Prefix": "Device\/IP\/Interfaces\/Interface[IP_DATA]\/IPv6Prefixes\/IPv6Prefix[LINK_LOCAL]", "PreferredLifetime": "-72-06-20T23:55:59+0100", "ValidLifetime": "-72-06-20T23:55:59+0100", "Anycast": false } ], "capability": { "name": "IPv6Addresses", "type": "ip:Interface:IPv6Addresses xmo:list xmo:container", "flags": { "list": true, "config": true, "xml-child": true }, "children": [ { "name": "IPv6Address", "type": "ip:Interface:IPv6Addresses:IPv6Address xmo:list-node xmo:uid-node xmo:extended-node xmo:child-node xmo:node", "flags": { "node": true, "config": true, "capability": true, "xml-child": true }, "attributes": [ { "name": "uid", "type": "xmo:uint32 xmo:number xmo:value", "flags": { "value": true, "read-only": true, "key": true, "xml-attribute": true } }, { "name": "Enable", "type": "ip:Interface:IPv6Addresses:IPv6Address:Enable xmo:boolean xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "false" }, { "name": "Status", "type": "ip:Interface:IPv6Addresses:IPv6Address:Status xmo:int32 xmo:number xmo:value", "flags": { "value": true, "status": true, "xml-child": true }, "default-value": "Disabled", "restrictions": { "enum-values": [ { "name": "DISABLED", "value": "0" }, { "name": "ENABLED", "value": "1" }, { "name": "ERROR_MISCONFIGURED", "value": "2" }, { "name": "ERROR", "value": "3" } ] } }, { "name": "IPAddressStatus", "type": "ip:Interface:IPv6Addresses:IPv6Address:IPAddressStatus xmo:int32 xmo:number xmo:value", "flags": { "value": true, "status": true, "xml-child": true }, "default-value": "Invalid", "restrictions": { "enum-values": [ { "name": "PREFERRED", "value": "0" }, { "name": "DEPRECATED", "value": "1" }, { "name": "INVALID", "value": "2" }, { "name": "INACCESSIBLE", "value": "3" }, { "name": "UNKNOWN", "value": "4" }, { "name": "TENTATIVE", "value": "5" }, { "name": "DUPLICATE", "value": "6" }, { "name": "OPTIMISTIC", "value": "7" } ] } }, { "name": "Alias", "type": "ip:Interface:IPv6Addresses:IPv6Address:Alias xmo:str xmo:value", "flags": { "value": true, "key": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 64 } }, { "name": "IPAddress", "type": "ip:Interface:IPv6Addresses:IPv6Address:IPAddress types:IPv6Address xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "" }, { "name": "Origin", "type": "ip:Interface:IPv6Addresses:IPv6Address:Origin xmo:int32 xmo:number xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "STATIC", "restrictions": { "enum-values": [ { "name": "AUTOCONFIGURED", "value": "0" }, { "name": "DHCPV6", "value": "1" }, { "name": "WELLKNOWN", "value": "2" }, { "name": "STATIC", "value": "3" } ] } }, { "name": "Prefix", "type": "ip:Interface:IPv6Addresses:IPv6Address:Prefix xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "" }, { "name": "PreferredLifetime", "type": "ip:Interface:IPv6Addresses:IPv6Address:PreferredLifetime xmo:time xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "9999-12-31T23:59:59Z" }, { "name": "ValidLifetime", "type": "ip:Interface:IPv6Addresses:IPv6Address:ValidLifetime xmo:time xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "9999-12-31T23:59:59Z" }, { "name": "Anycast", "type": "ip:Interface:IPv6Addresses:IPv6Address:Anycast xmo:boolean xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "false" } ] } ], "attributes": [ { "name": "element-count", "type": "xmo:list:element-count xmo:value", "flags": { "value": true, "read-only": true, "element-count": true, "xml-attribute": true }, "default-value": "0" }, { "name": "new-id", "type": "xmo:list:alloc-index xmo:uint32 xmo:number xmo:value", "flags": { "value": true, "alloc-index": true, "xml-attribute": true }, "default-value": "1" } ] } } } ] }, { "uid": 10, "id": 9, "error": { "code": 16777242, "description": "XMO_UNKNOWN_PATH_ERR" }, "callbacks": [] }, { "uid": 11, "id": 10, "error": { "code": 16777242, "description": "XMO_UNKNOWN_PATH_ERR" }, "callbacks": [] }, { "uid": 12, "id": 11, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DeviceInfo\/HardwareVersion", "parameters": { "value": "1.0", "capability": { "name": "HardwareVersion", "type": "devinfo:DeviceInfo:HardwareVersion xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 64 } } } } ] }, { "uid": 13, "id": 12, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DeviceInfo\/ExternalFirmwareVersion", "parameters": { "value": "SG_SIB2_05.008", "capability": { "name": "ExternalFirmwareVersion", "type": "devinfo:DeviceInfo:ExternalFirmwareVersion xmo:str xmo:value", "flags": { "value": true, "status": true, "xml-child": true }, "restrictions": { "max-length": 64 } } } } ] }, { "uid": 14, "id": 13, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DeviceInfo\/SoftwareVersion", "parameters": { "value": "SG_SIB2_05.008", "capability": { "name": "SoftwareVersion", "type": "devinfo:DeviceInfo:SoftwareVersion xmo:str xmo:value", "flags": { "value": true, "status": true, "xml-child": true }, "restrictions": { "max-length": 64 } } } } ] }, { "uid": 15, "id": 14, "error": { "code": 16777242, "description": "XMO_UNKNOWN_PATH_ERR" }, "callbacks": [] }, { "uid": 16, "id": 15, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DeviceInfo\/UpTime", "parameters": { "value": 5104676, "capability": { "name": "UpTime", "type": "xmo:uint32 xmo:number xmo:value", "flags": { "value": true, "statistic": true, "xml-child": true } } } } ] }, { "uid": 17, "id": 16, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/Managers\/NetworkData\/InterfaceType", "parameters": { "value": "FTTH", "capability": { "name": "InterfaceType", "type": "managers:InterfaceType xmo:int32 xmo:number xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "ADSL", "restrictions": { "enum-values": [ { "name": "ADSL", "value": "0" }, { "name": "VDSL", "value": "1" }, { "name": "FTTH", "value": "2" }, { "name": "ADSL_BOND", "value": "3" }, { "name": "VDSL_BOND", "value": "4" }, { "name": "ALL", "value": "5" }, { "name": "NONE", "value": "6" }, { "name": "LTE", "value": "7" } ] } } } } ] }, { "uid": 18, "id": 17, "error": { "code": 16777242, "description": "XMO_UNKNOWN_PATH_ERR" }, "callbacks": [] }, { "uid": 19, "id": 18, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DeviceInfo\/SerialNumber", "parameters": { "value": "10D7B0D559F0", "capability": { "name": "SerialNumber", "type": "devinfo:DeviceInfo:SerialNumber xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "restrictions": { "max-length": 64 } } } } ] }, { "uid": 20, "id": 19, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DeviceInfo\/MACAddress", "parameters": { "value": "10:D7:B0:D5:59:F0", "capability": { "name": "MACAddress", "type": "devinfo:DeviceInfo:MACAddress xmo:str xmo:value", "flags": { "value": true, "status": true, "xml-child": true }, "restrictions": { "max-length": 64 } } } } ] }, { "uid": 21, "id": 20, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/DeviceInfo\/Country", "parameters": { "value": "fr", "capability": { "name": "Country", "type": "devinfo:DeviceInfo:Country xmo:str xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "fr", "restrictions": { "min-length": 2, "max-length": 64 } } } } ] }, { "uid": 22, "id": 21, "error": { "code": 16777242, "description": "XMO_UNKNOWN_PATH_ERR" }, "callbacks": [] }, { "uid": 23, "id": 22, "error": { "code": 16777238, "description": "XMO_NO_ERR" }, "callbacks": [ { "uid": 1, "result": { "code": 16777238, "description": "XMO_NO_ERR" }, "xpath": "Device\/UserInterface\/RedirectionReason", "parameters": { "value": "NONE", "capability": { "name": "RedirectionReason", "type": "userifc:UserInterface:RedirectionReason xmo:int32 xmo:number xmo:value", "flags": { "value": true, "config": true, "xml-child": true }, "default-value": "NONE", "restrictions": { "enum-values": [ { "name": "NONE", "value": "0" }, { "name": "NOINTERNET", "value": "1" }, { "name": "FIRMWAREUPGRADE", "value": "2" } ] } } } } ] } ], "events": [] } }
Added in v1.4.0! many thanks @bunnis