Files
wlan-ucentral-schema/command/cmd_upgrade.uc
Arif Alam a6fdd32e40 cmd_upgrade: enable curl to follow redirects
Add -L flag to curl download command to automatically follow HTTP
redirects when downloading firmware images. This ensures that upgrade
operations work correctly when the firmware URI returns a redirect
response (e.g., 301, 302).

Signed-off-by: Arif Alam <arif.alam@netexperience.com>
2025-12-11 06:16:11 +01:00

159 lines
3.9 KiB
Ucode

let image_path = "/tmp/ucentral.upgrade";
function process_file(args, name, path) {
if (!args[name]) {
result(2, name + " is required in payload for secure download");
return false;
}
let content = b64dec(args[name]);
if (!content) {
result(2, "Failed to base64 decode " + name);
return false;
}
let f = fs.open(path, "w");
if (!f) {
result(2, "Failed to write " + name);
return false;
}
f.write(content);
f.close();
return true;
}
function download_run(cmd) {
let pipe = fs.popen(cmd);
if (!pipe)
return -1;
let out = trim(pipe.read("all"));
let ret = pipe.close();
return { "err": ret, "http_code": int(out) };
}
if (!args.uri) {
result(2, "No firmware URL provided");
return;
}
let secure_download = true;
let ca_file = "/etc/ucentral/operational.ca";
let cert_file = "/etc/ucentral/operational.pem";
let key_file = "/etc/ucentral/key.pem";
if (args['use-local-certificates'] == null) {
// Backwards compatibility: not provided by the cloud
secure_download = false;
}
else if (args['use-local-certificates'] == false) {
ca_file = "/tmp/_upgrade_cas.pem";
cert_file = "/tmp/_upgrade_cert.pem";
key_file = "/tmp/_upgrade_key.pem";
if (!process_file(args, "ca-certificate", ca_file))
return;
if (!process_file(args, "certificate", cert_file))
return;
if (!process_file(args, "private-key", key_file))
return;
}
let sargs = "";
if (secure_download) {
sargs = `--cacert ${ca_file} --cert ${cert_file} --key ${key_file}`;
}
let dl_cmd = `curl -L ${sargs} -w "%{http_code}" -o ${image_path} "${args.uri}"`;
let dl_ret = download_run(dl_cmd);
if (dl_ret.err != 0 || dl_ret.http_code < 200 || dl_ret.http_code >= 300) {
// Try a second time before erroring out
dl_ret = download_run(dl_cmd);
if (dl_ret.err != 0 || dl_ret.http_code < 200 || dl_ret.http_code >= 300) {
result(2, "Download failed, err %d, http_code %d, cmd %s", dl_ret.err, dl_ret.http_code, dl_cmd);
return;
}
}
let validation_result = ctx.call("system", "validate_firmware_image", { path: image_path });
if (!validation_result) {
result(2, "Validation call failed with status %s", ubus.error());
return;
}
else if (!validation_result.valid) {
result_json({
"error": 2,
"text": "Firmware image validation failed",
"data": sprintf("Archive command %s exited with non-zero code %d", archive_cmdline, rc)
});
warn(sprintf("ucentral-upgrade: firmware file validation failed: %J\n", validation_result));
return;
}
if (restrict.sysupgrade) {
let signature = require('signature');
if (!signature.verify(image_path, args.signature)) {
result_json({
"error": 2,
"text": "Invalid signature",
"resultCode": -1
});
return;
}
}
let archive_cmdline = [
'tar', 'czf', '/upgrade.tgz',
'/etc/config/ucentral'
];
if (args.keep_redirector) {
let files = [
"/etc/ucentral/key.pem", "/etc/ucentral/cert.pem",
"/etc/ucentral/gateway.json", "/etc/ucentral/profile.json",
"/etc/ucentral/operational.pem", "/etc/ucentral/operational.ca",
"/etc/ucentral/restrictions.json",
];
for (let f in files)
if (fs.stat(f))
push(archive_cmdline, f);
}
if (args.keep_config) {
let active_config = fs.readlink("/etc/ucentral/ucentral.active");
if (active_config)
push(archive_cmdline, '/etc/ucentral/ucentral.active', active_config);
else
result(2, "Unable to determine active configuration: %s", fs.error());
}
if (args.keep_redirector || args.keep_config) {
let rc = system(archive_cmdline);
if (rc != 0) {
result(2, "Archive command %s exited with non-zero code %d", archive_cmdline, rc);
return;
}
}
include('reboot_cause.uc', { reason: 'upgrade' });
result(0, "Triggering FW upgrade");
sleep(2000);
let sysupgrade_cmdline = sprintf("sysupgrade %s %s",
(args.keep_redirector || args.keep_config) ? "-f /upgrade.tgz" : "-n",
image_path);
warn("Upgrading firmware\n");
system("touch /ucentral.upgrade");
system("(sleep 10; /etc/init.d/network stop; " + sysupgrade_cmdline + ")&");
system("/etc/init.d/ucentral stop");