fix: session resumptions + google ldap auth
This commit is contained in:
parent
ab1ab1b130
commit
66fbcf4ca8
@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
|
### [1.1.6](https://github.com/simllll/node-radius-server/compare/v1.1.5...v1.1.6) (2020-08-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **google-auth:** search base must include ou ([a3ab393](https://github.com/simllll/node-radius-server/commit/a3ab393379be7f1b8b2f82347bbc4300b8db409d))
|
||||||
|
|
||||||
### [1.1.5](https://github.com/simllll/node-radius-server/compare/v1.1.4...v1.1.5) (2020-06-26)
|
### [1.1.5](https://github.com/simllll/node-radius-server/compare/v1.1.4...v1.1.5) (2020-06-26)
|
||||||
|
|
||||||
|
|
||||||
|
1235
package-lock.json
generated
1235
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "radius-server",
|
"name": "radius-server",
|
||||||
"description": "radius server for google LDAP and TTLS",
|
"description": "radius server for google LDAP and TTLS",
|
||||||
"version": "1.1.5",
|
"version": "1.1.6",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">13.10.1"
|
"node": ">13.10.1"
|
||||||
},
|
},
|
||||||
@ -30,30 +30,30 @@
|
|||||||
"preferGlobal": true,
|
"preferGlobal": true,
|
||||||
"main": "dist/app.js",
|
"main": "dist/app.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hokify/node-ts-cache": "^5.1.7",
|
"@hokify/node-ts-cache": "^5.2.0",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"imap-simple": "^5.0.0",
|
"imap-simple": "^5.0.0",
|
||||||
"ldapauth-fork": "^4.3.3",
|
"ldapauth-fork": "^4.3.3",
|
||||||
"ldapjs": "^2.0.0",
|
"ldapjs": "^2.1.1",
|
||||||
"native-duplexpair": "^1.0.0",
|
"native-duplexpair": "^1.0.0",
|
||||||
"node-cache": "^5.1.1",
|
"node-cache": "^5.1.2",
|
||||||
"radius": "~1.1.4",
|
"radius": "~1.1.4",
|
||||||
"smtp-client": "^0.3.1",
|
"smtp-client": "^0.3.2",
|
||||||
"yargs": "~15.3.1"
|
"yargs": "~15.4.1"
|
||||||
},
|
},
|
||||||
"license": "GPLv3",
|
"license": "GPLv3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ts-node": "^8.10.2",
|
"ts-node": "^8.10.2",
|
||||||
"standard-version": "^8.0.0",
|
"standard-version": "^8.0.2",
|
||||||
"@hokify/eslint-config": "^0.4.25",
|
"@hokify/eslint-config": "^0.4.42",
|
||||||
"@types/chai": "^4.2.11",
|
"@types/chai": "^4.2.12",
|
||||||
"@types/ldapjs": "^1.0.8",
|
"@types/ldapjs": "^1.0.9",
|
||||||
"@types/mocha": "^7.0.2",
|
"@types/mocha": "^8.0.1",
|
||||||
"@types/radius": "0.0.28",
|
"@types/radius": "0.0.28",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"eslint": "^7.3.1",
|
"eslint": "^7.6.0",
|
||||||
"mocha": "^8.0.1",
|
"mocha": "^8.1.1",
|
||||||
"prettier": "^2.0.5",
|
"prettier": "^2.0.5",
|
||||||
"typescript": "^3.9.5"
|
"typescript": "^3.9.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ interface IGoogleLDAPAuthOptions {
|
|||||||
/** base DN
|
/** base DN
|
||||||
* e.g. 'dc=hokify,dc=com', */
|
* e.g. 'dc=hokify,dc=com', */
|
||||||
base: string;
|
base: string;
|
||||||
|
searchBase?: string; // default ou=users,{{base}}
|
||||||
tls: {
|
tls: {
|
||||||
keyFile: string;
|
keyFile: string;
|
||||||
certFile: string;
|
certFile: string;
|
||||||
@ -35,8 +36,11 @@ export class GoogleLDAPAuth implements IAuthentication {
|
|||||||
|
|
||||||
private config: ClientOptions;
|
private config: ClientOptions;
|
||||||
|
|
||||||
|
searchBase: string;
|
||||||
|
|
||||||
constructor(config: IGoogleLDAPAuthOptions) {
|
constructor(config: IGoogleLDAPAuthOptions) {
|
||||||
this.base = config.base;
|
this.base = config.base;
|
||||||
|
this.searchBase = config.searchBase || `ou=users,${this.base}`;
|
||||||
|
|
||||||
const tlsOptions = {
|
const tlsOptions = {
|
||||||
key: fs.readFileSync(config.tls.keyFile),
|
key: fs.readFileSync(config.tls.keyFile),
|
||||||
@ -50,7 +54,9 @@ export class GoogleLDAPAuth implements IAuthentication {
|
|||||||
tlsOptions,
|
tlsOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.fetchDNs();
|
this.fetchDNs().catch((err) => {
|
||||||
|
console.error('fatal error google ldap auth, cannot fetch DNs', err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async fetchDNs() {
|
private async fetchDNs() {
|
||||||
@ -63,7 +69,7 @@ export class GoogleLDAPAuth implements IAuthentication {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ldapDNClient.search(
|
ldapDNClient.search(
|
||||||
this.base,
|
this.searchBase,
|
||||||
{
|
{
|
||||||
scope: 'sub',
|
scope: 'sub',
|
||||||
},
|
},
|
||||||
@ -86,8 +92,8 @@ export class GoogleLDAPAuth implements IAuthentication {
|
|||||||
});
|
});
|
||||||
|
|
||||||
res.on('error', function (ldapErr) {
|
res.on('error', function (ldapErr) {
|
||||||
console.error(`error: ${ldapErr.message}`);
|
console.error(`error: ${JSON.stringify(ldapErr)}`);
|
||||||
reject();
|
reject(ldapErr);
|
||||||
});
|
});
|
||||||
|
|
||||||
res.on('end', (result) => {
|
res.on('end', (result) => {
|
||||||
@ -132,6 +138,7 @@ export class GoogleLDAPAuth implements IAuthentication {
|
|||||||
if (!dnsFetched && !forceFetching) {
|
if (!dnsFetched && !forceFetching) {
|
||||||
return this.authenticate(username, password, count, true);
|
return this.authenticate(username, password, count, true);
|
||||||
}
|
}
|
||||||
|
// console.log('this.allValidDNsCache', this.allValidDNsCache);
|
||||||
console.error(`invalid username, not found in DN: ${username}`); // , this.allValidDNsCache);
|
console.error(`invalid username, not found in DN: ${username}`); // , this.allValidDNsCache);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,11 @@ export class EAPPacketHandler implements IPacketHandler {
|
|||||||
// EAP MESSAGE
|
// EAP MESSAGE
|
||||||
let msg = packet.attributes['EAP-Message'] as Buffer;
|
let msg = packet.attributes['EAP-Message'] as Buffer;
|
||||||
|
|
||||||
if (Array.isArray(msg)) {
|
if (Array.isArray(msg) && !(packet.attributes['EAP-Message'] instanceof Buffer)) {
|
||||||
msg = Buffer.concat(msg);
|
// log('multiple EAP Messages received, concat', msg.length);
|
||||||
|
const allMsgs = msg as Buffer[];
|
||||||
|
msg = Buffer.concat(allMsgs);
|
||||||
|
// log('final EAP Message', msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
/* eslint-disable no-bitwise */
|
/* eslint-disable no-bitwise */
|
||||||
import * as tls from 'tls';
|
import * as tls from 'tls';
|
||||||
import * as NodeCache from 'node-cache';
|
import * as NodeCache from 'node-cache';
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { attr_id_to_name, attr_name_to_id } from 'radius';
|
import { attr_id_to_name, attr_name_to_id } from 'radius';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
@ -219,12 +219,13 @@ export class EAPTTLS implements IEAPMethod {
|
|||||||
if (decodedFlags.lengthIncluded) {
|
if (decodedFlags.lengthIncluded) {
|
||||||
msglength = msg.slice(6, 10).readUInt32BE(0); // .readDoubleLE(0); // .toString('hex');
|
msglength = msg.slice(6, 10).readUInt32BE(0); // .readDoubleLE(0); // .toString('hex');
|
||||||
}
|
}
|
||||||
const data = msg.slice(decodedFlags.lengthIncluded ? 10 : 6, msg.length);
|
const data = msg.slice(decodedFlags.lengthIncluded ? 10 : 6).slice(0, msglength);
|
||||||
|
|
||||||
log('>>>>>>>>>>>> REQUEST FROM CLIENT: EAP TTLS', {
|
log('>>>>>>>>>>>> REQUEST FROM CLIENT: EAP TTLS', {
|
||||||
flags: `00000000${flags.toString(2)}`.substr(-8),
|
flags: `00000000${flags.toString(2)}`.substr(-8),
|
||||||
decodedFlags,
|
decodedFlags,
|
||||||
identifier,
|
identifier,
|
||||||
|
msglengthBuffer: msg.length,
|
||||||
msglength,
|
msglength,
|
||||||
data,
|
data,
|
||||||
// dataStr: data.toString()
|
// dataStr: data.toString()
|
||||||
@ -388,15 +389,24 @@ export class EAPTTLS implements IEAPMethod {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const responseHandler = (encryptedResponseData: Buffer) => {
|
const responseHandler = (encryptedResponseData: Buffer) => {
|
||||||
|
log('complete');
|
||||||
// send back...
|
// send back...
|
||||||
sendResponsePromise.resolve(
|
sendResponsePromise.resolve(
|
||||||
this.buildEAPTTLSResponse(identifier, 21, 0x00, stateID, encryptedResponseData)
|
this.buildEAPTTLSResponse(identifier, 21, 0x00, stateID, encryptedResponseData)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checkExistingSession = (isSessionReused) => {
|
||||||
|
if (isSessionReused) {
|
||||||
|
log('secured, session reused, accept auth!');
|
||||||
|
sendResponsePromise.resolve(this.authResponse(identifier, true, connection.tls, packet));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// register event listeners
|
// register event listeners
|
||||||
connection.events.on('incoming', incomingMessageHandler);
|
connection.events.on('incoming', incomingMessageHandler);
|
||||||
connection.events.on('response', responseHandler);
|
connection.events.on('response', responseHandler);
|
||||||
|
connection.events.on('secured', checkExistingSession);
|
||||||
|
|
||||||
// emit data to tls server
|
// emit data to tls server
|
||||||
connection.events.emit('decrypt', data);
|
connection.events.emit('decrypt', data);
|
||||||
@ -405,6 +415,9 @@ export class EAPTTLS implements IEAPMethod {
|
|||||||
// cleanup
|
// cleanup
|
||||||
connection.events.off('incoming', incomingMessageHandler);
|
connection.events.off('incoming', incomingMessageHandler);
|
||||||
connection.events.off('response', responseHandler);
|
connection.events.off('response', responseHandler);
|
||||||
|
connection.events.off('secured', checkExistingSession);
|
||||||
|
|
||||||
|
// connection.events.off('secured');
|
||||||
|
|
||||||
// send response
|
// send response
|
||||||
return responseData; // this.buildEAPTTLSResponse(identifier, 21, 0x00, stateID, encryptedResponseData);
|
return responseData; // this.buildEAPTTLSResponse(identifier, 21, 0x00, stateID, encryptedResponseData);
|
||||||
@ -473,7 +486,7 @@ export class EAPTTLS implements IEAPMethod {
|
|||||||
|
|
||||||
let vendorId;
|
let vendorId;
|
||||||
let data;
|
let data;
|
||||||
if (flags & 0b010000000) {
|
if (decodedFlags.V) {
|
||||||
// V flag set
|
// V flag set
|
||||||
vendorId = currentBuffer.slice(8, 12).readUInt32BE(0);
|
vendorId = currentBuffer.slice(8, 12).readUInt32BE(0);
|
||||||
data = currentBuffer.slice(12, length);
|
data = currentBuffer.slice(12, length);
|
||||||
|
@ -5,6 +5,7 @@ import * as crypto from 'crypto';
|
|||||||
import * as DuplexPair from 'native-duplexpair';
|
import * as DuplexPair from 'native-duplexpair';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import * as NodeCache from 'node-cache';
|
import * as NodeCache from 'node-cache';
|
||||||
|
// import * as constants from 'constants';
|
||||||
import * as config from '../../config';
|
import * as config from '../../config';
|
||||||
|
|
||||||
const log = debug('radius:tls');
|
const log = debug('radius:tls');
|
||||||
@ -96,6 +97,7 @@ export function startTLSServer(): ITLSServer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
log('*********** new TLS connection established / secured ********');
|
log('*********** new TLS connection established / secured ********');
|
||||||
|
emitter.emit('secured', cleartext.isSessionReused());
|
||||||
});
|
});
|
||||||
|
|
||||||
cleartext.on('error', (err?: Error) => {
|
cleartext.on('error', (err?: Error) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user