in src/js/state.js [9:157]
export default async function () {
async function fetch_guideline(guideln) {
// check for numerical version string, e.g. digit.digit
if (isNaN(guideln) || isNaN(parseFloat(guideln))) {
return guideln_latest; // invalid numerical version string
}
const url = "https://ssl-config.mozilla.org/guidelines/"+guideln+".json";
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`error retrieving ${guideln}.json: ${response.status}`);
}
guidelines[guideln] = await response.json();
return guideln;
} catch (error) {
console.error(error.message);
return guideln_latest;
}
}
const form = document.getElementById('form-generator').elements;
const config = form['config'].value;
const server = form['server'].value;
let guideln = form['guideline'].value !== ''
? form['guideline'].value
: guideln_latest;
let sstls = guidelines[guideln];
if (!sstls) {
guideln = await fetch_guideline(guideln);
if (guideln === '5.0') {
if (await fetch_guideline('5.1') === '5.1') {
// re-map keys from older guideline 5.0
for (let x of ['modern', 'intermediate', 'old']) {
let ss5 = guidelines['5.0'].configurations[x]; // server side tls config for that level
ss5.ciphersuites = ss5.openssl_ciphersuites;
ss5.ciphers = { // copy iana from 5.1 guideline
iana: guidelines['5.1'].configurations[x].ciphers.iana,
openssl: ss5.openssl_ciphers
};
}
}
else {
guideln = guideln_latest;
}
}
// note: sstls.version for '5.0' is rendered as number 5, not string '5.0'
sstls = guidelines[guideln];
}
const ssc = sstls.configurations[form['config'].value]; // server side tls config for that level
const supportsOcspStapling =
configs[server].supportsOcspStapling
&& minver(configs[server].supportsOcspStapling, form['version'].value);
const url = new URL(document.location);
// generate the fragment
let fragment = `server=${server}&version=${form['version'].value}&config=${config}`;
fragment += configs[server].usesOpenssl !== false ? `&openssl=${form['openssl'].value}` : '';
fragment += configs[server].supportsHsts !== false && !form['hsts'].checked ? `&hsts=false` : '';
fragment += supportsOcspStapling && !form['ocsp'].checked ? `&ocsp=false` : '';
fragment += `&guideline=${guideln}`;
// generate the version tags
let version_tags = `${configs[server].name} ${form['version'].value}`;
if (configs[server].eolBefore
&& !minver(configs[server].eolBefore, form['version'].value)) {
version_tags += ' (UNSUPPORTED; end-of-life)';
}
if (configs[server].usesOpenssl !== false) {
version_tags += `, OpenSSL ${form['openssl'].value}`;
if (!minver(configs['openssl'].eolBefore, form['openssl'].value)) {
version_tags += ' (UNSUPPORTED; end-of-life)';
}
}
version_tags += `, ${form['config'].value} config`;
// html-escape version_tags (even though version_tags is also used
// outside HTML contexts, HTML is not expected in version strings)
version_tags = xmlEntities(version_tags);
// generate the header
const date = new Date().toISOString().substr(0, 10);
let header = `generated ${date}, Mozilla Guideline v${guideln}, ${version_tags}`;
header += configs[server].supportsHsts !== false && !form['hsts'].checked ? `, no HSTS` : '';
header += supportsOcspStapling && !form['ocsp'].checked ? `, no OCSP` : '';
const link = `${url.origin}${url.pathname}#${fragment}`;
// we need to remove TLS 1.3 from the supported protocols if the software is too old
let protocols = ssc.tls_versions;
if (!configs[server].tls13
|| !minver(configs[server].tls13, form['version'].value)
|| !minver(configs['openssl'].tls13, form['openssl'].value)) {
protocols = protocols.filter(ciphers => ciphers !== 'TLSv1.3');
}
let ciphers = configs[server].cipherFormat ? ssc.ciphers[configs[server].cipherFormat] : ssc.ciphers.openssl;
if (configs[server].supportedCiphers) {
ciphers = ciphers.filter(suite => configs[server].supportedCiphers.indexOf(suite) !== -1);
} else {
ciphers = ciphers;
}
if (ciphers.length && ciphers[0] === '@SECLEVEL=0') ciphers.shift();
if (configs[server].usesOpenssl !== false && minver('3.0.0', form['openssl'].value)) {
// set SECLEVEL=0 via cipher string to support TLSv1-1.1 "old" with OpenSSL 3.x
if (protocols.includes('TLSv1.1')) ciphers.unshift('@SECLEVEL=0');
}
const state = {
form: {
config: form['config'].value,
hsts: form['hsts'].checked && configs[server].supportsHsts !== false,
ocsp: form['ocsp'].checked && supportsOcspStapling,
opensslVersion: form['openssl'].value,
server,
serverName: configs[server].name,
serverVersion: form['version'].value,
version_tags,
},
output: {
ciphers,
cipherSuites: ssc.ciphersuites,
date,
dhCommand: ssc.dh_param_size >= 2048 ? `curl ${url.origin}/ffdhe${ssc.dh_param_size}.txt` : `openssl dhparam ${ssc.dh_param_size}`,
dhParamSize: ssc.dh_param_size,
fragment,
hasVersions: configs[server].hasVersions !== false,
header,
hstsMaxAge: ssc.hsts_min_age,
hstsRedirectCode: 301,
latestVersion: configs[server].latestVersion,
link,
oldestClients: ssc.oldest_clients,
origin: url.origin,
protocols: protocols,
serverPreferredOrder: ssc.server_preferred_order,
showSupports: configs[server].showSupports !== false,
supportsHsts: configs[server].supportsHsts !== false,
supportsOcspStapling: supportsOcspStapling,
tlsCurves: ssc.tls_curves,
usesDhe: ciphers.join(":").includes(":DHE") || ciphers.join(":").includes("_DHE_"),
usesOpenssl: configs[server].usesOpenssl !== false,
},
};
return state;
};