mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-09-20 15:26:03 +08:00
Fixed CA handling for SNI certificates
This commit is contained in:
parent
d8150b7d2b
commit
3f738389ba
8
api.js
8
api.js
|
@ -145,10 +145,7 @@ if (config.api.secure && certOptions.key) {
|
||||||
let httpsServerOptions = {};
|
let httpsServerOptions = {};
|
||||||
|
|
||||||
httpsServerOptions.key = certOptions.key;
|
httpsServerOptions.key = certOptions.key;
|
||||||
if (certOptions.ca) {
|
httpsServerOptions.cert = tools.buildCertChain(certOptions.cert, certOptions.ca);
|
||||||
httpsServerOptions.ca = certOptions.ca;
|
|
||||||
}
|
|
||||||
httpsServerOptions.cert = certOptions.cert;
|
|
||||||
|
|
||||||
let defaultSecureContext = tls.createSecureContext(httpsServerOptions);
|
let defaultSecureContext = tls.createSecureContext(httpsServerOptions);
|
||||||
|
|
||||||
|
@ -534,10 +531,7 @@ module.exports = done => {
|
||||||
namespace: 'mail'
|
namespace: 'mail'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config.acme && config.acme.agent && config.acme.agent.enabled) {
|
|
||||||
acmeRoutes(db, server, { disableRedirect: true });
|
acmeRoutes(db, server, { disableRedirect: true });
|
||||||
}
|
|
||||||
|
|
||||||
usersRoutes(db, server, userHandler, settingsHandler);
|
usersRoutes(db, server, userHandler, settingsHandler);
|
||||||
addressesRoutes(db, server, userHandler, settingsHandler);
|
addressesRoutes(db, server, userHandler, settingsHandler);
|
||||||
mailboxesRoutes(db, server, mailboxHandler);
|
mailboxesRoutes(db, server, mailboxHandler);
|
||||||
|
|
|
@ -54,7 +54,8 @@ const tlsDefaults = {
|
||||||
'-----END CERTIFICATE-----',
|
'-----END CERTIFICATE-----',
|
||||||
honorCipherOrder: true,
|
honorCipherOrder: true,
|
||||||
requestOCSP: false,
|
requestOCSP: false,
|
||||||
sessionIdContext: crypto.createHash('sha1').update(process.argv.join(' ')).digest('hex').slice(0, 32)
|
sessionIdContext: crypto.createHash('sha1').update(process.argv.join(' ')).digest('hex').slice(0, 32),
|
||||||
|
minVersion: 'TLSv1'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -295,8 +295,6 @@ class CertHandler {
|
||||||
certData.cert = cert;
|
certData.cert = cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
certData.ca = [].concat(ca || []);
|
|
||||||
|
|
||||||
if (primaryCert) {
|
if (primaryCert) {
|
||||||
try {
|
try {
|
||||||
const parsedCert = forge.pki.certificateFromPem(primaryCert);
|
const parsedCert = forge.pki.certificateFromPem(primaryCert);
|
||||||
|
@ -558,7 +556,11 @@ class CertHandler {
|
||||||
// key might be encrypted
|
// key might be encrypted
|
||||||
let privateKey = await decrypt(certData.privateKey, this.secret, this.cipher);
|
let privateKey = await decrypt(certData.privateKey, this.secret, this.cipher);
|
||||||
|
|
||||||
let serviceCtxOpts = { key: privateKey, cert: certData.cert, ca: certData.ca };
|
let serviceCtxOpts = {
|
||||||
|
key: privateKey,
|
||||||
|
cert: tools.buildCertChain(certData.cert, certData.ca)
|
||||||
|
};
|
||||||
|
|
||||||
for (let key of ['dhparam']) {
|
for (let key of ['dhparam']) {
|
||||||
if (serverOptions[key]) {
|
if (serverOptions[key]) {
|
||||||
serviceCtxOpts[key] = serverOptions[key];
|
serviceCtxOpts[key] = serverOptions[key];
|
||||||
|
|
15
lib/certs.js
15
lib/certs.js
|
@ -4,6 +4,7 @@ const config = require('wild-config');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const db = require('./db');
|
const db = require('./db');
|
||||||
const CertHandler = require('./cert-handler');
|
const CertHandler = require('./cert-handler');
|
||||||
|
const { buildCertChain } = require('./tools');
|
||||||
|
|
||||||
const certs = new Map();
|
const certs = new Map();
|
||||||
const servers = [];
|
const servers = [];
|
||||||
|
@ -92,12 +93,7 @@ module.exports.loadTLSOptions = (serverOptions, name) => {
|
||||||
|
|
||||||
if (serverCerts) {
|
if (serverCerts) {
|
||||||
serverOptions.key = serverCerts.key;
|
serverOptions.key = serverCerts.key;
|
||||||
|
serverOptions.cert = buildCertChain(serverCerts.cert, serverCerts.ca);
|
||||||
if (serverCerts.ca) {
|
|
||||||
serverOptions.ca = serverCerts.ca;
|
|
||||||
}
|
|
||||||
|
|
||||||
serverOptions.cert = serverCerts.cert;
|
|
||||||
|
|
||||||
if (serverCerts.dhparam) {
|
if (serverCerts.dhparam) {
|
||||||
serverOptions.dhparam = serverCerts.dhparam;
|
serverOptions.dhparam = serverCerts.dhparam;
|
||||||
|
@ -130,13 +126,12 @@ config.on('reload', () => {
|
||||||
let certOptions = {};
|
let certOptions = {};
|
||||||
if (serverCerts) {
|
if (serverCerts) {
|
||||||
certOptions.key = serverCerts.key;
|
certOptions.key = serverCerts.key;
|
||||||
if (serverCerts.ca) {
|
certOptions.cert = buildCertChain(serverCerts.cert, serverCerts.ca);
|
||||||
certOptions.ca = serverCerts.ca;
|
|
||||||
}
|
|
||||||
certOptions.cert = serverCerts.cert;
|
|
||||||
if (serverCerts.dhparam) {
|
if (serverCerts.dhparam) {
|
||||||
certOptions.dhparam = serverCerts.dhparam;
|
certOptions.dhparam = serverCerts.dhparam;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.server.updateSecureContext(certOptions);
|
entry.server.updateSecureContext(certOptions);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
21
lib/tools.js
21
lib/tools.js
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint no-control-regex: 0 */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
@ -586,6 +587,24 @@ function roundTime(seconds) {
|
||||||
return `${seconds} ${seconds === 1 ? 'second' : 'seconds'}`;
|
return `${seconds} ${seconds === 1 ? 'second' : 'seconds'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parsePemBundle(bundle) {
|
||||||
|
bundle = (bundle || '').toString().split(/\r?\n/).join('\x00');
|
||||||
|
let matches = bundle.match(/[-]{3,}BEGIN [^-]+[-]{3,}.*?[-]{3,}END [^-]+[-]{3,}/g);
|
||||||
|
if (matches) {
|
||||||
|
matches = Array.from(matches).map(cert => cert.replace(/\x00/g, '\n') + '\n');
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCertChain(cert, ca) {
|
||||||
|
return [cert]
|
||||||
|
.concat(ca || [])
|
||||||
|
.flatMap(ca => ca)
|
||||||
|
.map(ca => ca.trim() + '\n')
|
||||||
|
.filter(ca => ca.trim())
|
||||||
|
.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
normalizeAddress,
|
normalizeAddress,
|
||||||
normalizeDomain,
|
normalizeDomain,
|
||||||
|
@ -609,6 +628,8 @@ module.exports = {
|
||||||
formatFingerprint,
|
formatFingerprint,
|
||||||
getEnabled2fa,
|
getEnabled2fa,
|
||||||
roundTime,
|
roundTime,
|
||||||
|
parsePemBundle,
|
||||||
|
buildCertChain,
|
||||||
|
|
||||||
formatMetaData: metaData => {
|
formatMetaData: metaData => {
|
||||||
if (typeof metaData === 'string') {
|
if (typeof metaData === 'string') {
|
||||||
|
|
Loading…
Reference in a new issue