commit f04c9ccdff66b53102cfc9f063bec75d6b801fe8 Author: David Fifield david@bamsoftware.com Date: Fri May 31 09:03:42 2013 -0700
Allow multiple public key pins. --- ChangeLog | 2 ++ facilitator/facilitator-email-poller | 13 ++++++++----- flashproxy-reg-appspot | 13 ++++++++----- flashproxy-reg-email | 13 ++++++++----- 4 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/ChangeLog b/ChangeLog index a9e92a3..be2ee15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ Changes in version 1.1 + o Programs that use certificate pins now take a --disable-pin option + that causes pins to be ignored.
Changes in version 1.0 o The facilitator runs on a new domain name fp-facilitator.org. Fixes diff --git a/facilitator/facilitator-email-poller b/facilitator/facilitator-email-poller index b70e649..9df7f3b 100755 --- a/facilitator/facilitator-email-poller +++ b/facilitator/facilitator-email-poller @@ -55,10 +55,12 @@ A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 -----END CERTIFICATE----- """ -# SHA-1 digest of expected public key. See +# SHA-1 digest of expected public keys. Any of these is valid. See # http://www.imperialviolet.org/2011/05/04/pinning.html for the reason behind # hashing the public key, not the entire certificate. -PUBKEY_SHA1 = "63c445c009328b663cdff9cb68f6c523ac7b6c2b".decode("hex") +PUBKEY_SHA1 = tuple(x.decode("hex") for x in ( + "63c445c009328b663cdff9cb68f6c523ac7b6c2b", +))
LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
@@ -294,9 +296,10 @@ def imap_login(): pubkey_der = cert.get_pubkey().as_der() pubkey_digest = sha1(pubkey_der).digest()
- if pubkey_digest != PUBKEY_SHA1: - raise ValueError("Public key does not match pin: got %s but expected %s" % - (pubkey_digest.encode("hex"), PUBKEY_SHA1.encode("hex"))) + if pubkey_digest not in PUBKEY_SHA1: + expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")" + raise ValueError("Public key does not match pin: got %s but expected any of %s" % + (pubkey_digest.encode("hex"), expected))
log(u"logging in as %s" % options.email_addr) imap.login(options.email_addr, email_password) diff --git a/flashproxy-reg-appspot b/flashproxy-reg-appspot index be2fbff..ab65f96 100755 --- a/flashproxy-reg-appspot +++ b/flashproxy-reg-appspot @@ -59,10 +59,12 @@ A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 -----END CERTIFICATE----- """ -# SHA-1 digest of expected public key. See +# SHA-1 digest of expected public keys. Any of these is valid. See # http://www.imperialviolet.org/2011/05/04/pinning.html for the reason behind # hashing the public key, not the entire certificate. -PUBKEY_SHA1 = "c70ccd442ff4528c603aefef85206fd693990e09".decode("hex") +PUBKEY_SHA1 = tuple(x.decode("hex") for x in ( + "c70ccd442ff4528c603aefef85206fd693990e09", +))
class options(object): address_family = socket.AF_UNSPEC @@ -194,9 +196,10 @@ class PinHTTPSConnection(httplib.HTTPSConnection): pubkey_der = cert.get_pubkey().as_der() pubkey_digest = sha1(pubkey_der).digest()
- if pubkey_digest != PUBKEY_SHA1: - raise ValueError("Public key does not match pin: got %s but expected %s" % - (pubkey_digest.encode("hex"), PUBKEY_SHA1.encode("hex"))) + if pubkey_digest not in PUBKEY_SHA1: + expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")" + raise ValueError("Public key does not match pin: got %s but expected any of %s" % + (pubkey_digest.encode("hex"), expected))
class PinHTTPSHandler(urllib2.HTTPSHandler): def https_open(self, req): diff --git a/flashproxy-reg-email b/flashproxy-reg-email index edfaff1..90e5264 100755 --- a/flashproxy-reg-email +++ b/flashproxy-reg-email @@ -57,10 +57,12 @@ A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 -----END CERTIFICATE----- """ -# SHA-1 digest of expected public key. See +# SHA-1 digest of expected public keys. Any of these is valid. See # http://www.imperialviolet.org/2011/05/04/pinning.html for the reason behind # hashing the public key, not the entire certificate. -PUBKEY_SHA1 = "69ba4a72fc198b2203ecdf0c75493e4d5300dac9".decode("hex") +PUBKEY_SHA1 = tuple(x.decode("hex") for x in ( + "69ba4a72fc198b2203ecdf0c75493e4d5300dac9", +))
# Registrations are encrypted with this public key before being emailed. Only # the facilitator operators should have the corresponding private key. Given a @@ -262,9 +264,10 @@ try: pubkey_der = cert.get_pubkey().as_der() pubkey_digest = sha1(pubkey_der).digest()
- if pubkey_digest != PUBKEY_SHA1: - raise ValueError("Public key does not match pin: got %s but expected %s" % - (pubkey_digest.encode("hex"), PUBKEY_SHA1.encode("hex"))) + if pubkey_digest not in PUBKEY_SHA1: + expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")" + raise ValueError("Public key does not match pin: got %s but expected any of %s" % + (pubkey_digest.encode("hex"), expected))
smtp.ehlo(EHLO_FQDN)
tor-commits@lists.torproject.org