iMicknl / python-sagemcom-api

(Unofficial) Python wrapper to interact with SagemCom F@st routers via internal API's.
MIT License
83 stars 36 forks source link

[FAST 5688S] Unable to login #297

Open bunnis opened 4 months ago

bunnis commented 4 months ago

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:

  1. Copy the quickstart script. Fill out the necessary details
  2. Run it, observe error
  3. Change encryption method to MD5
  4. 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]

pgaskin commented 4 months ago

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.

bunnis commented 4 months ago

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);
pgaskin commented 4 months ago

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...

bunnis commented 4 months ago

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>
iMicknl commented 3 months ago

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.