luci-app-sshtunnel: extract a public key from a key if no .pub

For the Dropbear keys without a .pub we need to fall back and execute the -y command to extract a pubkey from a private.

Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
This commit is contained in:
Sergey Ponomarev 2023-12-17 16:52:58 +02:00 committed by Paul Donald
parent 949e7cbcb3
commit 8755aa3a71
2 changed files with 52 additions and 33 deletions

View file

@ -20,7 +20,7 @@ return view.extend({
for (var sshKeyName of sshKeyNames) {
var sshPubKeyName = sshKeyName + '.pub';
tasks.push(Promise.resolve(sshKeyName));
tasks.push(fs.lines('/root/.ssh/' + sshPubKeyName));
tasks.push(_loadPublicKey(sshPubKeyName));
}
return Promise.all(tasks);
});
@ -45,29 +45,25 @@ return view.extend({
});
function _findAllPossibleIdKeys(entries) {
var sshKeyNames = [];
for (var item of entries) {
if (item.type !== 'file') {
continue
}
var sshKeyNames = new Set();
var fileNames = entries.filter(item => item.type === 'file').map(item => item.name);
for (var fileName of fileNames) {
// a key file should have a corresponding .pub file
if (item.name.endsWith('.pub')) {
var sshPubKeyName = item.name;
var sshKeyName = sshPubKeyName.substring(0, sshPubKeyName.length - 4);
if (!sshKeyNames.includes(sshKeyName)) {
sshKeyNames.push(sshKeyName)
if (fileName.endsWith('.pub')) {
var sshKeyName = fileName.slice(0, -4);
// if such a key exists then add it
if (fileNames.includes(sshKeyName)) {
sshKeyNames.add(sshKeyName);
}
} else {
// or at least it should start with id_ e.g. id_dropbear
if (item.name.startsWith('id_')) {
var sshKeyName = item.name;
if (!sshKeyNames.includes(sshKeyName)) {
sshKeyNames.push(sshKeyName)
}
if (fileName.startsWith('id_')) {
var sshKeyName = fileName;
sshKeyNames.add(sshKeyName);
}
}
}
return sshKeyNames;
return Array.from(sshKeyNames);
}
function _splitSshKeys(sshFiles) {
@ -158,3 +154,30 @@ function _handleKeyGenSubmit(event) {
});
return false;
}
function _extractPubKeyFromOutput(res) {
var lines = res.stdout.split('\n');
for (var line of lines) {
if (line.startsWith('ssh-')) {
return line;
}
}
return '';
}
function _loadPublicKey(sshPubKeyName) {
return fs.read('/root/.ssh/' + sshPubKeyName)
.catch(() => {
// If there is no the .pub file then this is probably a Dropbear key e.g. id_dropbear.
// We can extract it's public key by executing: dropbearkey -y -f /root/.ssh/id_dropbear
var sshKeyName = sshPubKeyName.substring(0, sshPubKeyName.length - 4);
return fs.exec('/usr/bin/dropbearkey', ['-y', '-f', '/root/.ssh/' + sshKeyName]).then((res) => {
if (res.code === 0) {
return _extractPubKeyFromOutput(res);
} else {
console.log('dropbearkey: ' + res.stdout + ' ' + res.stderr);
return '';
}
}).catch(()=> '');
});
}

View file

@ -129,27 +129,23 @@ return view.extend({
});
function _findAllPossibleIdKeys(entries) {
var sshKeyNames = [];
for (var item of entries) {
if (item.type !== 'file') {
continue
}
var sshKeyNames = new Set();
var fileNames = entries.filter(item => item.type === 'file').map(item => item.name);
for (var fileName of fileNames) {
// a key file should have a corresponding .pub file
if (item.name.endsWith('.pub')) {
var sshPubKeyName = item.name;
var sshKeyName = sshPubKeyName.substring(0, sshPubKeyName.length - 4);
if (!sshKeyNames.includes(sshKeyName)) {
sshKeyNames.push(sshKeyName)
if (fileName.endsWith('.pub')) {
var sshKeyName = fileName.slice(0, -4);
// if such a key exists then add it
if (fileNames.includes(sshKeyName)) {
sshKeyNames.add(sshKeyName);
}
} else {
// or at least it should start with id_ e.g. id_dropbear
if (item.name.startsWith('id_')) {
var sshKeyName = item.name;
if (!sshKeyNames.includes(sshKeyName)) {
sshKeyNames.push(sshKeyName)
}
if (fileName.startsWith('id_')) {
var sshKeyName = fileName;
sshKeyNames.add(sshKeyName);
}
}
}
return sshKeyNames;
return Array.from(sshKeyNames);
}