+ Implement SSH PubKey authentication

* Security related items to config/security dir
This commit is contained in:
Bryan Ashby 2019-02-20 23:55:09 -07:00
parent 65ef1feb6c
commit 57938e761e
No known key found for this signature in database
GPG key ID: B49EB437951D2542
7 changed files with 164 additions and 96 deletions

View file

@ -14,6 +14,8 @@ const {
Errors,
ErrorReasons
} = require('../../enig_error.js');
const User = require('../../user.js');
const UserProps = require('../../user_property.js');
// deps
const ssh2 = require('ssh2');
@ -21,6 +23,7 @@ const fs = require('graceful-fs');
const util = require('util');
const _ = require('lodash');
const assert = require('assert');
const crypto = require('crypto');
const ModuleInfo = exports.moduleInfo = {
name : 'SSH',
@ -42,8 +45,6 @@ function SSHClient(clientConn) {
clientConn.on('authentication', function authAttempt(ctx) {
const username = ctx.username || '';
const password = ctx.password || '';
const config = Config();
self.isNewUser = (config.users.newUserNames || []).indexOf(username) > -1;
@ -106,37 +107,36 @@ function SSHClient(clientConn) {
}
};
//
// If the system is open and |isNewUser| is true, the login
// sequence is hijacked in order to start the application process.
//
if(false === config.general.closedSystem && self.isNewUser) {
return ctx.accept();
}
const authWithPasswordOrPubKey = (authType) => {
if('pubKey' !== authType || !self.user.isAuthenticated() || !ctx.signature) {
// step 1: login/auth using PubKey
userLogin(self, ctx.username, ctx.password, { authType, ctx }, (err) => {
if(err) {
if(isSpecialHandleError(err)) {
return handleSpecialError(err, username);
}
if(username.length > 0 && password.length > 0) {
userLogin(self, ctx.username, ctx.password, function authResult(err) {
if(err) {
if(isSpecialHandleError(err)) {
return handleSpecialError(err, username);
if(Errors.BadLogin().code === err.code) {
return slowTerminateConnection();
}
return safeContextReject(SSHClient.ValidAuthMethods);
}
if(Errors.BadLogin().code === err.code) {
return slowTerminateConnection();
}
return safeContextReject(SSHClient.ValidAuthMethods);
ctx.accept();
});
} else {
// step 2: verify signature
const pubKeyActual = ssh2.utils.parseKey(self.user.getProperty(UserProps.LoginPubKey));
if(!pubKeyActual || !pubKeyActual.verify(ctx.blob, ctx.signature)) {
return slowTerminateConnection();
}
ctx.accept();
});
} else {
if(-1 === SSHClient.ValidAuthMethods.indexOf(ctx.method)) {
return safeContextReject(SSHClient.ValidAuthMethods);
return ctx.accept();
}
};
const authKeyboardInteractive = () => {
if(0 === username.length) {
// :TODO: can we display something here?
return safeContextReject();
}
@ -176,6 +176,30 @@ function SSHClient(clientConn) {
}
});
});
};
//
// If the system is open and |isNewUser| is true, the login
// sequence is hijacked in order to start the application process.
//
if(false === config.general.closedSystem && self.isNewUser) {
return ctx.accept();
}
switch(ctx.method) {
case 'password' :
return authWithPasswordOrPubKey('password');
//return authWithPassword();
case 'publickey' :
return authWithPasswordOrPubKey('pubKey');
//return authWithPubKey();
case 'keyboard-interactive' :
return authKeyboardInteractive();
default :
return safeContextReject(SSHClient.ValidAuthMethods);
}
});
@ -293,7 +317,11 @@ function SSHClient(clientConn) {
util.inherits(SSHClient, baseClient.Client);
SSHClient.ValidAuthMethods = [ 'password', 'keyboard-interactive' ];
SSHClient.ValidAuthMethods = [
'password',
'keyboard-interactive',
'publickey',
];
exports.getModule = class SSHServerModule extends LoginServerModule {
constructor() {