From d0bcc1305964ad8e756d85c9c50a007f0ffe0933 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Tue, 10 Jun 2014 08:08:17 -0700 Subject: [PATCH 01/10] Break ground on an postfix config wrangling engine --- mta-config-generator.py | 80 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 mta-config-generator.py diff --git a/mta-config-generator.py b/mta-config-generator.py new file mode 100644 index 000000000..0444c1e73 --- /dev/null +++ b/mta-config-generator.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python + +import string + +DEFAULT_POLICY_FILE = "texthash:/etc/postfix/starttls_everywhere_policy" + +def parse_line(self, line): + "return the and right hand sides of stripped, non-comment postfix config line" + # lines are like: + # smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache + left, sep, right = line.partition("=") + if not sep: + return None + return (left.strip(), right.strip()) + +#def get_cf_values(lines, var): + +class MTAConfigGenerator: + def __init__(self, stlse_config): + self.c = stlse_config + +class ExistingConfigError(ValueError): pass + +class PostfixConfigGenerator(MTAConfigGenerator): + def __init__(self, stlse_config): + MTAConfigGenerator.__init__(self, stlse_config) + this.postfix_cf_file = this.find_postfix_cf() + this.wrangle_existing_config() + + def ensure_cf_var(self, var, ideal, also_acceptable): + """ + Ensure that existing postfix config @var is in the list of @acceptable + values; if not, set it to the ideal value. """ + + acceptable = [ideal] + also_acceptable + + l = [line for line in cf if line.startswith("stmpd_use_tls")] + if not any(l): + this.additions.append("smtpd_use_tls = yes") + else: + values = [right for left, right in map(parse_line, l)] + if len(set(values)) > 1: + raise ExistingConfigError, "Conflicting existing config values " + `l` + if values[0] != "yes": + + def wrangle_existing_config(self): + "Try to ensure/mutate that the config file is in a sane state." + this.additions = [] + fn = find_postfix_cf() + raw_cf = open(fn).readlines() + cf = map(string.strip, raw_cf) + this.cf = [line for line in cf if line and not line.startswith("#")] + + # Check we're currently accepting inbound STARTTLS sensibly + this.ensure_cf_var("smtpd_use_tls", "yes", []) + # Ideally we use it opportunistically in the outbound direction + this.ensure_cf_var("smtp_tls_security_level", "may", ["encrypt"]) + # Maximum verbosity lets us collect failure information + this.ensure_cf_var("smtp_tls_loglevel", "1", []) + # Inject a reference to our per-domain policy map + this.ensure_cf_var("smtp_tls_policy_maps", DEFAULT_POLICY_FILE, []) + + this.maybe_add_config_lines() + + def maybe_add_config_lines(self): + if not this.additions: + return + this.additions[:0]=["","# New config lines added by STARTTLS Everywhere",""] + new_cf_lines = "\n".join(this.additions) + print "Adding to %s:" % fn + print new_cf_lines + if raw_cf[-1][-1] == "\n": sep = "" + else: sep = "\n" + new_cf = "".join(raw_cf) + sep + new_cf_lines + f = open(fn, "w").write(new_cf) + f.close() + + def find_postfix_cf(self): + "Search far and wide for the correct postfix configuration file" + return "/etc/postfix/main.cf" From a03db04ff44335e1911e4a79787cdff025bb711f Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Tue, 10 Jun 2014 08:08:40 -0700 Subject: [PATCH 02/10] WIP implementing deletion of existing cf lines --- mta-config-generator.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/mta-config-generator.py b/mta-config-generator.py index 0444c1e73..5d79423ef 100644 --- a/mta-config-generator.py +++ b/mta-config-generator.py @@ -4,10 +4,11 @@ import string DEFAULT_POLICY_FILE = "texthash:/etc/postfix/starttls_everywhere_policy" -def parse_line(self, line): +def parse_line(self, line_data): "return the and right hand sides of stripped, non-comment postfix config line" # lines are like: # smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache + num,line = line_data left, sep, right = line.partition("=") if not sep: return None @@ -34,22 +35,28 @@ class PostfixConfigGenerator(MTAConfigGenerator): acceptable = [ideal] + also_acceptable - l = [line for line in cf if line.startswith("stmpd_use_tls")] + l = [num,line for num,line in enumerate(cf) if line.startswith(var)] if not any(l): this.additions.append("smtpd_use_tls = yes") else: values = [right for left, right in map(parse_line, l)] if len(set(values)) > 1: + if this.fixup: + this.deletions.append( raise ExistingConfigError, "Conflicting existing config values " + `l` if values[0] != "yes": - def wrangle_existing_config(self): - "Try to ensure/mutate that the config file is in a sane state." + def wrangle_existing_config(self, fixup=false): + """ + Try to ensure/mutate that the config file is in a sane state. + Fixup means we'll delete existing lines if necessary to get there. + """ this.additions = [] fn = find_postfix_cf() raw_cf = open(fn).readlines() - cf = map(string.strip, raw_cf) - this.cf = [line for line in cf if line and not line.startswith("#")] + this.cf = map(string.strip, raw_cf) + #this.cf = [line for line in cf if line and not line.startswith("#")] + this.fixup = fixup # Check we're currently accepting inbound STARTTLS sensibly this.ensure_cf_var("smtpd_use_tls", "yes", []) From 46ce09d36d0b15113fd0ea1f61b4db842fb8e948 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 11 Jun 2014 05:01:46 -0700 Subject: [PATCH 03/10] MTA config wrangling seems to work --- mta-config-generator.py | 91 ++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 33 deletions(-) mode change 100644 => 100755 mta-config-generator.py diff --git a/mta-config-generator.py b/mta-config-generator.py old mode 100644 new mode 100755 index 5d79423ef..1346d37dd --- a/mta-config-generator.py +++ b/mta-config-generator.py @@ -4,7 +4,7 @@ import string DEFAULT_POLICY_FILE = "texthash:/etc/postfix/starttls_everywhere_policy" -def parse_line(self, line_data): +def parse_line(line_data): "return the and right hand sides of stripped, non-comment postfix config line" # lines are like: # smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache @@ -12,7 +12,7 @@ def parse_line(self, line_data): left, sep, right = line.partition("=") if not sep: return None - return (left.strip(), right.strip()) + return (num, left.strip(), right.strip()) #def get_cf_values(lines, var): @@ -23,10 +23,11 @@ class MTAConfigGenerator: class ExistingConfigError(ValueError): pass class PostfixConfigGenerator(MTAConfigGenerator): - def __init__(self, stlse_config): + def __init__(self, stlse_config, fixup=False): + self.fixup = fixup MTAConfigGenerator.__init__(self, stlse_config) - this.postfix_cf_file = this.find_postfix_cf() - this.wrangle_existing_config() + self.postfix_cf_file = self.find_postfix_cf() + self.wrangle_existing_config() def ensure_cf_var(self, var, ideal, also_acceptable): """ @@ -35,53 +36,77 @@ class PostfixConfigGenerator(MTAConfigGenerator): acceptable = [ideal] + also_acceptable - l = [num,line for num,line in enumerate(cf) if line.startswith(var)] + l = [(num,line) for num,line in enumerate(self.cf) if line.startswith(var)] if not any(l): - this.additions.append("smtpd_use_tls = yes") + self.additions.append(var + " = " + ideal) else: - values = [right for left, right in map(parse_line, l)] + values = map(parse_line, l) if len(set(values)) > 1: - if this.fixup: - this.deletions.append( - raise ExistingConfigError, "Conflicting existing config values " + `l` - if values[0] != "yes": + if self.fixup: + #print "Scheduling deletions:" + `values` + conflicting_lines = [num for num,_var,val in values] + self.deletions.extend(conflicting_lines) + self.additions.append(var + " = " + ideal) + else: + raise ExistingConfigError, "Conflicting existing config values " + `l` + val = values[0][2] + if val not in acceptable: + #print "Scheduling deletions:" + `values` + if self.fixup: + self.deletions.append(values[0][0]) + self.additions.append(var + " = " + ideal) + else: + raise ExistingConfigError, "Existing config has %s=%s"%(var,val) - def wrangle_existing_config(self, fixup=false): + def wrangle_existing_config(self): """ Try to ensure/mutate that the config file is in a sane state. Fixup means we'll delete existing lines if necessary to get there. """ - this.additions = [] - fn = find_postfix_cf() - raw_cf = open(fn).readlines() - this.cf = map(string.strip, raw_cf) - #this.cf = [line for line in cf if line and not line.startswith("#")] - this.fixup = fixup + self.additions = [] + self.deletions = [] + self.fn = self.find_postfix_cf() + self.raw_cf = open(self.fn).readlines() + self.cf = map(string.strip, self.raw_cf) + #self.cf = [line for line in cf if line and not line.startswith("#")] # Check we're currently accepting inbound STARTTLS sensibly - this.ensure_cf_var("smtpd_use_tls", "yes", []) + self.ensure_cf_var("smtpd_use_tls", "yes", []) # Ideally we use it opportunistically in the outbound direction - this.ensure_cf_var("smtp_tls_security_level", "may", ["encrypt"]) + self.ensure_cf_var("smtp_tls_security_level", "may", ["encrypt"]) # Maximum verbosity lets us collect failure information - this.ensure_cf_var("smtp_tls_loglevel", "1", []) + self.ensure_cf_var("smtp_tls_loglevel", "1", []) # Inject a reference to our per-domain policy map - this.ensure_cf_var("smtp_tls_policy_maps", DEFAULT_POLICY_FILE, []) + self.ensure_cf_var("smtp_tls_policy_maps", DEFAULT_POLICY_FILE, []) - this.maybe_add_config_lines() + self.maybe_add_config_lines() def maybe_add_config_lines(self): - if not this.additions: + if not self.additions: return - this.additions[:0]=["","# New config lines added by STARTTLS Everywhere",""] - new_cf_lines = "\n".join(this.additions) - print "Adding to %s:" % fn + if self.fixup: + print "Deleting lines:", self.deletions + self.additions[:0]=["#","# New config lines added by STARTTLS Everywhere","#"] + new_cf_lines = "\n".join(self.additions) + print "Adding to %s:" % self.fn print new_cf_lines - if raw_cf[-1][-1] == "\n": sep = "" - else: sep = "\n" - new_cf = "".join(raw_cf) + sep + new_cf_lines - f = open(fn, "w").write(new_cf) - f.close() + if self.raw_cf[-1][-1] == "\n": sep = "" + else: sep = "\n" + + self.new_cf = "" + for num, line in enumerate(self.raw_cf): + if self.fixup and num in self.deletions: + self.new_cf += "# Line removed by STARTTLS Everywhere\n# " + line + else: + self.new_cf += line + self.new_cf += sep + new_cf_lines + + print self.new_cf + f = open(self.fn, "w").write(self.new_cf) def find_postfix_cf(self): "Search far and wide for the correct postfix configuration file" return "/etc/postfix/main.cf" + +if __name__ == "__main__": + pcgen = PostfixConfigGenerator(None, fixup=True) From 6e1bcfdb2a7ebe34511c5bc92265ceebe373b47f Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 11 Jun 2014 09:17:50 -0700 Subject: [PATCH 04/10] WIP implementing domain-wise TLS policies --- mta-config-generator.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/mta-config-generator.py b/mta-config-generator.py index 1346d37dd..1b98e7e96 100755 --- a/mta-config-generator.py +++ b/mta-config-generator.py @@ -2,7 +2,9 @@ import string -DEFAULT_POLICY_FILE = "texthash:/etc/postfix/starttls_everywhere_policy" + +DEFAULT_POLICY_FILE = "/etc/postfix/starttls_everywhere_policy" +POLICY_CF_ENTRY="texthash:" + DEFAULT_POLICY_FILE def parse_line(line_data): "return the and right hand sides of stripped, non-comment postfix config line" @@ -17,17 +19,18 @@ def parse_line(line_data): #def get_cf_values(lines, var): class MTAConfigGenerator: - def __init__(self, stlse_config): - self.c = stlse_config + def __init__(self, policy_config): + self.policy_config = policy_config class ExistingConfigError(ValueError): pass class PostfixConfigGenerator(MTAConfigGenerator): - def __init__(self, stlse_config, fixup=False): + def __init__(self, policy_config, fixup=False): self.fixup = fixup - MTAConfigGenerator.__init__(self, stlse_config) + MTAConfigGenerator.__init__(self, policy_config) self.postfix_cf_file = self.find_postfix_cf() self.wrangle_existing_config() + self.set_domainwise_tls_policies() def ensure_cf_var(self, var, ideal, also_acceptable): """ @@ -77,7 +80,7 @@ class PostfixConfigGenerator(MTAConfigGenerator): # Maximum verbosity lets us collect failure information self.ensure_cf_var("smtp_tls_loglevel", "1", []) # Inject a reference to our per-domain policy map - self.ensure_cf_var("smtp_tls_policy_maps", DEFAULT_POLICY_FILE, []) + self.ensure_cf_var("smtp_tls_policy_maps", POLICY_CF_ENTRY, []) self.maybe_add_config_lines() @@ -87,7 +90,7 @@ class PostfixConfigGenerator(MTAConfigGenerator): if self.fixup: print "Deleting lines:", self.deletions self.additions[:0]=["#","# New config lines added by STARTTLS Everywhere","#"] - new_cf_lines = "\n".join(self.additions) + new_cf_lines = "\n".join(self.additions) + "\n" print "Adding to %s:" % self.fn print new_cf_lines if self.raw_cf[-1][-1] == "\n": sep = "" @@ -108,5 +111,18 @@ class PostfixConfigGenerator(MTAConfigGenerator): "Search far and wide for the correct postfix configuration file" return "/etc/postfix/main.cf" + def set_domainwise_tls_policies(self): + self.policy_lines = [] + for domain, policy in self.policy_config.tls_policies: + entry = domain + " encrypt " + if "min-tls-version" in policy: + entry += " " + policy["min-tls-version"] + self.policy_lines.append(entry) + + f = open(DEFAULT_POLICY_FILE, "w") + f.write("\n".join(self.policy_lines)) + if __name__ == "__main__": - pcgen = PostfixConfigGenerator(None, fixup=True) + import config-parser + c = config-parser.Config() + pcgen = PostfixConfigGenerator(c, fixup=True) From eea1b0d8c5cf5367dcb91099ac7331443ad8a631 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 11 Jun 2014 09:18:56 -0700 Subject: [PATCH 05/10] Switch naming conventions so that modules are importable :) It turns out that python won't import modules with hyphens in their names. It seems that CamelCase is most consistent with our Class naming. However feel free to do something different instead :) --- check-starttls.py => CheckSTARTTLS.py | 0 config-parser.py => ConfigParser.py | 0 mta-config-generator.py => MTAConfigGenerator.py | 0 ...-google-starttls-domains.py => ProcessGoogleSTARTTLSDomains.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename check-starttls.py => CheckSTARTTLS.py (100%) rename config-parser.py => ConfigParser.py (100%) rename mta-config-generator.py => MTAConfigGenerator.py (100%) rename process-google-starttls-domains.py => ProcessGoogleSTARTTLSDomains.py (100%) diff --git a/check-starttls.py b/CheckSTARTTLS.py similarity index 100% rename from check-starttls.py rename to CheckSTARTTLS.py diff --git a/config-parser.py b/ConfigParser.py similarity index 100% rename from config-parser.py rename to ConfigParser.py diff --git a/mta-config-generator.py b/MTAConfigGenerator.py similarity index 100% rename from mta-config-generator.py rename to MTAConfigGenerator.py diff --git a/process-google-starttls-domains.py b/ProcessGoogleSTARTTLSDomains.py similarity index 100% rename from process-google-starttls-domains.py rename to ProcessGoogleSTARTTLSDomains.py From 2540f1f1e8f924d50b629a682986d5973715a968 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 11 Jun 2014 09:31:41 -0700 Subject: [PATCH 06/10] Writing to the domain-wise policy file actually works now. --- MTAConfigGenerator.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MTAConfigGenerator.py b/MTAConfigGenerator.py index 1b98e7e96..27a714361 100755 --- a/MTAConfigGenerator.py +++ b/MTAConfigGenerator.py @@ -113,16 +113,16 @@ class PostfixConfigGenerator(MTAConfigGenerator): def set_domainwise_tls_policies(self): self.policy_lines = [] - for domain, policy in self.policy_config.tls_policies: - entry = domain + " encrypt " + for domain, policy in self.policy_config.tls_policies.items(): + entry = domain + " encrypt" if "min-tls-version" in policy: entry += " " + policy["min-tls-version"] self.policy_lines.append(entry) f = open(DEFAULT_POLICY_FILE, "w") - f.write("\n".join(self.policy_lines)) + f.write("\n".join(self.policy_lines) + "\n") if __name__ == "__main__": - import config-parser - c = config-parser.Config() + import ConfigParser + c = ConfigParser.Config() pcgen = PostfixConfigGenerator(c, fixup=True) From 182e9b29e4353a64a910a86edd6adb1d25976882 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 11 Jun 2014 09:42:17 -0700 Subject: [PATCH 07/10] Trying to standardize JSON terms --- ConfigParser.py | 10 +++++----- MTAConfigGenerator.py | 7 +++++-- config.json | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ConfigParser.py b/ConfigParser.py index dbc244b25..aba4eb23f 100755 --- a/ConfigParser.py +++ b/ConfigParser.py @@ -47,7 +47,7 @@ class Config: self.timestamp = parse_timestamp(val) elif atr == "expires": self.expires = parse_timestamp(val) - elif atr == "tls-policies": + elif atr == "security-policies": self.tls_policies = {} for domain,policies in self.check_tls_policy_domains(val): if type(policies) != dict: @@ -67,18 +67,18 @@ class Config: def check_tls_policy_domains(self, val): if type(val) != dict: - raise TypeError, "tls-policies should be a dict" + `val` + raise TypeError, "security-policies should be a dict" + `val` for domain, policies in val.items(): try: assert type(domain) == unicode d = str(domain) # convert from unicode except: - raise TypeError, "tls-policy domain not a string" + `domain` + raise TypeError, "security-policy domain not a string" + `domain` if not d.startswith("*."): - raise ValueError, "tls-policy domains must start with *.; try *."+d + raise ValueError, "security-policy domains must start with *.; try *."+d d = d.partition("*.")[2] if not looks_like_a_domain(d): - raise ValueError, "tls-policy for something that a domain? " + d + raise ValueError, "security-policy for something that a domain? " + d yield (d, policies) if __name__ == "__main__": diff --git a/MTAConfigGenerator.py b/MTAConfigGenerator.py index 27a714361..bee518e05 100755 --- a/MTAConfigGenerator.py +++ b/MTAConfigGenerator.py @@ -105,7 +105,9 @@ class PostfixConfigGenerator(MTAConfigGenerator): self.new_cf += sep + new_cf_lines print self.new_cf - f = open(self.fn, "w").write(self.new_cf) + f = open(self.fn, "w") + f.write(self.new_cf) + f.close() def find_postfix_cf(self): "Search far and wide for the correct postfix configuration file" @@ -121,8 +123,9 @@ class PostfixConfigGenerator(MTAConfigGenerator): f = open(DEFAULT_POLICY_FILE, "w") f.write("\n".join(self.policy_lines) + "\n") + f.close() if __name__ == "__main__": import ConfigParser - c = ConfigParser.Config() + c = ConfigParser.Config("starttls-everywhere.json") pcgen = PostfixConfigGenerator(c, fixup=True) diff --git a/config.json b/config.json index 1a9034545..8d38696ff 100644 --- a/config.json +++ b/config.json @@ -3,7 +3,7 @@ "timestamp": 1401093333, "author": "Electronic Frontier Foundation https://eff.org", "expires": 1404677353, "comment 2:": "epoch seconds", - "tls-policies": { + "security-policies": { "*.valid-example-recipient.com": { "min-tls-version": "TLSv1.1" } From 3712a4539907a05a98e289cfc48a6c62adccd686 Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 11 Jun 2014 09:48:43 -0700 Subject: [PATCH 08/10] Further (and different, and better) standardisation --- ConfigParser.py | 10 +++++----- README.md | 2 +- starttls-everywhere.json | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ConfigParser.py b/ConfigParser.py index aba4eb23f..dbc244b25 100755 --- a/ConfigParser.py +++ b/ConfigParser.py @@ -47,7 +47,7 @@ class Config: self.timestamp = parse_timestamp(val) elif atr == "expires": self.expires = parse_timestamp(val) - elif atr == "security-policies": + elif atr == "tls-policies": self.tls_policies = {} for domain,policies in self.check_tls_policy_domains(val): if type(policies) != dict: @@ -67,18 +67,18 @@ class Config: def check_tls_policy_domains(self, val): if type(val) != dict: - raise TypeError, "security-policies should be a dict" + `val` + raise TypeError, "tls-policies should be a dict" + `val` for domain, policies in val.items(): try: assert type(domain) == unicode d = str(domain) # convert from unicode except: - raise TypeError, "security-policy domain not a string" + `domain` + raise TypeError, "tls-policy domain not a string" + `domain` if not d.startswith("*."): - raise ValueError, "security-policy domains must start with *.; try *."+d + raise ValueError, "tls-policy domains must start with *.; try *."+d d = d.partition("*.")[2] if not looks_like_a_domain(d): - raise ValueError, "security-policy for something that a domain? " + d + raise ValueError, "tls-policy for something that a domain? " + d yield (d, policies) if __name__ == "__main__": diff --git a/README.md b/README.md index 79e0ed30d..2f0a410a1 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ The basic file format will be JSON with comments (http://blog.getify.com/json-co // "timestamp": 1401414363, : also acceptable "author": "Electronic Frontier Foundation https://eff.org", "expires": "2014-06-06T14:30:16+00:00", - "security-policies": { + "tls-policies": { // These match on the MX domain. "*.yahoodns.net": { "require-valid-certificate": true, diff --git a/starttls-everywhere.json b/starttls-everywhere.json index 4c91866d5..d0e656186 100644 --- a/starttls-everywhere.json +++ b/starttls-everywhere.json @@ -1,5 +1,5 @@ { - "mx-domains": { + "tls-policies": { "*.mx.aol.com": { "min-tls-version": "TLSv1", "require-tls": true @@ -49,7 +49,7 @@ "require-tls": true } }, - "address-domains": { + "acceptable-mxs": { "wp.pl": { "accept-mx-domains": [ "*.wp.pl" From 34cba3accfe2da92846cdf6a427724f60999a96a Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 11 Jun 2014 09:51:56 -0700 Subject: [PATCH 09/10] Now successfully parsing the larger policy set --- ConfigParser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ConfigParser.py b/ConfigParser.py index dbc244b25..8bc7e708f 100755 --- a/ConfigParser.py +++ b/ConfigParser.py @@ -55,7 +55,7 @@ class Config: self.tls_policies[domain] = {} # being here enforces TLS at all for policy, value in policies.items(): if policy == "min-tls-version": - reasonable = ["TLS", "TLSv1.1", "TLSv1.2", "TLSv1.3"] + reasonable = ["TLS", "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"] if not value in reasonable: raise ValueError, "Not a valid TLS version string: " + `value` self.tls_policies[domain]["min-tls-version"] = str(value) From a2ee328bc0dc3e384f9d1ecf6567aa16afbeb7ef Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Wed, 11 Jun 2014 10:32:52 -0700 Subject: [PATCH 10/10] Paramaterise "/etc/postfix" --- MTAConfigGenerator.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MTAConfigGenerator.py b/MTAConfigGenerator.py index bee518e05..3b69ba37a 100755 --- a/MTAConfigGenerator.py +++ b/MTAConfigGenerator.py @@ -1,9 +1,10 @@ #!/usr/bin/env python import string +import os.path - -DEFAULT_POLICY_FILE = "/etc/postfix/starttls_everywhere_policy" +POSTFIX_DIR = "/etc/postfix" +DEFAULT_POLICY_FILE = os.path.join(POSTFIX_DIR, "starttls_everywhere_policy") POLICY_CF_ENTRY="texthash:" + DEFAULT_POLICY_FILE def parse_line(line_data): @@ -111,7 +112,7 @@ class PostfixConfigGenerator(MTAConfigGenerator): def find_postfix_cf(self): "Search far and wide for the correct postfix configuration file" - return "/etc/postfix/main.cf" + return os.path.join(POSTFIX_DIR,"main.cf") def set_domainwise_tls_policies(self): self.policy_lines = []