mirror of
https://github.com/openwrt/openwrt.git
synced 2025-03-21 03:25:22 +00:00
unetd: cli: add support for changing network password
This does not actually create a new private key. Instead, the salt is replaced, and a xor key is generated which when merged with the key derived from the new password transforms into the original private key. Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
2055b73ba4
commit
1be7036f69
@ -39,6 +39,7 @@ function network_get_string_file(str)
|
||||
let f = mkstemp();
|
||||
f.write(str);
|
||||
f.flush();
|
||||
f.seek();
|
||||
return f;
|
||||
}
|
||||
|
||||
@ -50,24 +51,52 @@ function network_get_file_string(f)
|
||||
return str;
|
||||
}
|
||||
|
||||
function __network_get_pubkey(pw_file, salt, rounds)
|
||||
function network_keygen(pw_file, args, config, out_file, extra_args)
|
||||
{
|
||||
let rounds = config.rounds;
|
||||
let salt = config.salt;
|
||||
let out, output, xorkey;
|
||||
|
||||
if (!out_file) {
|
||||
output = mkstemp();
|
||||
out_file = "/dev/fd/" + output.fileno();
|
||||
}
|
||||
|
||||
if (extra_args)
|
||||
extra_args = '"' + extra_args + '"';
|
||||
else
|
||||
extra_args = "";
|
||||
args += ` -s ${rounds},${salt} -o ${out_file}`;
|
||||
|
||||
if (config.xorkey) {
|
||||
xorkey = network_get_string_file(config.xorkey);
|
||||
args += " -x /dev/fd/" + xorkey.fileno();
|
||||
}
|
||||
|
||||
pw_file.seek();
|
||||
args += " <&" + pw_file.fileno() + " " + extra_args;
|
||||
let rc = system("unet-tool " + args);
|
||||
|
||||
let pubkey_file = mkstemp();
|
||||
if (system(`unet-tool -P -s ${rounds},${salt} <&${pw_file.fileno()} >&${pubkey_file.fileno()}`))
|
||||
return ctx.command_failed("Failed to generate public key");
|
||||
if (xorkey)
|
||||
xorkey.close();
|
||||
|
||||
pubkey_file.seek();
|
||||
let pubkey = trim(pubkey_file.read("all"));
|
||||
pubkey_file.close();
|
||||
if (output)
|
||||
out = network_get_file_string(output);
|
||||
else
|
||||
out = true;
|
||||
|
||||
return pubkey;
|
||||
if (rc != 0)
|
||||
return;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function network_get_pubkey(pw_file, network)
|
||||
{
|
||||
return __network_get_pubkey(pw_file, network.config.salt, network.config.rounds);
|
||||
let key = network_keygen(pw_file, '-P', network.config);
|
||||
if (!key)
|
||||
return ctx.command_failed("Failed to generate public key");
|
||||
return key;
|
||||
}
|
||||
|
||||
function __network_fetch_password(ctx, named, confirm)
|
||||
@ -81,7 +110,7 @@ function __network_fetch_password(ctx, named, confirm)
|
||||
return;
|
||||
}
|
||||
|
||||
let pw = model.cb.getpass("Network config password: ");
|
||||
let pw = model.cb.getpass((confirm ? "Set new" : "Network") + " config password: ");
|
||||
if (length(pw) < 12) {
|
||||
if (ctx.invalid_argument)
|
||||
ctx.invalid_argument("Password must be at least 12 characters long");
|
||||
@ -115,6 +144,16 @@ function network_fetch_password(ctx, named, confirm)
|
||||
return pw_file;
|
||||
}
|
||||
|
||||
function network_generate_salt()
|
||||
{
|
||||
let salt = readfile("/dev/urandom", 16);
|
||||
if (length(salt) != 16)
|
||||
return;
|
||||
salt = map(split(salt, ""), (v) => ord(v));
|
||||
salt = join("", map(salt, (v) => sprintf("%02x", v)));
|
||||
return salt;
|
||||
}
|
||||
|
||||
function network_sign_data(ctx, name, network, pw_file, upload)
|
||||
{
|
||||
let rounds = network.config.rounds;
|
||||
@ -125,12 +164,11 @@ function network_sign_data(ctx, name, network, pw_file, upload)
|
||||
let bin_file = "/etc/unetd/" + name + ".bin";
|
||||
if (upload)
|
||||
bin_file += "." + time();
|
||||
writefile(json_file, sprintf("%.J\n", network));
|
||||
|
||||
pw_file.seek();
|
||||
let ret = system(`unet-tool -S -s ${rounds},${salt} -o "${bin_file}" "${json_file}" <&${pw_file.fileno()}`);
|
||||
writefile(json_file, sprintf("%.J\n", network));
|
||||
let ret = network_keygen(pw_file, '-S', network.config, bin_file, json_file);
|
||||
unlink(json_file);
|
||||
if (ret) {
|
||||
if (!ret) {
|
||||
if (ctx.command_failed)
|
||||
ctx.command_failed("Failed to sign network configuration");
|
||||
return false;
|
||||
@ -301,17 +339,19 @@ function network_create(ctx, argv, named) {
|
||||
if (!pw_file)
|
||||
return;
|
||||
|
||||
let salt = readfile("/dev/urandom", 16);
|
||||
if (length(salt) != 16)
|
||||
let salt = network_generate_salt();
|
||||
if (!salt)
|
||||
return ctx.unknown_error();
|
||||
|
||||
salt = map(split(salt, ""), (v) => ord(v));
|
||||
salt = join("", map(salt, (v) => sprintf("%02x", v)));
|
||||
let rounds = 10000;
|
||||
|
||||
let xorkey_file = mkstemp();
|
||||
system(`unet-tool -G >&${xorkey_file.fileno()}`);
|
||||
let xorkey = network_get_file_string(xorkey_file);
|
||||
|
||||
let network = {
|
||||
config: {
|
||||
salt, rounds,
|
||||
salt, rounds, xorkey,
|
||||
},
|
||||
hosts: {},
|
||||
};
|
||||
@ -702,6 +742,48 @@ function network_edit_exit_hook()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function network_set_password(ctx, argv, named)
|
||||
{
|
||||
let netdata = ctx.data.netdata;
|
||||
let network = netdata.json;
|
||||
|
||||
let pw_file = network_fetch_password(ctx, named);
|
||||
if (!pw_file)
|
||||
return;
|
||||
|
||||
let salt = network_generate_salt();
|
||||
if (!salt)
|
||||
return ctx.unknown_error();
|
||||
|
||||
let rounds = 10000;
|
||||
let config = { ...network.config, salt };
|
||||
|
||||
let key = network_keygen(pw_file, '-G', network.config);
|
||||
pw_file.close();
|
||||
|
||||
named.password = named["new-password"];
|
||||
pw_file = network_fetch_password(ctx, named, true);
|
||||
if (!pw_file)
|
||||
return;
|
||||
|
||||
let key_file = network_get_string_file(key);
|
||||
delete config.xorkey;
|
||||
config.xorkey = network_keygen(pw_file, '-G -x /dev/fd/' + key_file.fileno(), config);
|
||||
key_file.close();
|
||||
|
||||
if (!config.xorkey) {
|
||||
delete named.password;
|
||||
return ctx.unknown_error("Error generating key");
|
||||
}
|
||||
|
||||
network.config = config;
|
||||
netdata.changed = true;
|
||||
netdata.password = named.password;
|
||||
|
||||
return ctx.ok();
|
||||
}
|
||||
|
||||
function network_edit(ctx, argv) {
|
||||
let network = argv[0];
|
||||
if (!network) {
|
||||
@ -766,7 +848,7 @@ const network_status_args = [
|
||||
}
|
||||
];
|
||||
|
||||
const network_sign_args = {
|
||||
const network_password_arg = {
|
||||
password: {
|
||||
help: "Network configuration password",
|
||||
no_complete: true,
|
||||
@ -777,10 +859,21 @@ const network_sign_args = {
|
||||
},
|
||||
};
|
||||
|
||||
const network_new_password_arg = {
|
||||
"new-password": {
|
||||
help: "New network configuration password",
|
||||
no_complete: true,
|
||||
args: {
|
||||
type: "string",
|
||||
min: 12,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const network_config_args = editor.object_create_params(UnetConfigEdit);
|
||||
|
||||
const network_create_args = {
|
||||
...network_sign_args,
|
||||
...network_password_arg,
|
||||
...network_config_args,
|
||||
...network_local_args,
|
||||
host: {
|
||||
@ -834,7 +927,7 @@ const network_join_args = {
|
||||
|
||||
const network_invite_args = {
|
||||
...network_enroll_args,
|
||||
...network_sign_args,
|
||||
...network_password_arg,
|
||||
};
|
||||
|
||||
const host_editor = {
|
||||
@ -1081,6 +1174,14 @@ let UnetEdit = {
|
||||
return ctx.json("Network data", ctx.data.netdata.json);
|
||||
}
|
||||
},
|
||||
password: {
|
||||
help: "Edit network password",
|
||||
call: network_set_password,
|
||||
named_args: {
|
||||
...network_password_arg,
|
||||
...network_new_password_arg
|
||||
}
|
||||
},
|
||||
save: {
|
||||
help: "Save network data to json file",
|
||||
args: [
|
||||
@ -1137,7 +1238,7 @@ let UnetEdit = {
|
||||
},
|
||||
apply: {
|
||||
help: "Apply changes",
|
||||
named_args: network_sign_args,
|
||||
named_args: network_password_arg,
|
||||
call: function(ctx, argv, named) {
|
||||
let netdata = ctx.data.netdata;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user