From 9fe25a8b497071ea9276785b7f7710ae0e1e88f8 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 23 Feb 2020 00:49:17 +0100 Subject: [PATCH] feat: add debug pkg to reduce output --- package-lock.json | 4 +- package.json | 12 +- src/auth/google-ldap.ts | 12 +- src/radius/RadiusService.ts | 42 +----- src/radius/handler/EAPPacketHandler.ts | 15 +- src/radius/handler/eapMethods/EAPTTLS.ts | 137 ++---------------- .../eapMethods/challenges/PAPChallenge.ts | 11 +- src/server/UDPServer.ts | 2 - src/tls/crypt.ts | 35 +++-- 9 files changed, 67 insertions(+), 203 deletions(-) diff --git a/package-lock.json b/package-lock.json index 58bf99c..44a9147 100644 --- a/package-lock.json +++ b/package-lock.json @@ -866,7 +866,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -2494,8 +2493,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multimap": { "version": "1.1.0", diff --git a/package.json b/package.json index 0b0b195..a956448 100644 --- a/package.json +++ b/package.json @@ -3,22 +3,24 @@ "description": "radius server for google LDAP and TTLT", "version": "0.0.1", "scripts": { - "start": "/home/simon/Dev/others/node/node dist/app.js", + "debug": "DEBUG=radius:* ../node/node dist/app.js", + "start": "../node/node dist/app.js", "build": "tsc", "dev": "ts-node src/app.ts", "test-ttls-pap": "eapol_test -c ./ttls-pap.conf -s testing123", "create-certificate": "sh ./ssl/create.sh && sh ./ssl/sign.sh" }, "dependencies": { - "native-duplexpair": "^1.0.0", + "debug": "^4.1.1", "ldapjs": "^1.0.2", + "md5": "^2.2.1", + "native-duplexpair": "^1.0.0", "node-cache": "^5.1.0", + "passport-ldapauth": "^2.1.3", "radius": "~1.1.4", "ts-node": "^8.6.2", "type-cacheable": "^4.0.0", - "yargs": "~15.1.0", - "md5": "^2.2.1", - "passport-ldapauth": "^2.1.3" + "yargs": "~15.1.0" }, "license": "GPLv3", "devDependencies": { diff --git a/src/auth/google-ldap.ts b/src/auth/google-ldap.ts index 1c9deef..486d021 100644 --- a/src/auth/google-ldap.ts +++ b/src/auth/google-ldap.ts @@ -1,10 +1,12 @@ import * as NodeCache from 'node-cache'; import { Client, createClient } from 'ldapjs'; +import debug from 'debug'; import { IAuthentication } from '../types/Authentication'; const usernameFields = ['posixUid', 'mail']; +const log = debug('radius:auth:ldap'); // TLS: // https://github.com/ldapjs/node-ldapjs/issues/307 @@ -41,7 +43,7 @@ export class GoogleLDAPAuth implements IAuthentication { } res.on('searchEntry', function(entry) { - // console.log('entry: ' + JSON.stringify(entry.object)); + // log('entry: ' + JSON.stringify(entry.object)); usernameFields.forEach(field => { const index = entry.object[field] as string; dns[index] = entry.object.dn; @@ -49,7 +51,7 @@ export class GoogleLDAPAuth implements IAuthentication { }); res.on('searchReference', function(referral) { - console.log(`referral: ${referral.uris.join()}`); + log(`referral: ${referral.uris.join()}`); }); res.on('error', function(ldapErr) { @@ -58,11 +60,11 @@ export class GoogleLDAPAuth implements IAuthentication { }); res.on('end', result => { - console.log(`ldap status: ${result?.status}`); + log(`ldap status: ${result?.status}`); // replace with new dns this.allValidDNsCache = dns; - // console.log('allValidDNsCache', this.allValidDNsCache); + // log('allValidDNsCache', this.allValidDNsCache); resolve(); }); } @@ -84,7 +86,7 @@ export class GoogleLDAPAuth implements IAuthentication { let dnsFetched = false; if (!this.lastDNsFetch || this.lastDNsFetch < cacheValidTime || forceFetching) { - console.log('fetching dns'); + log('fetching dns'); await this.fetchDNs(); dnsFetched = true; } diff --git a/src/radius/RadiusService.ts b/src/radius/RadiusService.ts index 30dbe13..605c297 100644 --- a/src/radius/RadiusService.ts +++ b/src/radius/RadiusService.ts @@ -18,47 +18,9 @@ export class RadiusService { const packet = radius.decode({ packet: msg, secret: this.secret }); if (packet.code !== 'Access-Request') { - console.log('unknown packet type: ', packet.code); + console.error('unknown packet type: ', packet.code); return undefined; } - // console.log('packet.attributes', packet.attributes); - - // console.log('rinfo', rinfo); - /* - const checkAuth = async ( - username: string, - password: string, - additionalAuthHandler?: AdditionalAuthHandler - ) => { - console.log(`Access-Request for ${username}`); - let success = false; - try { - await this.authentication.authenticate(username, password); - success = true; - } catch (err) { - console.error(err); - } - - const attributes: any[] = []; - - if (additionalAuthHandler) { - await additionalAuthHandler(success, { packet, attributes, secret: this.secret }); - } - - const response = radius.encode_response({ - packet, - code: success ? 'Access-Accept' : 'Access-Reject', - secret: this.secret, - attributes - }); - console.log(`Sending ${success ? 'accept' : 'reject'} for user ${username}`); - - this.server.sendToClient(response, rinfo.port, rinfo.address, function(err, _bytes) { - if (err) { - console.log('Error sending response to ', rinfo); - } - }); - }; */ let response: IPacketHandlerResult; @@ -67,7 +29,7 @@ export class RadiusService { throw new Error('no packet handlers registered'); } - // process packet handlers until we get a response + // process packet handlers until we get a response from one do { /* response is of type IPacketHandlerResult */ response = await this.radiusPacketHandlers[i].handlePacket(packet.attributes, packet); diff --git a/src/radius/handler/EAPPacketHandler.ts b/src/radius/handler/EAPPacketHandler.ts index e4b458d..c177c63 100644 --- a/src/radius/handler/EAPPacketHandler.ts +++ b/src/radius/handler/EAPPacketHandler.ts @@ -2,6 +2,7 @@ import * as NodeCache from 'node-cache'; import { RadiusPacket } from 'radius'; +import debug from 'debug'; import { EAPTTLS } from './eapMethods/EAPTTLS'; import { makeid } from '../../helpers'; import { @@ -12,6 +13,8 @@ import { import { IAuthentication } from '../../types/Authentication'; import { IEAPMethod } from '../../types/EAPMethod'; +const log = debug('radius:eap'); + export class EAPPacketHandler implements IPacketHandler { private eapMethods: IEAPMethod[] = []; @@ -124,7 +127,7 @@ export class EAPPacketHandler implements IPacketHandler { case 2: // for response switch (type) { case 1: // identifiy - console.log('>>>>>>>>>>>> REQUEST FROM CLIENT: IDENTIFY', {}); + log('>>>>>>>>>>>> REQUEST FROM CLIENT: IDENTIFY', {}); // start identify if (currentState.validMethods.length > 0) { return currentState.validMethods[0].identify(identifier, stateID); @@ -132,11 +135,11 @@ export class EAPPacketHandler implements IPacketHandler { return this.buildEAPResponse(identifier, 3); case 2: // notification - console.log('>>>>>>>>>>>> REQUEST FROM CLIENT: notification', {}); + log('>>>>>>>>>>>> REQUEST FROM CLIENT: notification', {}); console.info('notification'); break; case 4: // md5-challenge - console.log('>>>>>>>>>>>> REQUEST FROM CLIENT: md5-challenge', {}); + log('>>>>>>>>>>>> REQUEST FROM CLIENT: md5-challenge', {}); console.info('md5-challenge'); break; @@ -145,6 +148,8 @@ export class EAPPacketHandler implements IPacketHandler { break; case 3: // nak if (data) { + // if there is data, each data octect reprsents a eap method the clients supports, + // kick out all unsupported ones const supportedEAPMethods: number[] = []; for (const supportedMethod of data) { supportedEAPMethods.push(supportedMethod); @@ -180,10 +185,10 @@ export class EAPPacketHandler implements IPacketHandler { } break; case 3: - console.log('Client Auth Success'); + log('Client Auth Success'); break; case 4: - console.log('Client Auth FAILURE'); + log('Client Auth FAILURE'); break; default: } diff --git a/src/radius/handler/eapMethods/EAPTTLS.ts b/src/radius/handler/eapMethods/EAPTTLS.ts index 9fb7c09..80cd768 100644 --- a/src/radius/handler/eapMethods/EAPTTLS.ts +++ b/src/radius/handler/eapMethods/EAPTTLS.ts @@ -2,6 +2,7 @@ import * as tls from 'tls'; import * as NodeCache from 'node-cache'; import { RadiusPacket } from 'radius'; +import debug from 'debug'; import { encodeTunnelPW, ITLSServer, startTLSServer } from '../../../tls/crypt'; import { ResponseAuthHandler } from '../../../types/Handler'; import { PAPChallenge } from './challenges/PAPChallenge'; @@ -11,94 +12,15 @@ import { IEAPMethod } from '../../../types/EAPMethod'; import { IAuthentication } from '../../../types/Authentication'; import { secret } from '../../../../config'; +const log = debug('radius:eap:ttls'); + interface IEAPResponseHandlers { response: (respData?: Buffer, msgType?: number) => void; checkAuth: ResponseAuthHandler; } -/* const handlers = { - response: (EAPMessage: Buffer) => { - const attributes: any = [['State', Buffer.from(state)]]; - let sentDataSize = 0; - do { - if (EAPMessage.length > 0) { - attributes.push([ - 'EAP-Message', - EAPMessage.slice(sentDataSize, sentDataSize + MAX_RADIUS_ATTRIBUTE_SIZE) - ]); - sentDataSize += MAX_RADIUS_ATTRIBUTE_SIZE; - } - } while (sentDataSize < EAPMessage.length); - - const response = radius.encode_response({ - packet, - code: 'Access-Challenge', - secret: this.secret, - attributes - }); - - waitForNextMsg[state] = newDeferredPromise(); - - server.sendToClient( - response, - rinfo.port, - rinfo.address, - function(err, _bytes) { - if (err) { - console.log('Error sending response to ', rinfo); - } - }, - state - ); - - return waitForNextMsg[state].promise; - }, - checkAuth -}; - - -const attributes: any = [['State', Buffer.from(stateID)]]; -let sentDataSize = 0; -do { - if (EAPMessage.length > 0) { - attributes.push([ - 'EAP-Message', - EAPMessage.slice(sentDataSize, sentDataSize + MAX_RADIUS_ATTRIBUTE_SIZE) - ]); - sentDataSize += MAX_RADIUS_ATTRIBUTE_SIZE; - } -} while (sentDataSize < EAPMessage.length); - -const response = radius.encode_response({ - packet, - code: 'Access-Challenge', - secret: this.secret, - attributes -}); - -waitForNextMsg[stateID] = newDeferredPromise(); - -server.sendToClient( - response, - rinfo.port, - rinfo.address, - function(err, _bytes) { - if (err) { - console.log('Error sending response to ', rinfo); - } - }, - stateID -); - -return waitForNextMsg[stateID].promise; -*/ -/* if (waitForNextMsg[state]) { - const identifier = attributes['EAP-Message'].slice(1, 2).readUInt8(0); // .toString('hex'); - waitForNextMsg[state].resolve({ response: handlers.response, identifier }); -} */ - function tlsHasExportKeyingMaterial( - tlsSocket: any + tlsSocket ): tlsSocket is { exportKeyingMaterial: (length: number, label: string, context?: Buffer) => Buffer; } { @@ -132,7 +54,7 @@ export class EAPTTLS implements IEAPMethod { newResponse = true ): IPacketHandlerResult { const maxSize = (MAX_RADIUS_ATTRIBUTE_SIZE - 5) * 4; - console.log('maxSize', maxSize); + log('maxSize', maxSize); /* it's the first one and we have more, therefore include length */ const includeLength = data && newResponse && data.length > maxSize; @@ -187,7 +109,7 @@ export class EAPTTLS implements IEAPMethod { // set EAP length header resBuffer.writeUInt16BE(resBuffer.byteLength, 2); - console.log('<<<<<<<<<<<< EAP RESPONSE TO CLIENT', { + log('<<<<<<<<<<<< EAP RESPONSE TO CLIENT', { code: 1, identifier: identifier + 1, includeLength, @@ -298,50 +220,19 @@ export class EAPTTLS implements IEAPMethod { attributes.push(['User-Name', packet.attributes['User-Name']]); } - /* - if (sess->eap_if->eapKeyDataLen > 64) { - len = 32; - } else { - len = sess->eap_if->eapKeyDataLen / 2; - } - */ if (tlsHasExportKeyingMaterial(socket)) { const keyingMaterial = (socket as any).exportKeyingMaterial(128, 'ttls keying material'); - // console.log('keyingMaterial', keyingMaterial); - - // eapKeyData + len attributes.push([ 'Vendor-Specific', 311, - [ - [ - 16, - encodeTunnelPW( - keyingMaterial.slice(64), - (packet as any).authenticator, - // params.packet.attributes['Message-Authenticator'], - secret - ) - ] - ] + [[16, encodeTunnelPW(keyingMaterial.slice(64), (packet as any).authenticator, secret)]] ]); // MS-MPPE-Send-Key - // eapKeyData attributes.push([ 'Vendor-Specific', 311, - [ - [ - 17, - encodeTunnelPW( - keyingMaterial.slice(0, 64), - (packet as any).authenticator, - // params.packet.attributes['Message-Authenticator'], - secret - ) - ] - ] + [[17, encodeTunnelPW(keyingMaterial.slice(0, 64), (packet as any).authenticator, secret)]] ]); // MS-MPPE-Recv-Key } else { console.error( @@ -365,7 +256,7 @@ export class EAPTTLS implements IEAPMethod { // check if no data package is there and we have something in the queue, if so.. empty the queue first if (!data || data.length === 0) { - console.warn( + log( `>>>>>>>>>>>> REQUEST FROM CLIENT: EAP TTLS, ACK / NACK (no data, just a confirmation, ID: ${identifier})` ); const queuedData = this.queueData.get(stateID); @@ -376,7 +267,7 @@ export class EAPTTLS implements IEAPMethod { return {}; } - console.log('>>>>>>>>>>>> REQUEST FROM CLIENT: EAP TTLS', { + log('>>>>>>>>>>>> REQUEST FROM CLIENT: EAP TTLS', { // flags: `00000000${flags.toString(2)}`.substr(-8), decodedFlags, identifier, @@ -393,7 +284,7 @@ export class EAPTTLS implements IEAPMethod { connection.events.on('end', () => { // cleanup socket - console.log('ENDING SOCKET'); + log('ENDING SOCKET'); this.openTLSSockets.del(stateID); }); } @@ -422,12 +313,12 @@ export class EAPTTLS implements IEAPMethod { } break; default: - console.log('data', incomingData); - console.log('data str', incomingData.toString()); + log('data', incomingData); + log('data str', incomingData.toString()); // currentConnection!.events.emit('end'); - console.log('UNSUPPORTED AUTH TYPE, requesting PAP'); + log('UNSUPPORTED AUTH TYPE, requesting PAP'); // throw new Error(`unsupported auth type${type}`); sendResponsePromise.resolve( this.buildEAPTTLSResponse(identifier, 3, 0, stateID, Buffer.from([1])) diff --git a/src/radius/handler/eapMethods/challenges/PAPChallenge.ts b/src/radius/handler/eapMethods/challenges/PAPChallenge.ts index 3b4b893..0c7b672 100644 --- a/src/radius/handler/eapMethods/challenges/PAPChallenge.ts +++ b/src/radius/handler/eapMethods/challenges/PAPChallenge.ts @@ -1,5 +1,8 @@ +import debug from 'debug'; import { IEAPChallenge } from '../../../../types/EAPChallenge'; +const log = debug('radius:eap:papchallenge'); + export class PAPChallenge implements IEAPChallenge { // i couldn't find any documentation about it, therefore best guess how this is processed... // http://www.networksorcery.com/enp/rfc/rfc1334.txt ? @@ -7,7 +10,7 @@ export class PAPChallenge implements IEAPChallenge { decode(data: Buffer) { const usrNameLength = data.slice(7, 8).readUInt8(0); const user = data.slice(8, usrNameLength); - console.log('user', user, user.toString().trim()); + log('user', user, user.toString().trim()); let pwdStart = usrNameLength; // data.slice(usrNameLength); const passwordDelimeter = Buffer.from([0x02, 0x40, 0x00, 0x00]); @@ -27,14 +30,14 @@ export class PAPChallenge implements IEAPChallenge { if (!found) { throw new Error("couldn't extract password"); } - // console.log('pwdStart+passwordDelimeter.length', pwdStart+passwordDelimeter.length); - // console.log('length', pwdStart + data.readUInt8(pwdStart+passwordDelimeter.length)); + // log('pwdStart+passwordDelimeter.length', pwdStart+passwordDelimeter.length); + // log('length', pwdStart + data.readUInt8(pwdStart+passwordDelimeter.length)); // first byte is a length property.. we ignore for now pwd = data.slice(pwdStart + passwordDelimeter.length + 1); // , pwdStart+ data.readUInt8(pwdStart+passwordDelimeter.length)); // trim pwd pwd = pwd.slice(0, pwd.indexOf(0x00)); - console.log('pwd', pwd, pwd.toString().trim().length, pwd.toString()); + log('pwd', pwd, pwd.toString().trim().length, pwd.toString()); return { username: user.toString(), diff --git a/src/server/UDPServer.ts b/src/server/UDPServer.ts index d7311f5..501aef2 100644 --- a/src/server/UDPServer.ts +++ b/src/server/UDPServer.ts @@ -60,8 +60,6 @@ export class UDPServer extends events.EventEmitter implements IServer { }); this.server.on('message', (_msg, rinfo) => { - console.log('incoming message 2'); - // message retrieved, reset timeout handler const identifierForRetry = `${rinfo.address}:${rinfo.port}`; if (this.timeout[identifierForRetry]) { diff --git a/src/tls/crypt.ts b/src/tls/crypt.ts index f994953..25c1894 100644 --- a/src/tls/crypt.ts +++ b/src/tls/crypt.ts @@ -4,9 +4,12 @@ import { createSecureContext } from 'tls'; import * as crypto from 'crypto'; import * as DuplexPair from 'native-duplexpair'; import * as constants from 'constants'; +import debug from 'debug'; import { makeid } from '../helpers'; import * as config from '../../config'; +const log = debug('radius:tls'); + // https://nodejs.org/api/tls.html const tlsOptions: tls.SecureContextOptions = { ...config.certificate, @@ -17,7 +20,7 @@ const tlsOptions: tls.SecureContextOptions = { // secureOptions: // ecdhCurve: 'auto' }; -console.log('tlsOptions', tlsOptions); +log('tlsOptions', tlsOptions); const secureContext = createSecureContext(tlsOptions); export interface ITLSServer { @@ -45,7 +48,7 @@ export function startTLSServer(): ITLSServer { }); encrypted.on('data', (data: Buffer) => { - // console.log('encrypted data', data, data.toString()); + // log('encrypted data', data, data.toString()); emitter.emit('response', data); }); @@ -53,42 +56,42 @@ export function startTLSServer(): ITLSServer { const cipher = cleartext.getCipher(); /* - console.log('Authorized', cleartext.authorized); - console.log('getTLSTicket', cleartext.getTLSTicket()); - console.log('getEphemeralKeyInfo', cleartext.getEphemeralKeyInfo()); - console.log('getPeerCertificate', cleartext.getPeerCertificate()); - console.log('getSharedSigalgs', cleartext.getSharedSigalgs()); - console.log('getCertificate', cleartext.getCertificate()); - console.log('getSession', cleartext.getSession()); + log('Authorized', cleartext.authorized); + log('getTLSTicket', cleartext.getTLSTicket()); + log('getEphemeralKeyInfo', cleartext.getEphemeralKeyInfo()); + log('getPeerCertificate', cleartext.getPeerCertificate()); + log('getSharedSigalgs', cleartext.getSharedSigalgs()); + log('getCertificate', cleartext.getCertificate()); + log('getSession', cleartext.getSession()); */ if (cipher) { - console.log(`TLS negotiated (${cipher.name}, ${cipher.version})`); + log(`TLS negotiated (${cipher.name}, ${cipher.version})`); } cleartext.on('data', (data: Buffer) => { - // console.log('cleartext data', data, data.toString()); + // log('cleartext data', data, data.toString()); emitter.emit('incoming', data); }); cleartext.once('close', (_data: Buffer) => { - console.log('cleartext close'); + log('cleartext close'); emitter.emit('end'); }); cleartext.on('keylog', line => { - console.log('############ KEYLOG #############', line); + log('############ KEYLOG #############', line); // cleartext.getTicketKeys() }); - console.log('*********** new client connection established / secured ********'); + log('*********** new client connection established / secured ********'); // this.emit('secure', securePair.cleartext); // this.encryptAllFutureTraffic(); - console.log('GET FINSIHED', cleartext.getFinished()); + log('GET FINSIHED', cleartext.getFinished()); }); cleartext.on('error', (err?: Error) => { - console.log('cleartext error', err); + log('cleartext error', err); encrypted.destroy(); cleartext.destroy(err);