diff --git a/CHANGES b/CHANGES index bc3c4fe019..692116d936 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,11 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_ssl: adding ssl_policies.h[.in] for policy cipher/protocol definitions. Use + update_policies.py to update manually from Mozilla JSON definitions at + https://statics.tls.security.mozilla.org/server-side-tls-conf.json + [Stefan Eissing] + *) mod_md: v0.9.5: - New directive (srly: what do you expect at this point?) "MDMustStaple on|off" to control if new certificates are requested with the OCSP Must Staple extension. diff --git a/modules/ssl/mod_ssl.dsp b/modules/ssl/mod_ssl.dsp index 72af2936ce..f7c9c2e070 100644 --- a/modules/ssl/mod_ssl.dsp +++ b/modules/ssl/mod_ssl.dsp @@ -180,6 +180,10 @@ SOURCE=.\ssl_private.h # End Source File # Begin Source File +SOURCE=.\ssl_policies.h +# End Source File +# Begin Source File + SOURCE=.\ssl_util_ssl.h # End Source File # Begin Source File diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index 48e09a630d..56dbc77ed4 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -30,6 +30,7 @@ #include #include "ssl_private.h" +#include "ssl_policies.h" #include "util_mutex.h" #include "ap_provider.h" @@ -521,70 +522,6 @@ void ssl_config_proxy_merge(apr_pool_t *p, ** _________________________________________________________________ */ -#define SSL_MOD_POLICIES_KEY "ssl_module_policies" - -#ifndef OPENSSL_NO_SSL3 -#define STUPID_PROTOCOL_CONSTANTS_SSLV3 SSL_PROTOCOL_SSLV3 -#else -#define STUPID_PROTOCOL_CONSTANTS_SSLV3 0 -#endif - -/** - * Define a core set of policies that are always there: - * - 'modern' from https://wiki.mozilla.org/Security/Server_Side_TLS - * - 'intermediate' from https://wiki.mozilla.org/Security/Server_Side_TLS - * - 'old' from https://wiki.mozilla.org/Security/Server_Side_TLS - */ -#ifdef HAVE_TLSV1_X - /* Only with OpenSSL > v1.0.2 do we have a chance to implement modern */ -#define SSL_POLICY_LEGACY_PROTOCOLS \ - (STUPID_PROTOCOL_CONSTANTS_SSLV3|SSL_PROTOCOL_TLSV1|SSL_PROTOCOL_TLSV1_1) - -#define SSL_POLICY_MODERN_PROTOCOLS \ - (SSL_PROTOCOL_ALL & ~SSL_POLICY_LEGACY_PROTOCOLS) -#define SSL_POLICY_MODERN_CIPHERS \ - "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:" \ - "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:" \ - "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:" \ - "ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:" \ - "ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256" -#endif - -#define SSL_POLICY_INTERMEDIATE_PROTOCOLS \ - (SSL_PROTOCOL_ALL & ~STUPID_PROTOCOL_CONSTANTS_SSLV3) - -#define SSL_POLICY_INTERMEDIATE_CIPHERS \ - "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:" \ - "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:" \ - "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:" \ - "DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:" \ - "ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:" \ - "ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:" \ - "ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:" \ - "DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:" \ - "ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:" \ - "AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:" \ - "AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS" - -#define SSL_POLICY_OLD_PROTOCOLS (SSL_PROTOCOL_ALL) -#define SSL_POLICY_OLD_CIPHERS \ - "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:" \ - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:" \ - "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:" \ - "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:" \ - "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:" \ - "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:" \ - "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:" \ - "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:" \ - "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:" \ - "ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:" \ - "AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:" \ - "DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:" \ - "!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP" - -#define SSL_POLICY_PROXY_VERIFY_MODE SSL_CVERIFY_REQUIRE -#define SSL_POLICY_PROXY_VERIFY_DEPTH -1 - static void add_policy(apr_hash_t *policies, apr_pool_t *p, const char *name, int protocols, const char *ciphers, int honor_order, int compression, int session_tickets, @@ -632,22 +569,36 @@ static apr_hash_t *get_policies(apr_pool_t *p, int create) if (create) { policies = apr_hash_make(p); - /* We could also invoke the commands here and let them parse strings. */ -#ifdef HAVE_TLSV1_X +#if SSL_POLICY_MODERN add_policy(policies, p, "modern", - SSL_POLICY_MODERN_PROTOCOLS, SSL_POLICY_MODERN_CIPHERS, - 1, 0, 0, - SSL_POLICY_PROXY_VERIFY_MODE, SSL_POLICY_PROXY_VERIFY_DEPTH); + SSL_POLICY_MODERN_PROTOCOLS, + SSL_POLICY_MODERN_CIPHERS, + SSL_POLICY_HONOR_ORDER, + SSL_POLICY_COMPRESSION, + SSL_POLICY_SESSION_TICKETS, + SSL_POLICY_PROXY_VERIFY_MODE, + SSL_POLICY_PROXY_VERIFY_DEPTH); #endif +#if SSL_POLICY_INTERMEDIATE add_policy(policies, p, "intermediate", - SSL_POLICY_INTERMEDIATE_PROTOCOLS, SSL_POLICY_INTERMEDIATE_CIPHERS, - 1, 0, 0, - SSL_POLICY_PROXY_VERIFY_MODE, SSL_POLICY_PROXY_VERIFY_DEPTH); - + SSL_POLICY_INTERMEDIATE_PROTOCOLS, + SSL_POLICY_INTERMEDIATE_CIPHERS, + SSL_POLICY_HONOR_ORDER, + SSL_POLICY_COMPRESSION, + SSL_POLICY_SESSION_TICKETS, + SSL_POLICY_PROXY_VERIFY_MODE, + SSL_POLICY_PROXY_VERIFY_DEPTH); +#endif +#if SSL_POLICY_OLD add_policy(policies, p, "old", - SSL_POLICY_OLD_PROTOCOLS, SSL_POLICY_OLD_CIPHERS, - 1, 0, 0, - SSL_CVERIFY_NONE, -1); + SSL_POLICY_OLD_PROTOCOLS, + SSL_POLICY_OLD_CIPHERS, + SSL_POLICY_HONOR_ORDER, + SSL_POLICY_COMPRESSION, + SSL_POLICY_SESSION_TICKETS, + SSL_CVERIFY_NONE, + SSL_POLICY_PROXY_VERIFY_DEPTH); +#endif apr_pool_userdata_set(policies, SSL_MOD_POLICIES_KEY, apr_pool_cleanup_null, p); diff --git a/modules/ssl/ssl_policies.h b/modules/ssl/ssl_policies.h new file mode 100644 index 0000000000..474f799668 --- /dev/null +++ b/modules/ssl/ssl_policies.h @@ -0,0 +1,87 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @verbatim + _ _ + _ __ ___ ___ __| | ___ ___| | mod_ssl + | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL + | | | | | | (_) | (_| | \__ \__ \ | + |_| |_| |_|\___/ \__,_|___|___/___/_| + |_____| + @endverbatim + * @file ssl_policies.h + * @brief Additional Utility Functions for OpenSSL + * + * @defgroup MOD_SSL_UTIL Utilities + * @ingroup MOD_SSL + * @{ + */ + +#ifndef __SSL_POLICIES_H__ +#define __SSL_POLICIES_H__ + +#define SSL_MOD_POLICIES_KEY "ssl_module_policies" + +#ifndef OPENSSL_NO_SSL3 +#define SSL_PROTOCOL_CONSTANTS_SSLV3 SSL_PROTOCOL_SSLV3 +#else +#define SSL_PROTOCOL_CONSTANTS_SSLV3 0 +#endif + +#ifdef HAVE_TLSV1_X +#define SSL_POLICY_LEGACY_PROTOCOLS \ + (SSL_PROTOCOL_CONSTANTS_SSLV3|SSL_PROTOCOL_TLSV1|SSL_PROTOCOL_TLSV1_1) +#endif + +/* Settings for all policies */ +#define SSL_POLICY_HONOR_ORDER 1 +#define SSL_POLICY_COMPRESSION 0 +#define SSL_POLICY_SESSION_TICKETS 0 +#define SSL_POLICY_PROXY_VERIFY_MODE SSL_CVERIFY_REQUIRE +#define SSL_POLICY_PROXY_VERIFY_DEPTH -1 + +/** + * Define a core set of policies that are always there: + * - 'modern' from https://wiki.mozilla.org/Security/Server_Side_TLS + * - 'intermediate' from https://wiki.mozilla.org/Security/Server_Side_TLS + * - 'old' from https://wiki.mozilla.org/Security/Server_Side_TLS + * The JSON version can be retrieved here: + * https://statics.tls.security.mozilla.org/server-side-tls-conf.json + */ + +#define SSL_POLICY_MOZILLA_VERSION 4.0 + +#ifdef HAVE_TLS1_X +#define SSL_POLICY_MODERN 1 +#define SSL_POLICY_MODERN_CIPHERS "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256" +#define SSL_POLICY_MODERN_PROTOCOLS SSL_PROTOCOL_TLSV1_2 +#else /* ifdef HAVE_TLS1_X */ +#define SSL_POLICY_MODERN 0 +#endif /* ifdef HAVE_TLS1_X, else part */ + +#define SSL_POLICY_INTERMEDIATE 1 +#define SSL_POLICY_INTERMEDIATE_CIPHERS "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS" +#define SSL_POLICY_INTERMEDIATE_PROTOCOLS (SSL_PROTOCOL_ALL & ~(SSL_PROTOCOL_CONSTANTS_SSLV3)) + +#define SSL_POLICY_OLD 1 +#define SSL_POLICY_OLD_CIPHERS "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP" +#define SSL_POLICY_OLD_PROTOCOLS SSL_PROTOCOL_ALL + + +#endif /* __SSL_POLICIES_H__ */ +/** @} */ + diff --git a/modules/ssl/ssl_policies.h.in b/modules/ssl/ssl_policies.h.in new file mode 100644 index 0000000000..164053c8d1 --- /dev/null +++ b/modules/ssl/ssl_policies.h.in @@ -0,0 +1,70 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @verbatim + _ _ + _ __ ___ ___ __| | ___ ___| | mod_ssl + | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL + | | | | | | (_) | (_| | \__ \__ \ | + |_| |_| |_|\___/ \__,_|___|___/___/_| + |_____| + @endverbatim + * @file ssl_policies.h + * @brief Additional Utility Functions for OpenSSL + * + * @defgroup MOD_SSL_UTIL Utilities + * @ingroup MOD_SSL + * @{ + */ + +#ifndef __SSL_POLICIES_H__ +#define __SSL_POLICIES_H__ + +#define SSL_MOD_POLICIES_KEY "ssl_module_policies" + +#ifndef OPENSSL_NO_SSL3 +#define SSL_PROTOCOL_CONSTANTS_SSLV3 SSL_PROTOCOL_SSLV3 +#else +#define SSL_PROTOCOL_CONSTANTS_SSLV3 0 +#endif + +#ifdef HAVE_TLSV1_X +#define SSL_POLICY_LEGACY_PROTOCOLS \ + (SSL_PROTOCOL_CONSTANTS_SSLV3|SSL_PROTOCOL_TLSV1|SSL_PROTOCOL_TLSV1_1) +#endif + +/* Settings for all policies */ +#define SSL_POLICY_HONOR_ORDER 1 +#define SSL_POLICY_COMPRESSION 0 +#define SSL_POLICY_SESSION_TICKETS 0 +#define SSL_POLICY_PROXY_VERIFY_MODE SSL_CVERIFY_REQUIRE +#define SSL_POLICY_PROXY_VERIFY_DEPTH -1 + +/** + * Define a core set of policies that are always there: + * - 'modern' from https://wiki.mozilla.org/Security/Server_Side_TLS + * - 'intermediate' from https://wiki.mozilla.org/Security/Server_Side_TLS + * - 'old' from https://wiki.mozilla.org/Security/Server_Side_TLS + * The JSON version can be retrieved here: + * https://statics.tls.security.mozilla.org/server-side-tls-conf.json + */ + +@MOZILLA_SECURITY_POLICIES@ + +#endif /* __SSL_POLICIES_H__ */ +/** @} */ + diff --git a/modules/ssl/update_policies.py b/modules/ssl/update_policies.py new file mode 100644 index 0000000000..785c652065 --- /dev/null +++ b/modules/ssl/update_policies.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python + +import json +import os +import sys + +from httplib import HTTPSConnection + +# The location were Mozilla defines the *current* TLS Security in JSON format +# +MOZ_TLS_CONF_SERVER = "statics.tls.security.mozilla.org" +MOZ_TLS_CONF_PATH = "/server-side-tls-conf.json" +MOZ_TLS_CONF_URL = "https://%s%s" % (MOZ_TLS_CONF_SERVER, MOZ_TLS_CONF_PATH) + +# The version we already know. Accept nothing less. +# +MOZ_TLS_CONF_VERSION_MIN = 4.0 + +# keys inside the JSON document +# +KEY_CONF = 'configurations' +KEY_HREF = 'href' +KEY_OSSL_CIPHERS = 'openssl_ciphersuites' +KEY_TLS_VERSIONS = 'tls_versions' +KEY_VERSION = 'version' + +# TLS Versions we know how to handle +# +TLS_VERSIONS = { + 'TLSv1.2' : "SSL_PROTOCOL_TLSV1_2", + 'TLSv1.1' : "SSL_PROTOCOL_TLSV1_1", + 'TLSv1' : "SSL_PROTOCOL_TLSV1", + 'SSLv3' : "SSL_PROTOCOL_CONSTANTS_SSLV3", +} +TLS_1_X_VERSIONS = [ 'TLSv1.2' ] + +# the Security configurations to extract +POLICY_NAMES = [ 'modern', 'intermediate', 'old' ] + + +def fail(msg): + sys.stderr.write(msg) + sys.exit(1) + + +def proto_string(tls_version): + if tls_version in TLS_VERSIONS: + return TLS_VERSIONS[tls_version] + fail("Unknown TLS protocol '%s'" % tls_version) + + +def proto_conf(tls_versions): + if len(TLS_VERSIONS) < len(tls_versions): + fail("more TLS versions used than we know: %s" % tls_versions) + if len(tls_versions) == 1: + return proto_string(tls_versions[0]) + missing = [] + for tls in TLS_VERSIONS: + if not tls in tls_versions: + missing.append(proto_string(tls)) + if len(missing): + return "(SSL_PROTOCOL_ALL & ~(%s))" % "|".join(missing) + return "SSL_PROTOCOL_ALL" + + +# return an #ifdef required for a policy or None +# +def required_ifdef(conf): + for tlsv in conf[KEY_TLS_VERSIONS]: + # if it has a non-1_X protocol, it works without OpenSSL 1.0.2 + if not tlsv in TLS_1_X_VERSIONS: + return None + return "HAVE_TLS1_X" + + +def getPolicyDef(): + c = HTTPSConnection(MOZ_TLS_CONF_SERVER) + c.request('GET', MOZ_TLS_CONF_PATH) + data = c.getresponse().read() + c.close() + return data + + +def printPolicies(doc): + print "#define SSL_POLICY_MOZILLA_VERSION %s" % doc[KEY_VERSION] + print "" + for pname in POLICY_NAMES: + prefix = "SSL_POLICY_%s" % pname.upper() + if not pname in doc[KEY_CONF]: + vars[prefix] = 0 + continue + p = doc[KEY_CONF][pname] + + ifdef = required_ifdef(p) + if ifdef: + print "#ifdef %s" % ifdef + + print "#define %s 1" % prefix + print "#define %s_CIPHERS \"%s\"" % (prefix, p[KEY_OSSL_CIPHERS]) + print "#define %s_PROTOCOLS %s" % (prefix, proto_conf(p[KEY_TLS_VERSIONS])) + + if ifdef: + print "#else /* ifdef %s */" % ifdef + print "#define %s 0" % prefix + print "#endif /* ifdef %s, else part */" % ifdef + print "" + + +def main(argv): + data = getPolicyDef() + doc = json.loads(data) + + if MOZ_TLS_CONF_URL != doc[KEY_HREF]: + fail("ERROR: Unexpected href in policy document: %s\n" % doc[KEY_HREF]) + if doc[KEY_VERSION] < MOZ_TLS_CONF_VERSION_MIN: + fail("ERROR: Expected at least version %s, but policy document has %s\n" \ + % (MOZ_TLS_CONF_VERSION_MIN, doc[KEY_VERSION])) + + if 1 == len(argv): + printPolicies(doc) + elif 2 == len(argv): + with open(argv[1]) as f: + for line in f: + if line == "@MOZILLA_SECURITY_POLICIES@\n": + printPolicies(doc) + else: + sys.stdout.write(line) + else: + fail("usage: %s [file] \nDownload and print/replace the Mozilla TLS Security policies" % argv[0]) + + +if __name__ == "__main__": + main(sys.argv)