luci-app-sshtunnel: ssh_keys: list keys without a corresponding .pub
authorSergey Ponomarev <stokito@gmail.com>
Sun, 17 Dec 2023 12:34:32 +0000 (14:34 +0200)
committerPaul Donald <newtwen@gmail.com>
Wed, 27 Dec 2023 20:29:19 +0000 (20:29 +0000)
The private keys doesn't have any extension so the only way to clearly say that this file is a key is a presence of the corresponding .pub file.
Most of time key files have a prefix id_ e.g. id_rsa etc.

The dropbearkey generates a key without a corresponding .pub file e.g. id_dropbearkey.

So we need to detect a key files by both .pub file or id_ prefix.
Key files without the id_ prefix won't be listed, sorry.

Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
(cherry picked from commit 949e7cbcb33cc457bfcdd27aaf4da487bab89f30)

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 4001404aadbc1ad9a1095bfd516e16d4197a7e94..2c3ee7a53f7cd80929be72f46c772f2c38b5f808 100644 (file)
@@ -11,14 +11,16 @@ return view.extend({
        load: function () {
                return L.resolveDefault(fs.list('/root/.ssh/'), []).then(function (entries) {
                        var tasks = [
+                               // detect if OpenSSH ssh-keygen is installed
                                L.resolveDefault(fs.stat('/usr/bin/ssh-keygen'), {}),
                        ];
+                       var sshKeyNames = _findAllPossibleIdKeys(entries);
+
                        // read pub keys
-                       for (var i = 0; i < entries.length; i++) {
-                               if (entries[i].type === 'file' && entries[i].name.match(/\.pub$/)) {
-                                       tasks.push(Promise.resolve(entries[i].name));
-                                       tasks.push(fs.lines('/root/.ssh/' + entries[i].name));
-                               }
+                       for (var sshKeyName of sshKeyNames) {
+                               var sshPubKeyName = sshKeyName + '.pub';
+                               tasks.push(Promise.resolve(sshKeyName));
+                               tasks.push(fs.lines('/root/.ssh/' + sshPubKeyName));
                        }
                        return Promise.all(tasks);
                });
@@ -42,12 +44,37 @@ return view.extend({
        },
 });
 
+function _findAllPossibleIdKeys(entries) {
+       var sshKeyNames = [];
+       for (var item of entries) {
+               if (item.type !== 'file') {
+                       continue
+               }
+               // 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)
+                       }
+               } 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)
+                               }
+                       }
+               }
+       }
+       return sshKeyNames;
+}
+
 function _splitSshKeys(sshFiles) {
        var sshKeys = {};
        for (var i = 0; i < sshFiles.length; i++) {
-               var sshPubKeyName = sshFiles[i];
-               var sshKeyName = sshPubKeyName.substring(0, sshPubKeyName.length - 4);
-               i++;
+               var sshKeyName = sshFiles[i];
+               i++; // next is a .pub content
                var sshPub = sshFiles[i];
                sshKeys[sshKeyName] = '<small><code>' + sshPub + '</code></small>';
        }
index 5aa33e6df882ac162942c5c5e5b72c0fdfbe3a44..e93280663128a63955e49d312191e11b87d47975 100644 (file)
@@ -5,24 +5,17 @@
 'require ui';
 'require view';
 
-var allSshKeys = {};
-
 return view.extend({
        load: function () {
                return L.resolveDefault(fs.list('/root/.ssh/'), []).then(function (entries) {
-                       var tasks = [];
-                       for (var i = 0; i < entries.length; i++) {
-                               if (entries[i].type === 'file' && entries[i].name.match(/\.pub$/)) {
-                                       tasks.push(Promise.resolve(entries[i].name));
-                               }
-                       }
-                       return Promise.all(tasks);
+                       var sshKeyNames = _findAllPossibleIdKeys(entries);
+                       return Promise.resolve(sshKeyNames);
                });
        },
 
        render: function (data) {
-               var sshKeys = _splitSshKeys(data);
-               if (sshKeys.length === 0) {
+               var sshKeyNames = data;
+               if (sshKeyNames.length === 0) {
                        ui.addNotification(null, E('p', _('No SSH keys found, <a %s>generate a new one</a>').format('href="./ssh_keys"')), 'warning');
                }
 
@@ -58,9 +51,9 @@ return view.extend({
                                'See <em>ssh_config IdentityFile</em>')
                );
                o.value('');
-               Object.keys(sshKeys).forEach(function (keyName) {
-                       o.value('/root/.ssh/' + keyName, keyName);
-               });
+               for (var sshKeyName of sshKeyNames) {
+                       o.value('/root/.ssh/' + sshKeyName, sshKeyName);
+               }
                o.optional = true;
 
 
@@ -135,13 +128,28 @@ return view.extend({
        },
 });
 
-function _splitSshKeys(sshFiles) {
-       var sshKeys = {};
-       for (var i = 0; i < sshFiles.length; i++) {
-               var sshPubKeyName = sshFiles[i];
-               var sshKeyName = sshPubKeyName.substring(0, sshPubKeyName.length - 4);
-               sshKeys[sshKeyName] = '';
+function _findAllPossibleIdKeys(entries) {
+       var sshKeyNames = [];
+       for (var item of entries) {
+               if (item.type !== 'file') {
+                       continue
+               }
+               // 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)
+                       }
+               } 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)
+                               }
+                       }
+               }
        }
-       allSshKeys = sshKeys;
-       return sshKeys;
+       return sshKeyNames;
 }