fix: a lot of bug fixes, first running version for windows and android :)
code is super ugly right now.. please don't judge
This commit is contained in:
		
							parent
							
								
									7e28c60d81
								
							
						
					
					
						commit
						0cb807a555
					
				
							
								
								
									
										33
									
								
								config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								config.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
import * as fs from 'fs';
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
	// radius secret
 | 
			
		||||
	secret: 'testing123',
 | 
			
		||||
 | 
			
		||||
	certificate: {
 | 
			
		||||
		cert: fs.readFileSync('./ssl/cert/server.crt'),
 | 
			
		||||
		key: [
 | 
			
		||||
			{
 | 
			
		||||
				pem: fs.readFileSync('./ssl/cert/server.key'),
 | 
			
		||||
				passphrase: 'whatever2020'
 | 
			
		||||
			}
 | 
			
		||||
		]
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// authentication
 | 
			
		||||
	authentication: 'ldap',
 | 
			
		||||
	authenticationOptions: {
 | 
			
		||||
		url: 'ldap://127.0.0.1:1636',
 | 
			
		||||
		base: 'dc=hokify,dc=com',
 | 
			
		||||
		tlsOptions2: {
 | 
			
		||||
			key: fs.readFileSync('ldap.gsuite.hokify.com.40567.key'),
 | 
			
		||||
			cert: fs.readFileSync('ldap.gsuite.hokify.com.40567.crt'),
 | 
			
		||||
 | 
			
		||||
			// This is necessary only if using the client certificate authentication.
 | 
			
		||||
			requestCert: true,
 | 
			
		||||
 | 
			
		||||
			// This is necessary only if the client uses the self-signed certificate.
 | 
			
		||||
			ca: [fs.readFileSync('ldap.gsuite.hokify.com.40567.key')]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
@ -3,7 +3,7 @@
 | 
			
		||||
  "description": "radius server for google LDAP and TTLT",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "node dist/app.js",
 | 
			
		||||
    "start": "/home/simon/Dev/others/node/node dist/app.js",
 | 
			
		||||
    "build": "tsc",
 | 
			
		||||
    "dev": "ts-node src/app.ts",
 | 
			
		||||
    "test-ttls-pap": "eapol_test -c ./ttls-pap.conf -s testing123",
 | 
			
		||||
@ -17,7 +17,8 @@
 | 
			
		||||
    "ts-node": "^8.6.2",
 | 
			
		||||
    "type-cacheable": "^4.0.0",
 | 
			
		||||
    "yargs": "~15.1.0",
 | 
			
		||||
    "md5": "^2.2.1"
 | 
			
		||||
    "md5": "^2.2.1",
 | 
			
		||||
    "passport-ldapauth": "^2.1.3"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/ldapjs": "^1.0.5",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										100
									
								
								src/app.ts
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/app.ts
									
									
									
									
									
								
							@ -3,27 +3,15 @@ import * as radius from 'radius';
 | 
			
		||||
// import * as dgram from "dgram";
 | 
			
		||||
// import * as fs from 'fs';
 | 
			
		||||
import { EAPHandler } from './eap';
 | 
			
		||||
import { makeid } from './helpers';
 | 
			
		||||
import { IDeferredPromise, makeid, MAX_RADIUS_ATTRIBUTE_SIZE, newDeferredPromise } from './helpers';
 | 
			
		||||
 | 
			
		||||
import { LDAPAuth } from './ldap';
 | 
			
		||||
import { GoogleLDAPAuth } from './auth/google-ldap';
 | 
			
		||||
import { AdditionalAuthHandler } from './types/Handler';
 | 
			
		||||
 | 
			
		||||
const server = dgram.createSocket('udp4');
 | 
			
		||||
 | 
			
		||||
// not used right now, using stunnel to connect to ldap
 | 
			
		||||
/* const tlsOptions = {
 | 
			
		||||
	key: fs.readFileSync('ldap.gsuite.hokify.com.40567.key'),
 | 
			
		||||
	cert: fs.readFileSync('ldap.gsuite.hokify.com.40567.crt'),
 | 
			
		||||
 | 
			
		||||
	// This is necessary only if using the client certificate authentication.
 | 
			
		||||
	requestCert: true,
 | 
			
		||||
 | 
			
		||||
	// This is necessary only if the client uses the self-signed certificate.
 | 
			
		||||
	ca: [fs.readFileSync('ldap.gsuite.hokify.com.40567.key')]
 | 
			
		||||
}; */
 | 
			
		||||
 | 
			
		||||
const { argv } = require('yargs')
 | 
			
		||||
	.usage('Simple Google LDAP <> RADIUS Server\nUsage: $0')
 | 
			
		||||
	.usage('RADIUS Server\nUsage: $0')
 | 
			
		||||
	.example('$0 --port 1812 -s radiussecret')
 | 
			
		||||
	.default({
 | 
			
		||||
		port: 1812,
 | 
			
		||||
@ -46,9 +34,39 @@ console.log(`LDAP Server: ${argv.ldapServer}`);
 | 
			
		||||
 | 
			
		||||
// const ldap = new LDAPAuth({url: 'ldap://ldap.google.com', base: 'dc=hokify,dc=com', uid: 'uid', tlsOptions});
 | 
			
		||||
 | 
			
		||||
const ldap = new LDAPAuth(argv.ldapServer, argv.baseDN);
 | 
			
		||||
const ldap = new GoogleLDAPAuth(argv.ldapServer, argv.baseDN);
 | 
			
		||||
 | 
			
		||||
const eapHandler = new EAPHandler();
 | 
			
		||||
const timeout: { [key: string]: NodeJS.Timeout } = {};
 | 
			
		||||
const waitForNextMsg: { [key: string]: IDeferredPromise } = {};
 | 
			
		||||
 | 
			
		||||
function sendToClient(
 | 
			
		||||
	msg: string | Uint8Array,
 | 
			
		||||
	offset: number,
 | 
			
		||||
	length: number,
 | 
			
		||||
	port?: number,
 | 
			
		||||
	address?: string,
 | 
			
		||||
	callback?: (error: Error | null, bytes: number) => void,
 | 
			
		||||
	stateForRetry?: string
 | 
			
		||||
): void {
 | 
			
		||||
	let retried = 0;
 | 
			
		||||
 | 
			
		||||
	function sendResponse() {
 | 
			
		||||
		console.log(`sending response... (try: ${retried})`);
 | 
			
		||||
		server.send(msg, offset, length, port, address, (error: Error | null, bytes: number) => {
 | 
			
		||||
			// all good
 | 
			
		||||
 | 
			
		||||
			if (callback) callback(error, bytes);
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		if (stateForRetry && retried < 3) {
 | 
			
		||||
			// timeout[stateForRetry] = setTimeout(sendResponse, 600 * (retried+1));
 | 
			
		||||
		}
 | 
			
		||||
		retried++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sendResponse();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
server.on('message', async function(msg, rinfo) {
 | 
			
		||||
	const packet = radius.decode({ packet: msg, secret: argv.secret });
 | 
			
		||||
@ -57,7 +75,6 @@ server.on('message', async function(msg, rinfo) {
 | 
			
		||||
		console.log('unknown packet type: ', packet.code);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// console.log('packet.attributes', packet.attributes);
 | 
			
		||||
 | 
			
		||||
	// console.log('rinfo', rinfo);
 | 
			
		||||
@ -90,7 +107,7 @@ server.on('message', async function(msg, rinfo) {
 | 
			
		||||
		});
 | 
			
		||||
		console.log(`Sending ${success ? 'accept' : 'reject'} for user ${username}`);
 | 
			
		||||
 | 
			
		||||
		server.send(response, 0, response.length, rinfo.port, rinfo.address, function(err, _bytes) {
 | 
			
		||||
		sendToClient(response, 0, response.length, rinfo.port, rinfo.address, function(err, _bytes) {
 | 
			
		||||
			if (err) {
 | 
			
		||||
				console.log('Error sending response to ', rinfo);
 | 
			
		||||
			}
 | 
			
		||||
@ -99,15 +116,22 @@ server.on('message', async function(msg, rinfo) {
 | 
			
		||||
 | 
			
		||||
	if (packet.attributes['EAP-Message']) {
 | 
			
		||||
		const state = (packet.attributes.State && packet.attributes.State.toString()) || makeid(16);
 | 
			
		||||
		// EAP MESSAGE
 | 
			
		||||
		eapHandler.handleEAPMessage(packet.attributes['EAP-Message'], state, {
 | 
			
		||||
 | 
			
		||||
		if (timeout[state]) {
 | 
			
		||||
			clearTimeout(timeout[state]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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 + 253)]);
 | 
			
		||||
						sentDataSize += 253;
 | 
			
		||||
						attributes.push([
 | 
			
		||||
							'EAP-Message',
 | 
			
		||||
							EAPMessage.slice(sentDataSize, sentDataSize + MAX_RADIUS_ATTRIBUTE_SIZE)
 | 
			
		||||
						]);
 | 
			
		||||
						sentDataSize += MAX_RADIUS_ATTRIBUTE_SIZE;
 | 
			
		||||
					}
 | 
			
		||||
				} while (sentDataSize < EAPMessage.length);
 | 
			
		||||
 | 
			
		||||
@ -118,14 +142,34 @@ server.on('message', async function(msg, rinfo) {
 | 
			
		||||
					attributes
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				server.send(response, 0, response.length, rinfo.port, rinfo.address, function(err, _bytes) {
 | 
			
		||||
					if (err) {
 | 
			
		||||
						console.log('Error sending response to ', rinfo);
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
				waitForNextMsg[state] = newDeferredPromise();
 | 
			
		||||
 | 
			
		||||
				sendToClient(
 | 
			
		||||
					response,
 | 
			
		||||
					0,
 | 
			
		||||
					response.length,
 | 
			
		||||
					rinfo.port,
 | 
			
		||||
					rinfo.address,
 | 
			
		||||
					function(err, _bytes) {
 | 
			
		||||
						if (err) {
 | 
			
		||||
							console.log('Error sending response to ', rinfo);
 | 
			
		||||
						}
 | 
			
		||||
					},
 | 
			
		||||
					state
 | 
			
		||||
				);
 | 
			
		||||
 | 
			
		||||
				return waitForNextMsg[state].promise;
 | 
			
		||||
			},
 | 
			
		||||
			checkAuth
 | 
			
		||||
		});
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		if (waitForNextMsg[state]) {
 | 
			
		||||
			const identifier = packet.attributes['EAP-Message'].slice(1, 2).readUInt8(0); // .toString('hex');
 | 
			
		||||
			waitForNextMsg[state].resolve({ response: handlers.response, identifier });
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// EAP MESSAGE
 | 
			
		||||
		eapHandler.handleEAPMessage(packet.attributes['EAP-Message'], state, handlers);
 | 
			
		||||
	} else {
 | 
			
		||||
		const username = packet.attributes['User-Name'];
 | 
			
		||||
		const password = packet.attributes['User-Password'];
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,14 @@
 | 
			
		||||
import * as NodeCache from 'node-cache';
 | 
			
		||||
 | 
			
		||||
import { createClient, Client } from 'ldapjs';
 | 
			
		||||
import { IAuthentication } from '../types/Authentication';
 | 
			
		||||
 | 
			
		||||
const usernameFields = ['posixUid', 'mail'];
 | 
			
		||||
 | 
			
		||||
// TLS:
 | 
			
		||||
// https://github.com/ldapjs/node-ldapjs/issues/307
 | 
			
		||||
 | 
			
		||||
export class LDAPAuth {
 | 
			
		||||
export class GoogleLDAPAuth implements IAuthentication {
 | 
			
		||||
	cache = new NodeCache();
 | 
			
		||||
 | 
			
		||||
	ldap: Client;
 | 
			
		||||
@ -24,7 +25,7 @@ export class LDAPAuth {
 | 
			
		||||
		this.fetchDNs();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async fetchDNs() {
 | 
			
		||||
	private async fetchDNs() {
 | 
			
		||||
		const dns: { [key: string]: string } = {};
 | 
			
		||||
 | 
			
		||||
		await new Promise((resolve, reject) => {
 | 
			
		||||
@ -119,6 +120,6 @@ export class LDAPAuth {
 | 
			
		||||
 | 
			
		||||
		this.cache.set(cacheKey, true, 86400);
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
		return username;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										80
									
								
								src/eap.ts
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								src/eap.ts
									
									
									
									
									
								
							@ -4,6 +4,7 @@
 | 
			
		||||
// https://tools.ietf.org/html/draft-funk-eap-ttls-v1-00 TTLS v1 (not implemented)
 | 
			
		||||
import { IResponseHandlers, ResponseHandler } from './types/Handler';
 | 
			
		||||
import { EAPTTLS } from './eap/eap-ttls';
 | 
			
		||||
import { MAX_RADIUS_ATTRIBUTE_SIZE } from './helpers';
 | 
			
		||||
 | 
			
		||||
export class EAPHandler {
 | 
			
		||||
	eapTTLS: EAPTTLS;
 | 
			
		||||
@ -17,28 +18,35 @@ export class EAPHandler {
 | 
			
		||||
	 * @param data
 | 
			
		||||
	 * @param type 1 = identity, 21 = EAP-TTLS, 2 = notification, 4 = md5-challenge, 3 = NAK
 | 
			
		||||
	 */
 | 
			
		||||
	private sendEAPResponse(
 | 
			
		||||
	private async sendEAPResponse(
 | 
			
		||||
		response: ResponseHandler,
 | 
			
		||||
		identifier: number,
 | 
			
		||||
		data?: Buffer,
 | 
			
		||||
		msgType = 21,
 | 
			
		||||
		msgFlags = 0x00
 | 
			
		||||
	) {
 | 
			
		||||
		const maxFragmentSize = 1400; // @todo .. take framed-mtu into account from AVPs
 | 
			
		||||
		let i = 0;
 | 
			
		||||
 | 
			
		||||
		const maxSize = (MAX_RADIUS_ATTRIBUTE_SIZE - 5) * 4;
 | 
			
		||||
 | 
			
		||||
		let sentDataSize = 0;
 | 
			
		||||
 | 
			
		||||
		let currentIdentifier = identifier;
 | 
			
		||||
		let currentResponse = response;
 | 
			
		||||
 | 
			
		||||
		do {
 | 
			
		||||
			const fragmentMaxPart =
 | 
			
		||||
				data && (i + 1) * maxFragmentSize > data.length ? undefined : (i + 1) * maxFragmentSize;
 | 
			
		||||
			const sslPart = data && data.slice(i * maxFragmentSize, fragmentMaxPart);
 | 
			
		||||
			console.log('sslPart', sslPart, i, maxFragmentSize, i * maxFragmentSize, fragmentMaxPart);
 | 
			
		||||
			// SLICE
 | 
			
		||||
 | 
			
		||||
			const includeLength =
 | 
			
		||||
				data &&
 | 
			
		||||
				i === 0 &&
 | 
			
		||||
				fragmentMaxPart !== undefined; /* firsrt one and we have more, therefore include length */
 | 
			
		||||
			// const fragmentMaxPart =
 | 
			
		||||
			// data && (i + 1) * maxFragmentSize > data.length ? (i + 1) * maxFragmentSize : undefined;
 | 
			
		||||
 | 
			
		||||
			const dataPart = data && data.length > 0 && data.slice(sentDataSize, sentDataSize + maxSize);
 | 
			
		||||
 | 
			
		||||
			/* it's the first one and we have more, therefore include length */
 | 
			
		||||
			const includeLength = data && i === 0 && sentDataSize < data.length;
 | 
			
		||||
 | 
			
		||||
			sentDataSize += maxSize;
 | 
			
		||||
 | 
			
		||||
			// console.log('includeLength', includeLength, fragmentMaxPart, i)
 | 
			
		||||
			i += 1;
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
@ -62,11 +70,13 @@ export class EAPHandler {
 | 
			
		||||
			const flags =
 | 
			
		||||
				msgFlags +
 | 
			
		||||
				(includeLength ? 0b10000000 : 0) + // set L bit
 | 
			
		||||
				(fragmentMaxPart /* we have more */ ? 0b01000000 : 0); // set M bit
 | 
			
		||||
				(data && sentDataSize < data.length /* we have more */ ? 0b01000000 : 0); // set M bit
 | 
			
		||||
 | 
			
		||||
			currentIdentifier++;
 | 
			
		||||
 | 
			
		||||
			let buffer = Buffer.from([
 | 
			
		||||
				1, // request
 | 
			
		||||
				identifier + 1,
 | 
			
		||||
				currentIdentifier,
 | 
			
		||||
				0, // length (1/2)
 | 
			
		||||
				0, //  length (2/2)
 | 
			
		||||
				msgType, // 1 = identity, 21 = EAP-TTLS, 2 = notificaiton, 4 = md5-challenge, 3 = NAK
 | 
			
		||||
@ -81,15 +91,16 @@ export class EAPHandler {
 | 
			
		||||
				buffer = Buffer.concat([buffer, length]);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			const resBuffer = sslPart ? Buffer.concat([buffer, sslPart]) : buffer;
 | 
			
		||||
			const resBuffer = dataPart ? Buffer.concat([buffer, dataPart]) : buffer;
 | 
			
		||||
			resBuffer.writeUInt16BE(resBuffer.byteLength, 2);
 | 
			
		||||
 | 
			
		||||
			console.log('EAP RESPONSE', {
 | 
			
		||||
			console.log('<<<<<<<<<<<< EAP RESPONSE TO CLIENT', {
 | 
			
		||||
				code: 1,
 | 
			
		||||
				identifier: identifier + 1,
 | 
			
		||||
				length: (includeLength && data && data.byteLength) || 0,
 | 
			
		||||
				msgType,
 | 
			
		||||
				flags,
 | 
			
		||||
				currentIdentifier,
 | 
			
		||||
				includeLength,
 | 
			
		||||
				length: (data && data.byteLength) || 0,
 | 
			
		||||
				msgType: msgType.toString(10),
 | 
			
		||||
				flags: `00000000${flags.toString(2)}`.substr(-8),
 | 
			
		||||
				data
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
@ -98,13 +109,14 @@ export class EAPHandler {
 | 
			
		||||
			// buffer.writeInt8(21, 4); // eap-ttls
 | 
			
		||||
			// buffer.writeInt8(0, 5); // flags
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
            @todo: this is wrong,
 | 
			
		||||
            if there are more messages, add them to a queue
 | 
			
		||||
            and process the next one when client has ack. (message without data)
 | 
			
		||||
             */
 | 
			
		||||
			response(resBuffer);
 | 
			
		||||
		} while (data && i * maxFragmentSize < data.length);
 | 
			
		||||
			console.log('sending message with identifier', currentIdentifier);
 | 
			
		||||
			({ identifier: currentIdentifier, response: currentResponse } = await currentResponse(
 | 
			
		||||
				resBuffer
 | 
			
		||||
			));
 | 
			
		||||
			console.log('next message got identifier', currentIdentifier);
 | 
			
		||||
		} while (data && sentDataSize < data.length);
 | 
			
		||||
 | 
			
		||||
		console.log('DONE', sentDataSize, data && data.length);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	handleEAPMessage(msg: Buffer, state: string, handlers: IResponseHandlers) {
 | 
			
		||||
@ -148,8 +160,7 @@ export class EAPHandler {
 | 
			
		||||
						 Message Length         |             Data...
 | 
			
		||||
						 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
						 */
 | 
			
		||||
 | 
			
		||||
						console.log('RESPONDING WITH IDENTIDY / START');
 | 
			
		||||
						console.log('>>>>>>>>>>>> REQUEST FROM CLIENT: IDENTIFY', {});
 | 
			
		||||
 | 
			
		||||
						this.sendEAPResponse(handlers.response, identifier, undefined, 21, 0x20);
 | 
			
		||||
 | 
			
		||||
@ -167,14 +178,17 @@ export class EAPHandler {
 | 
			
		||||
						break;
 | 
			
		||||
					case 21: // EAP TTLS
 | 
			
		||||
						this.eapTTLS.handleMessage(msg, state, handlers, identifier);
 | 
			
		||||
						return;
 | 
			
		||||
						break;
 | 
			
		||||
					case 3: // nak
 | 
			
		||||
						this.sendEAPResponse(handlers.response, identifier, undefined, 3);
 | 
			
		||||
						// this.sendEAPResponse(handlers.response, identifier, undefined, 3);
 | 
			
		||||
						break;
 | 
			
		||||
					case 2: // notification
 | 
			
		||||
						console.log('>>>>>>>>>>>> REQUEST FROM CLIENT: notification', {});
 | 
			
		||||
						console.info('notification');
 | 
			
		||||
						break;
 | 
			
		||||
					case 4: // md5-challenge
 | 
			
		||||
						console.log('>>>>>>>>>>>> REQUEST FROM CLIENT: md5-challenge', {});
 | 
			
		||||
 | 
			
		||||
						console.info('md5-challenge');
 | 
			
		||||
						break;
 | 
			
		||||
					case 254: // expanded type
 | 
			
		||||
@ -183,7 +197,11 @@ export class EAPHandler {
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
					default:
 | 
			
		||||
						console.error('unsupported type', type);
 | 
			
		||||
						// we do not support this auth type, ask for TTLS
 | 
			
		||||
						console.error('unsupported type', type, 'requesting TTLS (21)');
 | 
			
		||||
 | 
			
		||||
						this.sendEAPResponse(handlers.response, identifier, Buffer.from([21]), 3);
 | 
			
		||||
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import { IAuthChallenge } from '../../types/AuthChallenge';
 | 
			
		||||
import { IEAPChallenge } from '../../types/EAPChallenge';
 | 
			
		||||
 | 
			
		||||
export class PAPChallenge implements IAuthChallenge {
 | 
			
		||||
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 ?
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,16 @@
 | 
			
		||||
/* eslint-disable no-bitwise */
 | 
			
		||||
import * as events from 'events';
 | 
			
		||||
import * as tls from 'tls';
 | 
			
		||||
import { encodeTunnelPW, openTLSSockets, startTLSServer } from '../tls/crypt';
 | 
			
		||||
import { AdditionalAuthHandler, IResponseHandlers } from '../types/Handler';
 | 
			
		||||
import { AdditionalAuthHandler, ResponseAuthHandler } from '../types/Handler';
 | 
			
		||||
import { PAPChallenge } from './challenges/pap';
 | 
			
		||||
import { IEAPType } from '../types/EAPType';
 | 
			
		||||
 | 
			
		||||
interface IEAPResponseHandlers {
 | 
			
		||||
	response: (respData?: Buffer, msgType?: number) => void;
 | 
			
		||||
	checkAuth: ResponseAuthHandler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class EAPTTLS implements IEAPType {
 | 
			
		||||
	papChallenge: PAPChallenge;
 | 
			
		||||
 | 
			
		||||
@ -12,23 +18,48 @@ export class EAPTTLS implements IEAPType {
 | 
			
		||||
		this.papChallenge = new PAPChallenge();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	handleMessage(msg: Buffer, state: string, handlers, identifier: number) {
 | 
			
		||||
		const flags = msg.slice(5, 6); // .toString('hex');
 | 
			
		||||
	decode(msg: Buffer) {
 | 
			
		||||
		const flags = msg.slice(5, 6).readUInt8(0); // .toString('hex');
 | 
			
		||||
 | 
			
		||||
		// if (flags)
 | 
			
		||||
		// @todo check if "L" flag is set in flags
 | 
			
		||||
		const msglength = msg.slice(6, 10).readInt32BE(0); // .toString('hex');
 | 
			
		||||
		const data = msg.slice(6, msg.length); // 10); //.toString('hex');
 | 
			
		||||
		const decodedFlags = {
 | 
			
		||||
			lengthIncluded: flags & 0b010000000,
 | 
			
		||||
			moreFragments: flags & 0b001000000,
 | 
			
		||||
			start: flags & 0b000100000,
 | 
			
		||||
			reserved: flags & 0b000011000,
 | 
			
		||||
			version: flags & 0b010000111
 | 
			
		||||
		};
 | 
			
		||||
		let msglength;
 | 
			
		||||
		if (decodedFlags.lengthIncluded) {
 | 
			
		||||
			msglength = msg.slice(6, 10).readInt32BE(0); // .readDoubleLE(0); // .toString('hex');
 | 
			
		||||
		}
 | 
			
		||||
		const data = msg.slice(decodedFlags.lengthIncluded ? 10 : 6, msg.length);
 | 
			
		||||
 | 
			
		||||
		return {
 | 
			
		||||
			decodedFlags,
 | 
			
		||||
			msglength,
 | 
			
		||||
			data
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	handleMessage(msg: Buffer, state: string, handlers, identifier: number) {
 | 
			
		||||
		const { decodedFlags, msglength, data } = this.decode(msg);
 | 
			
		||||
 | 
			
		||||
		// check if no data package is there and we have something in the queue, if so.. empty the queue first
 | 
			
		||||
		if (!data) {
 | 
			
		||||
		if (!data || data.length === 0) {
 | 
			
		||||
			// @todo: queue processing
 | 
			
		||||
			console.warn('no data, just a confirmation!');
 | 
			
		||||
			console.warn(
 | 
			
		||||
				`>>>>>>>>>>>> REQUEST FROM CLIENT: EAP TTLS, ACK / NACK (no data, just a confirmation, ID: ${identifier})`
 | 
			
		||||
			);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		console.log('incoming EAP TTLS', {
 | 
			
		||||
			flags /*
 | 
			
		||||
		console.log('>>>>>>>>>>>> REQUEST FROM CLIENT: EAP TTLS', {
 | 
			
		||||
			// flags: `00000000${flags.toString(2)}`.substr(-8),
 | 
			
		||||
			decodedFlags,
 | 
			
		||||
			identifier,
 | 
			
		||||
			/*
 | 
			
		||||
                      0   1   2   3   4   5   6   7
 | 
			
		||||
                    +---+---+---+---+---+---+---+---+
 | 
			
		||||
                    | L | M | S | R | R |     V     |
 | 
			
		||||
@ -39,14 +70,15 @@ export class EAPTTLS implements IEAPType {
 | 
			
		||||
                    S = Start
 | 
			
		||||
                    R = Reserved
 | 
			
		||||
                    V = Version (000 for EAP-TTLSv0)
 | 
			
		||||
                    */,
 | 
			
		||||
                    */
 | 
			
		||||
 | 
			
		||||
			msglength,
 | 
			
		||||
			data,
 | 
			
		||||
			dataStr: data.toString()
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		let currentConnection = openTLSSockets.get(state) as
 | 
			
		||||
			| { events: events.EventEmitter; tls: tls.TLSSocket; currentHandlers: IResponseHandlers }
 | 
			
		||||
			| { events: events.EventEmitter; tls: tls.TLSSocket; currentHandlers: IEAPResponseHandlers }
 | 
			
		||||
			| undefined;
 | 
			
		||||
		if (!currentConnection) {
 | 
			
		||||
			const connection = startTLSServer();
 | 
			
		||||
@ -71,12 +103,15 @@ export class EAPTTLS implements IEAPType {
 | 
			
		||||
							// pwd not found..
 | 
			
		||||
							console.error('pwd not found', err);
 | 
			
		||||
							// NAK
 | 
			
		||||
							currentConnection!.currentHandlers.response(undefined, 3);
 | 
			
		||||
 | 
			
		||||
							/*
 | 
			
		||||
							this.sendEAPResponse(
 | 
			
		||||
								currentConnection!.currentHandlers.response,
 | 
			
		||||
								identifier,
 | 
			
		||||
								undefined,
 | 
			
		||||
								3
 | 
			
		||||
							);
 | 
			
		||||
							); */
 | 
			
		||||
							currentConnection!.events.emit('end');
 | 
			
		||||
							throw new Error(`pwd not found`);
 | 
			
		||||
						}
 | 
			
		||||
@ -85,16 +120,28 @@ export class EAPTTLS implements IEAPType {
 | 
			
		||||
						console.log('data', incomingData);
 | 
			
		||||
						console.log('data str', incomingData.toString());
 | 
			
		||||
 | 
			
		||||
						currentConnection!.events.emit('end');
 | 
			
		||||
						throw new Error(`unsupported auth type${type}`);
 | 
			
		||||
						// currentConnection!.events.emit('end');
 | 
			
		||||
 | 
			
		||||
						console.log('UNSUPPORTED AUTH TYPE, requesting PAP');
 | 
			
		||||
						// throw new Error(`unsupported auth type${type}`);
 | 
			
		||||
						currentConnection!.currentHandlers.response(Buffer.from([1]), 3);
 | 
			
		||||
 | 
			
		||||
					/*
 | 
			
		||||
						this.sendEAPResponse(
 | 
			
		||||
							currentConnection!.currentHandlers.response,
 | 
			
		||||
							identifier,
 | 
			
		||||
							Buffer.from([1]),
 | 
			
		||||
							3
 | 
			
		||||
						); */
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			currentConnection.events.on('response', (responseData: Buffer) => {
 | 
			
		||||
				console.log('sending encrypted data back to client', responseData);
 | 
			
		||||
				// console.log('sending encrypted data back to client', responseData);
 | 
			
		||||
 | 
			
		||||
				// send back...
 | 
			
		||||
				this.sendEAPResponse(currentConnection!.currentHandlers.response, identifier, responseData);
 | 
			
		||||
				currentConnection!.currentHandlers.response(responseData);
 | 
			
		||||
				// this.sendEAPResponse(currentConnection!.currentHandlers.response, identifier, responseData);
 | 
			
		||||
				// this.sendMessage(TYPE.PRELOGIN, data, false);
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
@ -103,13 +150,14 @@ export class EAPTTLS implements IEAPType {
 | 
			
		||||
				console.log('ENDING SOCKET');
 | 
			
		||||
				openTLSSockets.del(state);
 | 
			
		||||
			});
 | 
			
		||||
		} else {
 | 
			
		||||
		} /* else {
 | 
			
		||||
			console.log('using existing socket');
 | 
			
		||||
		}
 | 
			
		||||
		} */
 | 
			
		||||
 | 
			
		||||
		// update handlers
 | 
			
		||||
		currentConnection.currentHandlers = {
 | 
			
		||||
			...handlers,
 | 
			
		||||
			response: (respData?: Buffer, msgType?: number) =>
 | 
			
		||||
				this.sendEAPResponse(handlers.response, identifier, respData, msgType),
 | 
			
		||||
			checkAuth: (username: string, password: string) => {
 | 
			
		||||
				const additionalAuthHandler: AdditionalAuthHandler = (success, params) => {
 | 
			
		||||
					const buffer = Buffer.from([
 | 
			
		||||
@ -138,7 +186,7 @@ export class EAPTTLS implements IEAPType {
 | 
			
		||||
						'ttls keying material'
 | 
			
		||||
					);
 | 
			
		||||
 | 
			
		||||
					console.log('keyingMaterial', keyingMaterial);
 | 
			
		||||
					// console.log('keyingMaterial', keyingMaterial);
 | 
			
		||||
 | 
			
		||||
					// eapKeyData + len
 | 
			
		||||
					params.attributes.push([
 | 
			
		||||
 | 
			
		||||
@ -7,3 +7,33 @@ export function makeid(length) {
 | 
			
		||||
	}
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const MAX_RADIUS_ATTRIBUTE_SIZE = 253;
 | 
			
		||||
 | 
			
		||||
export interface IDeferredPromise {
 | 
			
		||||
	promise: Promise<any>;
 | 
			
		||||
	resolve: (value?: unknown) => Promise<void>;
 | 
			
		||||
	reject: (reason?: any) => Promise<void>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const newDeferredPromise = (): IDeferredPromise => {
 | 
			
		||||
	if (Promise && !('deferred' in Promise)) {
 | 
			
		||||
		let fResolve;
 | 
			
		||||
		let fReject;
 | 
			
		||||
 | 
			
		||||
		const P = new Promise((resolve, reject) => {
 | 
			
		||||
			fResolve = resolve;
 | 
			
		||||
			fReject = reject;
 | 
			
		||||
		});
 | 
			
		||||
		return {
 | 
			
		||||
			promise: P,
 | 
			
		||||
			resolve: fResolve,
 | 
			
		||||
			reject: fReject
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (Promise as any).deferred;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const delay = (timeout: number) =>
 | 
			
		||||
	new Promise(resolve => setTimeout(() => resolve(), timeout));
 | 
			
		||||
 | 
			
		||||
@ -5,14 +5,21 @@ import { createSecureContext } from 'tls';
 | 
			
		||||
import * as fs from 'fs';
 | 
			
		||||
import * as crypto from 'crypto';
 | 
			
		||||
import * as DuplexPair from 'native-duplexpair';
 | 
			
		||||
import * as constants from 'constants';
 | 
			
		||||
import { makeid } from '../helpers';
 | 
			
		||||
import * as config from '../../config';
 | 
			
		||||
 | 
			
		||||
// https://nodejs.org/api/tls.html
 | 
			
		||||
const tlsOptions = {
 | 
			
		||||
	cert: fs.readFileSync('./ssl/public-cert.pem'),
 | 
			
		||||
	key: fs.readFileSync('./ssl/private-key.pem'),
 | 
			
		||||
	ecdhCurve: 'auto'
 | 
			
		||||
const tlsOptions: tls.SecureContextOptions = {
 | 
			
		||||
	...config.certificate,
 | 
			
		||||
	// ca: fs.readFileSync('./ssl/server.pem'),
 | 
			
		||||
	// eslint-disable-next-line no-bitwise
 | 
			
		||||
	secureOptions: constants.SSL_OP_NO_TICKET // : constants.SSL_OP_NO_TLSv1_2 | constants.SSL_OP_NO_TLSv1_1,
 | 
			
		||||
	// honorCipherOrder: true
 | 
			
		||||
	// secureOptions:
 | 
			
		||||
	// ecdhCurve: 'auto'
 | 
			
		||||
};
 | 
			
		||||
console.log('tlsOptions', tlsOptions);
 | 
			
		||||
const secureContext = createSecureContext(tlsOptions);
 | 
			
		||||
export const openTLSSockets = new NodeCache({ useClones: false, stdTTL: 3600 }); // keep sockets for about one hour
 | 
			
		||||
 | 
			
		||||
@ -22,7 +29,11 @@ export function startTLSServer(): { events: events.EventEmitter; tls: tls.TLSSoc
 | 
			
		||||
 | 
			
		||||
	const cleartext = new tls.TLSSocket(duplexpair.socket1, {
 | 
			
		||||
		secureContext,
 | 
			
		||||
		isServer: true
 | 
			
		||||
		isServer: true,
 | 
			
		||||
		enableTrace: true,
 | 
			
		||||
		rejectUnauthorized: false,
 | 
			
		||||
		// handshakeTimeout: 10,
 | 
			
		||||
		requestCert: false
 | 
			
		||||
	});
 | 
			
		||||
	const encrypted = duplexpair.socket2;
 | 
			
		||||
 | 
			
		||||
@ -71,6 +82,7 @@ export function startTLSServer(): { events: events.EventEmitter; tls: tls.TLSSoc
 | 
			
		||||
		console.log('*********** new client connection established / secured ********');
 | 
			
		||||
		//        this.emit('secure', securePair.cleartext);
 | 
			
		||||
		//        this.encryptAllFutureTraffic();
 | 
			
		||||
		console.log('GET FINSIHED', cleartext.getFinished());
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	cleartext.on('error', (err?: Error) => {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								src/types/Authentication.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/types/Authentication.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
export interface IAuthentication {
 | 
			
		||||
	authenticate(username: string, password: string): Promise<string>;
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,3 @@
 | 
			
		||||
export interface IAuthChallenge {
 | 
			
		||||
export interface IEAPChallenge {
 | 
			
		||||
	decode(data: Buffer): { username: string; password: string };
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,3 @@
 | 
			
		||||
export interface IEAPType {
 | 
			
		||||
    handleMessage(msg: Buffer, state: string, handlers, identifier: number)
 | 
			
		||||
	handleMessage(msg: Buffer, state: string, handlers, identifier: number);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
import { RadiusPacket } from 'radius';
 | 
			
		||||
 | 
			
		||||
export type ResponseHandler = (msg: Buffer) => void;
 | 
			
		||||
export type ResponseHandler = (
 | 
			
		||||
	msg: Buffer
 | 
			
		||||
) => Promise<{ identifier: number; response: ResponseHandler }>;
 | 
			
		||||
export type ResponseAuthHandler = (
 | 
			
		||||
	username: string,
 | 
			
		||||
	password: string,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								ssl/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ssl/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
this is based on freeradius cert directory :)
 | 
			
		||||
 | 
			
		||||
1.) edit ca.cnf
 | 
			
		||||
2.) edit server.cnf
 | 
			
		||||
3.) replace your choosen pwd (deafult is whatever2020) in create.sh
 | 
			
		||||
4.) run ./create.sh
 | 
			
		||||
5.) set your choosen pwd in ~/config.js  
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								ssl/ca.cnf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								ssl/ca.cnf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
[ ca ]
 | 
			
		||||
default_ca              = CA_default
 | 
			
		||||
 | 
			
		||||
[ CA_default ]
 | 
			
		||||
dir                     = ./cert/
 | 
			
		||||
certs                   = $dir
 | 
			
		||||
crl_dir                 = $dir/crl
 | 
			
		||||
database                = db/index.txt
 | 
			
		||||
new_certs_dir           = $dir
 | 
			
		||||
certificate             = $dir/ca.pem
 | 
			
		||||
serial                  = db/serial
 | 
			
		||||
crl                     = $dir/crl.pem
 | 
			
		||||
private_key             = $dir/ca.key
 | 
			
		||||
RANDFILE                = $dir/.rand
 | 
			
		||||
name_opt                = ca_default
 | 
			
		||||
cert_opt                = ca_default
 | 
			
		||||
default_days            = 60
 | 
			
		||||
default_crl_days        = 30
 | 
			
		||||
default_md              = sha256
 | 
			
		||||
preserve                = no
 | 
			
		||||
policy                  = policy_match
 | 
			
		||||
crlDistributionPoints   = URI:http://www.example.org/example_ca.crl
 | 
			
		||||
 | 
			
		||||
[ policy_match ]
 | 
			
		||||
countryName             = match
 | 
			
		||||
stateOrProvinceName     = match
 | 
			
		||||
organizationName        = match
 | 
			
		||||
organizationalUnitName  = optional
 | 
			
		||||
commonName              = supplied
 | 
			
		||||
emailAddress            = optional
 | 
			
		||||
 | 
			
		||||
[ policy_anything ]
 | 
			
		||||
countryName             = optional
 | 
			
		||||
stateOrProvinceName     = optional
 | 
			
		||||
localityName            = optional
 | 
			
		||||
organizationName        = optional
 | 
			
		||||
organizationalUnitName  = optional
 | 
			
		||||
commonName              = supplied
 | 
			
		||||
emailAddress            = optional
 | 
			
		||||
 | 
			
		||||
[ req ]
 | 
			
		||||
prompt                  = no
 | 
			
		||||
distinguished_name      = certificate_authority
 | 
			
		||||
default_bits            = 2048
 | 
			
		||||
input_password          = whatever2020
 | 
			
		||||
output_password         = whatever2020
 | 
			
		||||
x509_extensions         = v3_ca
 | 
			
		||||
 | 
			
		||||
[certificate_authority]
 | 
			
		||||
countryName             = AT
 | 
			
		||||
stateOrProvinceName     = Vienna
 | 
			
		||||
localityName            = Vienna
 | 
			
		||||
organizationName        = hokify.com
 | 
			
		||||
emailAddress            = info@hokify.com
 | 
			
		||||
commonName              = "hokify GmbH"
 | 
			
		||||
 | 
			
		||||
[v3_ca]
 | 
			
		||||
subjectKeyIdentifier    = hash
 | 
			
		||||
authorityKeyIdentifier  = keyid:always,issuer:always
 | 
			
		||||
basicConstraints        = critical,CA:true
 | 
			
		||||
crlDistributionPoints   = URI:http://www.example.org/example_ca.crl
 | 
			
		||||
							
								
								
									
										0
									
								
								ssl/cert/index.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								ssl/cert/index.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1
									
								
								ssl/cert/serial
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ssl/cert/serial
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
00
 | 
			
		||||
@ -1,2 +1,15 @@
 | 
			
		||||
openssl genrsa -out private-key.pem 1024
 | 
			
		||||
openssl req -new -key private-key.pem -out csr.pem
 | 
			
		||||
# generate private key
 | 
			
		||||
# openssl genrsa -out csr.key 2048
 | 
			
		||||
 | 
			
		||||
# CA
 | 
			
		||||
openssl req -new -x509 -keyout cert/ca.key -out cert/ca.pem -days 3600 -config ./ca.cnf
 | 
			
		||||
 | 
			
		||||
# server
 | 
			
		||||
openssl req -new  -out cert/server.csr -keyout cert/server.key -config ./server.cnf
 | 
			
		||||
 | 
			
		||||
# sign it
 | 
			
		||||
# -key $(PASSWORD_CA) (default pwd is whatever2020)
 | 
			
		||||
openssl ca -batch -keyfile cert/ca.key -cert cert/ca.pem -in cert/server.csr -key whatever2020 -out cert/server.crt -extensions xpserver_ext -extfile xpextensions -config ./server.cnf
 | 
			
		||||
 | 
			
		||||
# sign it
 | 
			
		||||
# openssl x509 -req -in csr.pem -signkey private-key.pem -out public-cert.pem
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								ssl/server.cnf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								ssl/server.cnf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
[ ca ]
 | 
			
		||||
default_ca		= CA_default
 | 
			
		||||
 | 
			
		||||
[ CA_default ]
 | 
			
		||||
dir			= ./cert/
 | 
			
		||||
certs			= $dir
 | 
			
		||||
crl_dir			= $dir/crl
 | 
			
		||||
database		= db/index.txt
 | 
			
		||||
new_certs_dir		= $dir
 | 
			
		||||
certificate		= $dir/server.pem
 | 
			
		||||
serial			= db/serial
 | 
			
		||||
crl			= $dir/crl.pem
 | 
			
		||||
private_key		= $dir/server.key
 | 
			
		||||
RANDFILE		= $dir/.rand
 | 
			
		||||
name_opt		= ca_default
 | 
			
		||||
cert_opt		= ca_default
 | 
			
		||||
default_days		= 6000
 | 
			
		||||
default_crl_days	= 30
 | 
			
		||||
default_md		= sha256
 | 
			
		||||
preserve		= no
 | 
			
		||||
policy			= policy_match
 | 
			
		||||
 | 
			
		||||
[ policy_match ]
 | 
			
		||||
countryName		= match
 | 
			
		||||
stateOrProvinceName	= match
 | 
			
		||||
organizationName	= match
 | 
			
		||||
organizationalUnitName	= optional
 | 
			
		||||
commonName		= supplied
 | 
			
		||||
emailAddress		= optional
 | 
			
		||||
 | 
			
		||||
[ policy_anything ]
 | 
			
		||||
countryName		= optional
 | 
			
		||||
stateOrProvinceName	= optional
 | 
			
		||||
localityName		= optional
 | 
			
		||||
organizationName	= optional
 | 
			
		||||
organizationalUnitName	= optional
 | 
			
		||||
commonName		= supplied
 | 
			
		||||
emailAddress		= optional
 | 
			
		||||
 | 
			
		||||
[ req ]
 | 
			
		||||
prompt			= no
 | 
			
		||||
distinguished_name	= server
 | 
			
		||||
default_bits		= 2048
 | 
			
		||||
input_password		= whatever2020
 | 
			
		||||
output_password		= whatever2020
 | 
			
		||||
 | 
			
		||||
[server]
 | 
			
		||||
countryName		= AT
 | 
			
		||||
stateOrProvinceName	= Vienna
 | 
			
		||||
localityName		= Vienna
 | 
			
		||||
organizationName	= hokify.com
 | 
			
		||||
emailAddress		= info@hokify.com
 | 
			
		||||
commonName		= "hokify GmbH"
 | 
			
		||||
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
openssl x509 -req -in csr.pem -signkey private-key.pem -out public-cert.pem
 | 
			
		||||
							
								
								
									
										24
									
								
								ssl/xpextensions
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								ssl/xpextensions
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
#
 | 
			
		||||
#  File containing the OIDs required for Windows.
 | 
			
		||||
#
 | 
			
		||||
#  http://support.microsoft.com/kb/814394/en-us
 | 
			
		||||
#
 | 
			
		||||
[ xpclient_ext]
 | 
			
		||||
extendedKeyUsage = 1.3.6.1.5.5.7.3.2
 | 
			
		||||
crlDistributionPoints = URI:http://www.example.com/example_ca.crl
 | 
			
		||||
 | 
			
		||||
[ xpserver_ext]
 | 
			
		||||
extendedKeyUsage = 1.3.6.1.5.5.7.3.1
 | 
			
		||||
crlDistributionPoints = URI:http://www.example.com/example_ca.crl
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
#  Add this to the PKCS#7 keybag attributes holding the client's private key
 | 
			
		||||
#  for machine authentication.
 | 
			
		||||
#
 | 
			
		||||
#  the presence of this OID tells Windows XP that the cert is intended
 | 
			
		||||
#  for use by the computer itself, and not by an end-user.
 | 
			
		||||
#
 | 
			
		||||
#  The other solution is to use Microsoft's web certificate server
 | 
			
		||||
#  to generate these certs.
 | 
			
		||||
#
 | 
			
		||||
# 1.3.6.1.4.1.311.17.2
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user