mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-12-26 09:50:47 +08:00
Fixed CA handling for SNI certificates
This commit is contained in:
parent
d8150b7d2b
commit
3f738389ba
5 changed files with 35 additions and 22 deletions
10
api.js
10
api.js
|
@ -145,10 +145,7 @@ if (config.api.secure && certOptions.key) {
|
|||
let httpsServerOptions = {};
|
||||
|
||||
httpsServerOptions.key = certOptions.key;
|
||||
if (certOptions.ca) {
|
||||
httpsServerOptions.ca = certOptions.ca;
|
||||
}
|
||||
httpsServerOptions.cert = certOptions.cert;
|
||||
httpsServerOptions.cert = tools.buildCertChain(certOptions.cert, certOptions.ca);
|
||||
|
||||
let defaultSecureContext = tls.createSecureContext(httpsServerOptions);
|
||||
|
||||
|
@ -534,10 +531,7 @@ module.exports = done => {
|
|||
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);
|
||||
addressesRoutes(db, server, userHandler, settingsHandler);
|
||||
mailboxesRoutes(db, server, mailboxHandler);
|
||||
|
|
|
@ -54,7 +54,8 @@ const tlsDefaults = {
|
|||
'-----END CERTIFICATE-----',
|
||||
honorCipherOrder: true,
|
||||
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.ca = [].concat(ca || []);
|
||||
|
||||
if (primaryCert) {
|
||||
try {
|
||||
const parsedCert = forge.pki.certificateFromPem(primaryCert);
|
||||
|
@ -558,7 +556,11 @@ class CertHandler {
|
|||
// key might be encrypted
|
||||
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']) {
|
||||
if (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 db = require('./db');
|
||||
const CertHandler = require('./cert-handler');
|
||||
const { buildCertChain } = require('./tools');
|
||||
|
||||
const certs = new Map();
|
||||
const servers = [];
|
||||
|
@ -92,12 +93,7 @@ module.exports.loadTLSOptions = (serverOptions, name) => {
|
|||
|
||||
if (serverCerts) {
|
||||
serverOptions.key = serverCerts.key;
|
||||
|
||||
if (serverCerts.ca) {
|
||||
serverOptions.ca = serverCerts.ca;
|
||||
}
|
||||
|
||||
serverOptions.cert = serverCerts.cert;
|
||||
serverOptions.cert = buildCertChain(serverCerts.cert, serverCerts.ca);
|
||||
|
||||
if (serverCerts.dhparam) {
|
||||
serverOptions.dhparam = serverCerts.dhparam;
|
||||
|
@ -130,13 +126,12 @@ config.on('reload', () => {
|
|||
let certOptions = {};
|
||||
if (serverCerts) {
|
||||
certOptions.key = serverCerts.key;
|
||||
if (serverCerts.ca) {
|
||||
certOptions.ca = serverCerts.ca;
|
||||
}
|
||||
certOptions.cert = serverCerts.cert;
|
||||
certOptions.cert = buildCertChain(serverCerts.cert, serverCerts.ca);
|
||||
|
||||
if (serverCerts.dhparam) {
|
||||
certOptions.dhparam = serverCerts.dhparam;
|
||||
}
|
||||
|
||||
entry.server.updateSecureContext(certOptions);
|
||||
}
|
||||
});
|
||||
|
|
21
lib/tools.js
21
lib/tools.js
|
@ -1,3 +1,4 @@
|
|||
/* eslint no-control-regex: 0 */
|
||||
'use strict';
|
||||
|
||||
const os = require('os');
|
||||
|
@ -586,6 +587,24 @@ function roundTime(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 = {
|
||||
normalizeAddress,
|
||||
normalizeDomain,
|
||||
|
@ -609,6 +628,8 @@ module.exports = {
|
|||
formatFingerprint,
|
||||
getEnabled2fa,
|
||||
roundTime,
|
||||
parsePemBundle,
|
||||
buildCertChain,
|
||||
|
||||
formatMetaData: metaData => {
|
||||
if (typeof metaData === 'string') {
|
||||
|
|
Loading…
Reference in a new issue