[tor-commits] [flashproxy/master] move common code into a separate flashproxy-common package
infinity0 at torproject.org
infinity0 at torproject.org
Tue Nov 5 23:54:35 UTC 2013
commit aa03e11328d69aaee0caa9bf0aca9cd47673ff45
Author: Ximin Luo <infinity0 at gmx.com>
Date: Sun Sep 15 18:28:51 2013 +0100
move common code into a separate flashproxy-common package
---
Makefile | 7 ++-
common/.gitignore | 5 ++
common/flashproxy/keys.py | 54 +++++++++++++++++++++
common/flashproxy/util.py | 52 ++++++++++++++++++++
common/setup.py | 22 +++++++++
flashproxy-client | 54 ++-------------------
flashproxy-client-test | 14 +++---
flashproxy-reg-appspot | 97 ++------------------------------------
flashproxy-reg-email | 115 +++------------------------------------------
flashproxy-reg-http | 52 +-------------------
flashproxy-reg-url | 64 ++-----------------------
11 files changed, 166 insertions(+), 370 deletions(-)
diff --git a/Makefile b/Makefile
index 7aa71fc..62fd852 100644
--- a/Makefile
+++ b/Makefile
@@ -5,13 +5,14 @@ PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man
-PYTHON = python
+PYTHON ?= PYTHONPATH=common python
export PY2EXE_TMPDIR = py2exe-tmp
CLIENT_BIN = flashproxy-client flashproxy-reg-appspot flashproxy-reg-email flashproxy-reg-http flashproxy-reg-url
CLIENT_MAN = doc/flashproxy-client.1 doc/flashproxy-reg-appspot.1 doc/flashproxy-reg-email.1 doc/flashproxy-reg-http.1 doc/flashproxy-reg-url.1
CLIENT_DIST_FILES = $(CLIENT_BIN) README LICENSE ChangeLog torrc
CLIENT_DIST_DOC_FILES = $(CLIENT_MAN)
+CLIENT_DIST_LIB_COMMON = common/flashproxy/__init__.py common/flashproxy/keys.py common/flashproxy/util.py
all: $(CLIENT_DIST_FILES) $(CLIENT_MAN)
:
@@ -34,6 +35,9 @@ dist: $(CLIENT_MAN)
mkdir $(DISTDIR)/doc
cp -f $(CLIENT_DIST_FILES) $(DISTDIR)
cp -f $(CLIENT_DIST_DOC_FILES) $(DISTDIR)/doc
+ test -n "$(CLIENT_DIST_LIB_COMMON)" && \
+ { mkdir $(DISTDIR)/flashproxy && \
+ cp -f $(CLIENT_DIST_LIB_COMMON) $(DISTDIR)/flashproxy; } || true
cd dist && zip -q -r -9 $(DISTNAME).zip $(DISTNAME)
dist/$(DISTNAME).zip: $(CLIENT_DIST_FILES)
@@ -51,6 +55,7 @@ $(PY2EXE_TMPDIR)/dist: $(CLIENT_BIN)
dist-exe: DISTNAME := $(DISTNAME)-win32
dist-exe: CLIENT_BIN := $(PY2EXE_TMPDIR)/dist/*
dist-exe: CLIENT_MAN := $(addsuffix .txt,$(CLIENT_MAN))
+dist-exe: CLIENT_DIST_LIB_COMMON := # py2exe static-links dependencies
# Delegate to the "dist" target using the substitutions above.
dist-exe: $(PY2EXE_TMPDIR)/dist setup.py dist
diff --git a/common/.gitignore b/common/.gitignore
new file mode 100644
index 0000000..b50e9ab
--- /dev/null
+++ b/common/.gitignore
@@ -0,0 +1,5 @@
+# built by setup.py
+/build
+/dist
+/MANIFEST
+/*.egg-info
diff --git a/common/flashproxy/__init__.py b/common/flashproxy/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/common/flashproxy/keys.py b/common/flashproxy/keys.py
new file mode 100644
index 0000000..71525c8
--- /dev/null
+++ b/common/flashproxy/keys.py
@@ -0,0 +1,54 @@
+# We trust no other CA certificate than this.
+#
+# To find the certificate to copy here,
+# $ strace openssl s_client -connect FRONT_DOMAIN:443 -verify 10 -CApath /etc/ssl/certs 2>&1 | grep /etc/ssl/certs
+# stat("/etc/ssl/certs/XXXXXXXX.0", {st_mode=S_IFREG|0644, st_size=YYYY, ...}) = 0
+PIN_GOOGLE_CERT = """\
+subject=/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
+issuer=/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
+UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
+dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
+MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
+dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
+BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
+cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
+AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
+aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
+ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
+IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
+MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
+A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
+7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
+1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
+-----END CERTIFICATE-----
+"""
+# 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.
+PIN_GOOGLE_PUBKEY_SHA1 = (
+ # https://src.chromium.org/viewvc/chrome/trunk/src/net/http/transport_security_state_static.h?revision=209003&view=markup
+ # kSPKIHash_Google1024
+ "\x40\xc5\x40\x1d\x6f\x8c\xba\xf0\x8b\x00\xed\xef\xb1\xee\x87\xd0\x05\xb3\xb9\xcd",
+ # kSPKIHash_GoogleG2
+ "\x43\xda\xd6\x30\xee\x53\xf8\xa9\x80\xca\x6e\xfd\x85\xf4\x6a\xa3\x79\x90\xe0\xea",
+)
+
+# Registrations are encrypted with this public key before being emailed. Only
+# the facilitator operators should have the corresponding private key. Given a
+# private key in reg-email, get the public key like this:
+# openssl rsa -pubout < reg-email > reg-email.pub
+DEFAULT_FACILITATOR_PUBKEY_PEM = """\
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA44Mt8c599/4N2fgu6ppN
+oatPW1GOgZxxObljFtEy0OWM1eHB35OOn+Kn9MxNHTRxVWwCEi0HYxWNVs2qrXxV
+84LmWBz6A65d2qBlgltgLXusiXLrpwxVmJeO+GfmbF8ur0U9JSYxA20cGW/kujNg
+XYDGQxO1Gvxq2lHK2LQmBpkfKEE1DMFASmIvlHDQgDj3XBb5lYeOsHZmg16UrGAq
+1UH238hgJITPGLXBtwLtJkYbrATJvrEcmvI7QSm57SgYGpaB5ZdCbJL5bag5Pgt6
+M5SDDYYY4xxEPzokjFJfCQv+kcyAnzERNMQ9kR41ePTXG62bpngK5iWGeJ5XdkxG
+gwIDAQAB
+-----END PUBLIC KEY-----
+"""
diff --git a/common/flashproxy/util.py b/common/flashproxy/util.py
new file mode 100644
index 0000000..47bd87a
--- /dev/null
+++ b/common/flashproxy/util.py
@@ -0,0 +1,52 @@
+import re
+import socket
+
+def parse_addr_spec(spec, defhost = None, defport = None):
+ host = None
+ port = None
+ af = 0
+ m = None
+ # IPv6 syntax.
+ if not m:
+ m = re.match(ur'^\[(.+)\]:(\d*)$', spec)
+ if m:
+ host, port = m.groups()
+ af = socket.AF_INET6
+ if not m:
+ m = re.match(ur'^\[(.+)\]$', spec)
+ if m:
+ host, = m.groups()
+ af = socket.AF_INET6
+ # IPv4/hostname/port-only syntax.
+ if not m:
+ try:
+ host, port = spec.split(":", 1)
+ except ValueError:
+ host = spec
+ if re.match(ur'^[\d.]+$', host):
+ af = socket.AF_INET
+ else:
+ af = 0
+ host = host or defhost
+ port = port or defport
+ if port is not None:
+ port = int(port)
+ return host, port
+
+def format_addr(addr):
+ host, port = addr
+ if not host:
+ return u":%d" % port
+ # Numeric IPv6 address?
+ try:
+ addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_NUMERICHOST)
+ af = addrs[0][0]
+ except socket.gaierror, e:
+ af = 0
+ if af == socket.AF_INET6:
+ result = u"[%s]" % host
+ else:
+ result = "%s" % host
+ if port is not None:
+ result += u":%d" % port
+ return result
diff --git a/common/setup.py b/common/setup.py
new file mode 100755
index 0000000..44c9c3e
--- /dev/null
+++ b/common/setup.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+import sys
+
+from setuptools import setup, find_packages
+
+setup(
+ name = "flashproxy-common",
+ author = "dcf",
+ author_email = "dcf at torproject.org",
+ description = ("Common code for flashproxy"),
+ license = "BSD",
+ keywords = ['tor', 'flashproxy'],
+
+ packages = find_packages(),
+
+ version = "1.3",
+
+ install_requires = [
+ 'setuptools',
+ ],
+)
diff --git a/flashproxy-client b/flashproxy-client
index cf16437..e1cfadc 100755
--- a/flashproxy-client
+++ b/flashproxy-client
@@ -20,6 +20,8 @@ import traceback
import urllib
import xml.sax.saxutils
+from flashproxy.util import parse_addr_spec, format_addr
+
try:
from hashlib import sha1
except ImportError:
@@ -147,56 +149,6 @@ def log(msg):
finally:
log_lock.release()
-def parse_addr_spec(spec, defhost = None, defport = None):
- host = None
- port = None
- af = 0
- m = None
- # IPv6 syntax.
- if not m:
- m = re.match(ur'^\[(.+)\]:(\d*)$', spec)
- if m:
- host, port = m.groups()
- af = socket.AF_INET6
- if not m:
- m = re.match(ur'^\[(.+)\]$', spec)
- if m:
- host, = m.groups()
- af = socket.AF_INET6
- # IPv4/hostname/port-only syntax.
- if not m:
- try:
- host, port = spec.split(":", 1)
- except ValueError:
- host = spec
- if re.match(ur'^[\d.]+$', host):
- af = socket.AF_INET
- else:
- af = 0
- host = host or defhost
- port = port or defport
- if port is not None:
- port = int(port)
- return host, port
-
-def format_addr(addr):
- host, port = addr
- if not host:
- return u":%d" % port
- # Numeric IPv6 address?
- try:
- addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_NUMERICHOST)
- af = addrs[0][0]
- except socket.gaierror, e:
- af = 0
- if af == socket.AF_INET6:
- result = u"[%s]" % host
- else:
- result = "%s" % host
- if port is not None:
- result += u":%d" % port
- return result
-
def safe_format_addr(addr):
return safe_str(format_addr(addr))
@@ -728,7 +680,7 @@ def forward_ports(pairs):
log("%s exited with status %d." % (basename, p.returncode))
return False
return True
-
+
register_condvar = threading.Condition()
# register_flag true means registration_thread_func should register at its next
# opportunity.
diff --git a/flashproxy-client-test b/flashproxy-client-test
index 084a272..e3c6644 100755
--- a/flashproxy-client-test
+++ b/flashproxy-client-test
@@ -8,7 +8,7 @@ import socket
import subprocess
import sys
import unittest
-
+print sys.path
try:
from hashlib import sha1
except ImportError:
@@ -20,14 +20,14 @@ except ImportError:
import imp
dont_write_bytecode = sys.dont_write_bytecode
sys.dont_write_bytecode = True
-flashproxy = imp.load_source("flashproxy", "flashproxy-client")
-parse_socks_request = flashproxy.parse_socks_request
-handle_websocket_request = flashproxy.handle_websocket_request
-WebSocketDecoder = flashproxy.WebSocketDecoder
-WebSocketEncoder = flashproxy.WebSocketEncoder
+fp_client = imp.load_source("fp_client", "flashproxy-client")
+parse_socks_request = fp_client.parse_socks_request
+handle_websocket_request = fp_client.handle_websocket_request
+WebSocketDecoder = fp_client.WebSocketDecoder
+WebSocketEncoder = fp_client.WebSocketEncoder
sys.dont_write_bytecode = dont_write_bytecode
del dont_write_bytecode
-del flashproxy
+del fp_client
LOCAL_ADDRESS = ("127.0.0.1", 40000)
REMOTE_ADDRESS = ("127.0.0.1", 40001)
diff --git a/flashproxy-reg-appspot b/flashproxy-reg-appspot
index c84f9e7..fc49985 100755
--- a/flashproxy-reg-appspot
+++ b/flashproxy-reg-appspot
@@ -13,6 +13,8 @@ import tempfile
import urlparse
import urllib2
+from flashproxy.keys import PIN_GOOGLE_CERT, PIN_GOOGLE_PUBKEY_SHA1
+from flashproxy.util import parse_addr_spec, format_addr
from hashlib import sha1
try:
@@ -32,45 +34,6 @@ TARGET_DOMAIN = "fp-reg-a.appspot.com"
FLASHPROXY_REG_URL = "flashproxy-reg-url"
-# We trust no other CA certificate than this.
-#
-# To find the certificate to copy here,
-# $ strace openssl s_client -connect FRONT_DOMAIN:443 -verify 10 -CApath /etc/ssl/certs 2>&1 | grep /etc/ssl/certs
-# stat("/etc/ssl/certs/XXXXXXXX.0", {st_mode=S_IFREG|0644, st_size=YYYY, ...}) = 0
-CA_CERTS = """\
-subject=/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
-issuer=/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
-MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
-dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
-BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
-cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
-MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
-ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
-7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
-1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
------END CERTIFICATE-----
-"""
-# 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 = (
- # https://src.chromium.org/viewvc/chrome/trunk/src/net/http/transport_security_state_static.h?revision=209003&view=markup
- # kSPKIHash_Google1024
- "\x40\xc5\x40\x1d\x6f\x8c\xba\xf0\x8b\x00\xed\xef\xb1\xee\x87\xd0\x05\xb3\xb9\xcd",
- # kSPKIHash_GoogleG2
- "\x43\xda\xd6\x30\xee\x53\xf8\xa9\x80\xca\x6e\xfd\x85\xf4\x6a\xa3\x79\x90\xe0\xea",
-)
-
class options(object):
address_family = socket.AF_UNSPEC
facilitator_pubkey_filename = None
@@ -104,56 +67,6 @@ def safe_str(s):
else:
return s
-def parse_addr_spec(spec, defhost = None, defport = None):
- host = None
- port = None
- af = 0
- m = None
- # IPv6 syntax.
- if not m:
- m = re.match(ur'^\[(.+)\]:(\d*)$', spec)
- if m:
- host, port = m.groups()
- af = socket.AF_INET6
- if not m:
- m = re.match(ur'^\[(.+)\]$', spec)
- if m:
- host, = m.groups()
- af = socket.AF_INET6
- # IPv4/hostname/port-only syntax.
- if not m:
- try:
- host, port = spec.split(":", 1)
- except ValueError:
- host = spec
- if re.match(ur'^[\d.]+$', host):
- af = socket.AF_INET
- else:
- af = 0
- host = host or defhost
- port = port or defport
- if port is not None:
- port = int(port)
- return host, port
-
-def format_addr(addr):
- host, port = addr
- if not host:
- return u":%d" % port
- # Numeric IPv6 address?
- try:
- addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_NUMERICHOST)
- af = addrs[0][0]
- except socket.gaierror, e:
- af = 0
- if af == socket.AF_INET6:
- result = u"[%s]" % host
- else:
- result = "%s" % host
- if port is not None:
- result += u":%d" % port
- return result
-
def safe_format_addr(addr):
return safe_str(format_addr(addr))
@@ -225,7 +138,7 @@ class PinHTTPSConnection(httplib.HTTPSConnection):
ca_certs_fd, ca_certs_path = tempfile.mkstemp(prefix="flashproxy-reg-appspot-",
dir=get_state_dir(), suffix=".crt")
try:
- os.write(ca_certs_fd, CA_CERTS)
+ os.write(ca_certs_fd, PIN_GOOGLE_CERT)
os.close(ca_certs_fd)
ret = ctx.load_verify_locations(ca_certs_path)
assert ret == 1
@@ -240,12 +153,12 @@ class PinHTTPSConnection(httplib.HTTPSConnection):
for cert in self.sock.get_peer_cert_chain():
pubkey_der = cert.get_pubkey().as_der()
pubkey_digest = sha1(pubkey_der).digest()
- if pubkey_digest in PUBKEY_SHA1:
+ if pubkey_digest in PIN_GOOGLE_PUBKEY_SHA1:
break
found.append(pubkey_digest)
else:
found = "(" + ", ".join(x.encode("hex") for x in found) + ")"
- expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
+ expected = "(" + ", ".join(x.encode("hex") for x in PIN_GOOGLE_PUBKEY_SHA1) + ")"
raise ValueError("Public key does not match pin: got %s but expected any of %s" % (found, expected))
class PinHTTPSHandler(urllib2.HTTPSHandler):
diff --git a/flashproxy-reg-email b/flashproxy-reg-email
index 13ab5a5..0cb626b 100755
--- a/flashproxy-reg-email
+++ b/flashproxy-reg-email
@@ -10,6 +10,8 @@ import ssl
import sys
import tempfile
+from flashproxy.keys import PIN_GOOGLE_CERT, PIN_GOOGLE_PUBKEY_SHA1, DEFAULT_FACILITATOR_PUBKEY_PEM
+from flashproxy.util import parse_addr_spec, format_addr
from hashlib import sha1
try:
@@ -29,59 +31,6 @@ DEFAULT_SMTP_PORT = 25
EHLO_FQDN = "[127.0.0.1]"
FROM_EMAIL_ADDRESS = "nobody at localhost"
-# We trust no other CA certificate than this.
-#
-# To find the certificate to copy here,
-# $ strace openssl s_client -connect gmail-smtp-in.l.google.com:25 -starttls smtp -verify 10 -CApath /etc/ssl/certs 2>&1 | grep /etc/ssl/certs
-# stat("/etc/ssl/certs/XXXXXXXX.0", {st_mode=S_IFREG|0644, st_size=YYYY, ...}) = 0
-CA_CERTS = """\
-subject=/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
-issuer=/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
-MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
-dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
-BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
-cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
-MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
-ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
-7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
-1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
------END CERTIFICATE-----
-"""
-# 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 = (
- # https://src.chromium.org/viewvc/chrome/trunk/src/net/http/transport_security_state_static.h?revision=209003&view=markup
- # kSPKIHash_Google1024
- "\x40\xc5\x40\x1d\x6f\x8c\xba\xf0\x8b\x00\xed\xef\xb1\xee\x87\xd0\x05\xb3\xb9\xcd",
-)
-
-# Registrations are encrypted with this public key before being emailed. Only
-# the facilitator operators should have the corresponding private key. Given a
-# private key in reg-email, get the public key like this:
-# openssl rsa -pubout < reg-email > reg-email.pub
-DEFAULT_FACILITATOR_PUBKEY_PEM = """\
------BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA44Mt8c599/4N2fgu6ppN
-oatPW1GOgZxxObljFtEy0OWM1eHB35OOn+Kn9MxNHTRxVWwCEi0HYxWNVs2qrXxV
-84LmWBz6A65d2qBlgltgLXusiXLrpwxVmJeO+GfmbF8ur0U9JSYxA20cGW/kujNg
-XYDGQxO1Gvxq2lHK2LQmBpkfKEE1DMFASmIvlHDQgDj3XBb5lYeOsHZmg16UrGAq
-1UH238hgJITPGLXBtwLtJkYbrATJvrEcmvI7QSm57SgYGpaB5ZdCbJL5bag5Pgt6
-M5SDDYYY4xxEPzokjFJfCQv+kcyAnzERNMQ9kR41ePTXG62bpngK5iWGeJ5XdkxG
-gwIDAQAB
------END PUBLIC KEY-----
-"""
-
class options(object):
remote_addr = None
email_addr = None
@@ -131,56 +80,6 @@ def safe_str(s):
else:
return s
-def parse_addr_spec(spec, defhost = None, defport = None):
- host = None
- port = None
- af = 0
- m = None
- # IPv6 syntax.
- if not m:
- m = re.match(ur'^\[(.+)\]:(\d*)$', spec)
- if m:
- host, port = m.groups()
- af = socket.AF_INET6
- if not m:
- m = re.match(ur'^\[(.+)\]$', spec)
- if m:
- host, = m.groups()
- af = socket.AF_INET6
- # IPv4/hostname/port-only syntax.
- if not m:
- try:
- host, port = spec.split(":", 1)
- except ValueError:
- host = spec
- if re.match(ur'^[\d.]+$', host):
- af = socket.AF_INET
- else:
- af = 0
- host = host or defhost
- port = port or defport
- if port is not None:
- port = int(port)
- return host, port
-
-def format_addr(addr):
- host, port = addr
- if not host:
- return u":%d" % port
- # Numeric IPv6 address?
- try:
- addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_NUMERICHOST)
- af = addrs[0][0]
- except socket.gaierror, e:
- af = 0
- if af == socket.AF_INET6:
- result = u"[%s]" % host
- else:
- result = "%s" % host
- if port is not None:
- result += u":%d" % port
- return result
-
def safe_format_addr(addr):
return safe_str(format_addr(addr))
@@ -265,7 +164,7 @@ try:
ca_certs_fd, ca_certs_path = tempfile.mkstemp(prefix="flashproxy-reg-email-",
dir=get_state_dir(), suffix=".crt")
try:
- os.write(ca_certs_fd, CA_CERTS)
+ os.write(ca_certs_fd, PIN_GOOGLE_CERT)
os.close(ca_certs_fd)
# We roll our own initial EHLO/STARTTLS because smtplib.SMTP.starttls
# doesn't allow enough certificate validation.
@@ -291,16 +190,16 @@ try:
for cert in smtp.sock.get_peer_cert_chain():
pubkey_der = cert.get_pubkey().as_der()
pubkey_digest = sha1(pubkey_der).digest()
- if pubkey_digest in PUBKEY_SHA1:
+ if pubkey_digest in PIN_GOOGLE_PUBKEY_SHA1:
break
found.append(pubkey_digest)
else:
found = "(" + ", ".join(x.encode("hex") for x in found) + ")"
- expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
+ expected = "(" + ", ".join(x.encode("hex") for x in PIN_GOOGLE_PUBKEY_SHA1) + ")"
raise ValueError("Public key does not match pin: got %s but expected any of %s" % (found, expected))
- if options.use_certificate_pin and pubkey_digest not in PUBKEY_SHA1:
- expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
+ if options.use_certificate_pin and pubkey_digest not in PIN_GOOGLE_PUBKEY_SHA1:
+ expected = "(" + ", ".join(x.encode("hex") for x in PIN_GOOGLE_PUBKEY_SHA1) + ")"
raise ValueError("Public key does not match pin: got %s but expected any of %s" %
(pubkey_digest.encode("hex"), expected))
diff --git a/flashproxy-reg-http b/flashproxy-reg-http
index 975ebda..6639e57 100755
--- a/flashproxy-reg-http
+++ b/flashproxy-reg-http
@@ -8,6 +8,8 @@ import sys
import urllib
import urllib2
+from flashproxy.util import parse_addr_spec, format_addr
+
DEFAULT_REMOTE_ADDRESS = ""
DEFAULT_REMOTE_PORT = 9000
DEFAULT_FACILITATOR_URL = "https://fp-facilitator.org/"
@@ -43,56 +45,6 @@ def safe_str(s):
else:
return s
-def parse_addr_spec(spec, defhost = None, defport = None):
- host = None
- port = None
- af = 0
- m = None
- # IPv6 syntax.
- if not m:
- m = re.match(ur'^\[(.+)\]:(\d*)$', spec)
- if m:
- host, port = m.groups()
- af = socket.AF_INET6
- if not m:
- m = re.match(ur'^\[(.+)\]$', spec)
- if m:
- host, = m.groups()
- af = socket.AF_INET6
- # IPv4/hostname/port-only syntax.
- if not m:
- try:
- host, port = spec.split(":", 1)
- except ValueError:
- host = spec
- if re.match(ur'^[\d.]+$', host):
- af = socket.AF_INET
- else:
- af = 0
- host = host or defhost
- port = port or defport
- if port is not None:
- port = int(port)
- return host, port
-
-def format_addr(addr):
- host, port = addr
- if not host:
- return u":%d" % port
- # Numeric IPv6 address?
- try:
- addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_NUMERICHOST)
- af = addrs[0][0]
- except socket.gaierror, e:
- af = 0
- if af == socket.AF_INET6:
- result = u"[%s]" % host
- else:
- result = "%s" % host
- if port is not None:
- result += u":%d" % port
- return result
-
options.facilitator_url = DEFAULT_FACILITATOR_URL
options.remote_addr = (DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)
diff --git a/flashproxy-reg-url b/flashproxy-reg-url
index b30c550..1c0b348 100755
--- a/flashproxy-reg-url
+++ b/flashproxy-reg-url
@@ -7,6 +7,9 @@ import socket
import sys
import urlparse
+from flashproxy.keys import DEFAULT_FACILITATOR_PUBKEY_PEM
+from flashproxy.util import parse_addr_spec, format_addr
+
try:
from M2Crypto import BIO, RSA
except ImportError:
@@ -16,17 +19,6 @@ except ImportError:
DEFAULT_REMOTE_ADDRESS = None
DEFAULT_REMOTE_PORT = 9000
DEFAULT_FACILITATOR_URL = "https://fp-facilitator.org/"
-DEFAULT_FACILITATOR_PUBKEY_PEM = """\
------BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA44Mt8c599/4N2fgu6ppN
-oatPW1GOgZxxObljFtEy0OWM1eHB35OOn+Kn9MxNHTRxVWwCEi0HYxWNVs2qrXxV
-84LmWBz6A65d2qBlgltgLXusiXLrpwxVmJeO+GfmbF8ur0U9JSYxA20cGW/kujNg
-XYDGQxO1Gvxq2lHK2LQmBpkfKEE1DMFASmIvlHDQgDj3XBb5lYeOsHZmg16UrGAq
-1UH238hgJITPGLXBtwLtJkYbrATJvrEcmvI7QSm57SgYGpaB5ZdCbJL5bag5Pgt6
-M5SDDYYY4xxEPzokjFJfCQv+kcyAnzERNMQ9kR41ePTXG62bpngK5iWGeJ5XdkxG
-gwIDAQAB
------END PUBLIC KEY-----
-"""
class options(object):
facilitator_url = None
@@ -51,56 +43,6 @@ default PORT is %(port)d.
"port": DEFAULT_REMOTE_PORT,
}
-def parse_addr_spec(spec, defhost = None, defport = None):
- host = None
- port = None
- af = 0
- m = None
- # IPv6 syntax.
- if not m:
- m = re.match(ur'^\[(.+)\]:(\d*)$', spec)
- if m:
- host, port = m.groups()
- af = socket.AF_INET6
- if not m:
- m = re.match(ur'^\[(.+)\]$', spec)
- if m:
- host, = m.groups()
- af = socket.AF_INET6
- # IPv4/hostname/port-only syntax.
- if not m:
- try:
- host, port = spec.split(":", 1)
- except ValueError:
- host = spec
- if re.match(ur'^[\d.]+$', host):
- af = socket.AF_INET
- else:
- af = 0
- host = host or defhost
- port = port or defport
- if port is not None:
- port = int(port)
- return host, port
-
-def format_addr(addr):
- host, port = addr
- if not host:
- return u":%d" % port
- # Numeric IPv6 address?
- try:
- addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_NUMERICHOST)
- af = addrs[0][0]
- except socket.gaierror, e:
- af = 0
- if af == socket.AF_INET6:
- result = u"[%s]" % host
- else:
- result = "%s" % host
- if port is not None:
- result += u":%d" % port
- return result
-
def get_facilitator_pubkey():
if options.facilitator_pubkey_filename is not None:
return RSA.load_pub_key(options.facilitator_pubkey_filename)
More information about the tor-commits
mailing list