luci-app-sshtunnel: extract a public key from a key if no .pub
authorSergey Ponomarev <stokito@gmail.com>
Sun, 17 Dec 2023 14:52:58 +0000 (16:52 +0200)
committerPaul Donald <newtwen@gmail.com>
Wed, 27 Dec 2023 20:28:58 +0000 (20:28 +0000)
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>
(cherry picked from commit 8755aa3a71bf47ba65706a39c72cd294923d9285)

applications/luci-app-sshtunnel/htdocs/luci-static/resources/view/sshtunnel/ssh_keys.js
applications/luci-app-sshtunnel/htdocs/luci-static/resources/view/sshtunnel/ssh_servers.js

index 2c3ee7a53f7cd80929be72f46c772f2c38b5f808..adaa1035973ea5a15b4a7c6600c75bedf96e1f49 100644 (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(()=> '');
+               });
+}
index e93280663128a63955e49d312191e11b87d47975..30b1b4fb3050e65ed815ee72382b792741133cf3 100644 (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);
 }