From dfd8915d6421f3b1ebf8cc40d3cc5f53c1e5e1de Mon Sep 17 00:00:00 2001 From: Andrew Plummer Date: Mon, 25 Jun 2018 14:57:13 +0100 Subject: [PATCH 1/3] Reindent authentication logic --- lib/node-sftp-s3.js | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/node-sftp-s3.js b/lib/node-sftp-s3.js index b18d280..86af2d9 100644 --- a/lib/node-sftp-s3.js +++ b/lib/node-sftp-s3.js @@ -110,32 +110,32 @@ class SFTPS3Server extends EventEmitter { this.emit('client-error', { client: client, error: err }); }); client.on('authentication', (ctx) => { - if(ctx.method !== 'publickey') { - this._log('rejecting non-public-key authentication'); - return ctx.reject(['publickey']); - } - - pubKey = this._findKey(ctx.username, ctx.key); - if(!pubKey) { - this._log('public key not found'); - return ctx.reject(['publickey not found']); - } + if(ctx.method === 'publickey') { + pubKey = this._findKey(ctx.username, ctx.key); + if(!pubKey) { + this._log('public key not found'); + return ctx.reject(['publickey not found']); + } - if(ctx.signature) { - var verifier = crypto.createVerify(ctx.sigAlgo); - verifier.update(ctx.blob); - if(verifier.verify(pubKey.key.publicOrig, ctx.signature)) { - this._log('signature verified'); - return ctx.accept(); + if(ctx.signature) { + var verifier = crypto.createVerify(ctx.sigAlgo); + verifier.update(ctx.blob); + if(verifier.verify(pubKey.key.publicOrig, ctx.signature)) { + this._log('signature verified'); + return ctx.accept(); + } + else { + this._log('signature rejected'); + return ctx.reject(); + } } else { - this._log('signature rejected'); - return ctx.reject(); + this._log('no signature present'); + return ctx.accept(); } - } - else { - this._log('no signature present'); - return ctx.accept(); + } else { + this._log('rejecting non-public-key authentication'); + return ctx.reject(['publickey']); } }) .on('ready', () => { From 3eeee212a89dff332141220e6e9513f34021d27b Mon Sep 17 00:00:00 2001 From: Andrew Plummer Date: Mon, 25 Jun 2018 14:58:11 +0100 Subject: [PATCH 2/3] Fix rejection methodsLeft --- lib/node-sftp-s3.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node-sftp-s3.js b/lib/node-sftp-s3.js index 86af2d9..04f5690 100644 --- a/lib/node-sftp-s3.js +++ b/lib/node-sftp-s3.js @@ -114,7 +114,7 @@ class SFTPS3Server extends EventEmitter { pubKey = this._findKey(ctx.username, ctx.key); if(!pubKey) { this._log('public key not found'); - return ctx.reject(['publickey not found']); + return ctx.reject(); } if(ctx.signature) { From 5413ca144d8b0dd00b2556e582f9fce06836b08c Mon Sep 17 00:00:00 2001 From: Andrew Plummer Date: Mon, 25 Jun 2018 15:06:10 +0100 Subject: [PATCH 3/3] Allow password login To fix #19. --- lib/node-sftp-s3.js | 58 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/lib/node-sftp-s3.js b/lib/node-sftp-s3.js index 04f5690..d0a1194 100644 --- a/lib/node-sftp-s3.js +++ b/lib/node-sftp-s3.js @@ -21,6 +21,7 @@ class SFTPS3Server extends EventEmitter { super(); this.s3 = s3Instance; this.publicKeys = []; + this.passwordLogins = []; this.hostKeys = []; this.loggingEnabled = false; } @@ -60,6 +61,19 @@ class SFTPS3Server extends EventEmitter { this._log(util.format('Added public key for username %s, path %s', username, path)); } + addPasswordLogin(password, username, ns) { + var path = _path.normalize(username); + if(ns) { + path = _path.join(_path.normalize(ns), path); + } + + while (path.indexOf('\\') >= 0) + path = path.replace('\\', '/'); + + this.passwordLogins.push({ password: password, username: username, path: path }); + this._log(util.format('Added password login for username %s, path %s', username, path)); + } + /** * Remove the public key for a username * @@ -73,6 +87,14 @@ class SFTPS3Server extends EventEmitter { }); } + removePasswordLogin(username) { + const self = this; + _.remove(this.passwordLogins, (p) => { + self._log(util.format('Removed password login for username %s', username)); + return p.username === username; + }); + } + /** * Remove all public keys */ @@ -81,6 +103,11 @@ class SFTPS3Server extends EventEmitter { this.publicKeys = []; } + removeAllPasswordLogins() { + this._log(util.format('Removed all password logins')); + this.passwordLogins = []; + } + /** * Add a host key. You need at least one host key before you can start the server. * @@ -106,15 +133,19 @@ class SFTPS3Server extends EventEmitter { hostKeys: this.hostKeys }, (client) => { var pubKey; + var remainingMethods = ['publickey', 'password']; client.on('error', (err) => { this.emit('client-error', { client: client, error: err }); }); client.on('authentication', (ctx) => { + var supportedMethods = ['publickey', 'password']; + if(ctx.method === 'publickey') { + remainingMethods = ['password'] pubKey = this._findKey(ctx.username, ctx.key); if(!pubKey) { this._log('public key not found'); - return ctx.reject(); + return ctx.reject(remainingMethods); } if(ctx.signature) { @@ -126,16 +157,24 @@ class SFTPS3Server extends EventEmitter { } else { this._log('signature rejected'); - return ctx.reject(); + return ctx.reject(remainingMethods); } } else { this._log('no signature present'); return ctx.accept(); } + } else if(ctx.method === 'password') { + remainingMethods = []; + pubKey = this._findPassword(ctx.username, ctx.password); + if (!pubKey) { + this._log('password not found'); + return ctx.reject(remainingMethods); + } + return ctx.accept(); } else { - this._log('rejecting non-public-key authentication'); - return ctx.reject(['publickey']); + this._log('unsupported method ' + ctx.method); + return ctx.reject(remainingMethods); } }) .on('ready', () => { @@ -679,6 +718,17 @@ class SFTPS3Server extends EventEmitter { } } + _findPassword(username, password) { + for (var idx = 0; idx < this.passwordLogins.length; idx++) { + if (this.passwordLogins[idx]['username'] == username) { + var passwd = this.passwordLogins[idx]; + if (passwd.password === password) { + return passwd; + } + } + } + } + _mapKey(path, filename) { var p = filename; p = p.replace('\\\\', '/');