fix tls connect

Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-12-27 03:58:56 +01:00
padre d41701664d
commit 2a968b00fe
Se han modificado 2 ficheros con 80 adiciones y 38 borrados

Ver fichero

@@ -24,15 +24,11 @@ class C2SServer extends EventEmitter {
async start() { async start() {
const port = this.config.get('network.c2s.port', 5222); const port = this.config.get('network.c2s.port', 5222);
const interface_ = this.config.get('network.c2s.interface', '0.0.0.0'); const interface_ = this.config.get('network.c2s.interface', '0.0.0.0');
const tlsEnabled = this.config.get('network.c2s.tls.enabled', true);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
if (tlsEnabled) { // C2S always starts as plain connection and negotiates STARTTLS later
this.startTLSServer(port, interface_, resolve, reject);
} else {
this.startPlainServer(port, interface_, resolve, reject); this.startPlainServer(port, interface_, resolve, reject);
}
} catch (error) { } catch (error) {
reject(error); reject(error);
} }
@@ -55,38 +51,6 @@ class C2SServer extends EventEmitter {
}); });
} }
startTLSServer(port, interface_, resolve, reject) {
const tlsOptions = this.getTLSOptions();
this.server = tls.createServer(tlsOptions, (socket) => {
this.handleConnection(socket, true);
});
this.server.on('error', (error) => {
this.logger.error('C2S TLS server error:', error);
if (reject) reject(error);
});
this.server.on('tlsClientError', (error) => {
this.logger.error('TLS client error:', error);
});
this.server.listen(port, interface_, () => {
this.logger.info(`C2S TLS server listening on ${interface_}:${port}`);
if (resolve) resolve();
});
}
getTLSOptions() {
// In production, load from config
return {
// key: fs.readFileSync(this.config.get('security.tlsKeyPath')),
// cert: fs.readFileSync(this.config.get('security.tlsCertPath')),
requestCert: false,
rejectUnauthorized: false
};
}
handleConnection(socket, isSecure) { handleConnection(socket, isSecure) {
const remoteAddress = socket.remoteAddress; const remoteAddress = socket.remoteAddress;
const connectionId = `c2s-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const connectionId = `c2s-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

Ver fichero

@@ -7,6 +7,8 @@ const EventEmitter = require('events');
const ltx = require('ltx'); const ltx = require('ltx');
const Logger = require('../utils/logger'); const Logger = require('../utils/logger');
const crypto = require('crypto'); const crypto = require('crypto');
const tls = require('tls');
const fs = require('fs');
// Simple XML stream parser // Simple XML stream parser
class StreamParser extends EventEmitter { class StreamParser extends EventEmitter {
@@ -254,6 +256,12 @@ class XMPPStream extends EventEmitter {
this.logger.debug('Received stanza:', stanza.name); this.logger.debug('Received stanza:', stanza.name);
try { try {
// Handle STARTTLS
if (stanza.name === 'starttls') {
this.handleStartTLS(stanza);
return;
}
// Handle authentication stanzas // Handle authentication stanzas
if (stanza.name === 'auth') { if (stanza.name === 'auth') {
this.handleAuth(stanza); this.handleAuth(stanza);
@@ -285,6 +293,76 @@ class XMPPStream extends EventEmitter {
} }
} }
handleStartTLS(stanza) {
if (this.secure) {
this.logger.warn('STARTTLS received on secure connection');
return;
}
this.logger.debug('STARTTLS negotiation initiated');
// Send proceed element
const proceed = new ltx.Element('proceed', {
xmlns: 'urn:ietf:params:xml:ns:xmpp-tls'
});
this.send(proceed);
// Get TLS options
const tlsOptions = this.getTLSOptions();
// Upgrade socket to TLS
const secureSocket = tls.connect({
socket: this.socket,
...tlsOptions,
rejectUnauthorized: false
}, () => {
this.logger.debug('TLS upgrade successful');
// Update socket and restart stream
this.socket = secureSocket;
this.secure = true;
// Setup socket handlers for new socket
this.setupSocket();
// Reset state for stream restart
this.setState('wait-for-stream');
this.streamId = this.generateStreamId();
});
secureSocket.on('error', (error) => {
this.logger.error('TLS upgrade error:', error);
this.close();
});
}
getTLSOptions() {
const tlsConfig = this.config.get('network.c2s.tls', {});
// Try to load certificates from config
let options = {
requestCert: false,
rejectUnauthorized: false
};
try {
const keyPath = tlsConfig.keyPath || '/home/ale/projects/xmpp/prosody-nodejs/certs/localhost-key.pem';
const certPath = tlsConfig.certPath || '/home/ale/projects/xmpp/prosody-nodejs/certs/localhost.pem';
if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
options.key = fs.readFileSync(keyPath);
options.cert = fs.readFileSync(certPath);
this.logger.debug('Using configured TLS certificates');
} else {
this.logger.warn('TLS certificates not found, using default options');
}
} catch (error) {
this.logger.warn('Error loading TLS certificates:', error);
}
return options;
}
handleAuth(stanza) { handleAuth(stanza) {
const mechanism = stanza.attrs.mechanism; const mechanism = stanza.attrs.mechanism;
this.logger.debug(`Authentication attempt with mechanism: ${mechanism}`); this.logger.debug(`Authentication attempt with mechanism: ${mechanism}`);