tor-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2013
- 17 participants
- 1171 discussions

[translation/torbirdy_completed] Update translations for torbirdy_completed
by translation@torproject.org 06 Nov '13
by translation@torproject.org 06 Nov '13
06 Nov '13
commit eb984b8c8544d5903bf692e3d9aac99715e2dbb7
Author: Translation commit bot <translation(a)torproject.org>
Date: Wed Nov 6 01:16:08 2013 +0000
Update translations for torbirdy_completed
---
pl/torbirdy.properties | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pl/torbirdy.properties b/pl/torbirdy.properties
index c6372f7..761296f 100644
--- a/pl/torbirdy.properties
+++ b/pl/torbirdy.properties
@@ -13,7 +13,7 @@ torbirdy.email.advanced=Zmiana ustawień zaawansowanych TorBirdy NIE jest zaleca
torbirdy.email.advanced.nextwarning=Pokaż to ostrzeżenie następnym razem
torbirdy.email.advanced.title=Zaawansowane Ustawienia TorBirdy
-torbirdy.restart=Aby ustawienie strefy czasowej odniosło skutek, proszę zamknąć Thunderbirda i ponownie go uruchomić.
+torbirdy.restart=Musisz zrestartować Thunderbird'a aby zmiany czasowe uległy zmianie.
torbirdy.firstrun=TorBirdy jest teraz uruchomiony\n\nAby chronić Twoją anonimowość, TorBirdy będzie pilnował ustawionych przez siebie ustawień Thunderbirda, zapobiegając ich zmianie przez Ciebie lub inne dodatki. Można zmienić niektóre ustawienia, do których jest dostęp z okna ustawień TorBirdy. Gdy TorBirdy jest odinstalowany lub wyłączony, wszystkie zmienione przez niego ustawienia są resetowane do wartości domyślnych (sprzed instalacji TorBirdy).\n\nJeśli jesteś nowym użytkownikiem, zalecane jest przeczytanie strony internetowej TorBirdy, aby zrozumieć, co chcemy osiągnąć z TorBirdy dla naszych użytkowników.
torbirdy.website=https://trac.torproject.org/projects/tor/wiki/torbirdy
1
0

06 Nov '13
commit a2a215f2453ea49c9cf7f1a5543492ade7f27950
Author: Translation commit bot <translation(a)torproject.org>
Date: Wed Nov 6 01:16:04 2013 +0000
Update translations for torbirdy
---
pl/torbirdy.properties | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pl/torbirdy.properties b/pl/torbirdy.properties
index 9a5918d..761296f 100644
--- a/pl/torbirdy.properties
+++ b/pl/torbirdy.properties
@@ -13,7 +13,7 @@ torbirdy.email.advanced=Zmiana ustawień zaawansowanych TorBirdy NIE jest zaleca
torbirdy.email.advanced.nextwarning=Pokaż to ostrzeżenie następnym razem
torbirdy.email.advanced.title=Zaawansowane Ustawienia TorBirdy
-# torbirdy.restart=You must restart Thunderbird for the time zone preference to take effect.
+torbirdy.restart=Musisz zrestartować Thunderbird'a aby zmiany czasowe uległy zmianie.
torbirdy.firstrun=TorBirdy jest teraz uruchomiony\n\nAby chronić Twoją anonimowość, TorBirdy będzie pilnował ustawionych przez siebie ustawień Thunderbirda, zapobiegając ich zmianie przez Ciebie lub inne dodatki. Można zmienić niektóre ustawienia, do których jest dostęp z okna ustawień TorBirdy. Gdy TorBirdy jest odinstalowany lub wyłączony, wszystkie zmienione przez niego ustawienia są resetowane do wartości domyślnych (sprzed instalacji TorBirdy).\n\nJeśli jesteś nowym użytkownikiem, zalecane jest przeczytanie strony internetowej TorBirdy, aby zrozumieć, co chcemy osiągnąć z TorBirdy dla naszych użytkowników.
torbirdy.website=https://trac.torproject.org/projects/tor/wiki/torbirdy
1
0

[translation/torbutton-branddtd_completed] Update translations for torbutton-branddtd_completed
by translation@torproject.org 06 Nov '13
by translation@torproject.org 06 Nov '13
06 Nov '13
commit eb8bafe255a3dfa3a6e84943d157e19cc04a113f
Author: Translation commit bot <translation(a)torproject.org>
Date: Wed Nov 6 00:46:31 2013 +0000
Update translations for torbutton-branddtd_completed
---
pl/brand.dtd | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/pl/brand.dtd b/pl/brand.dtd
new file mode 100644
index 0000000..4cc23fd
--- /dev/null
+++ b/pl/brand.dtd
@@ -0,0 +1,8 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!ENTITY brandShortName "PrzeglądarkaTor'a">
+<!ENTITY brandFullName "Przeglądarka Tor'a">
+<!ENTITY vendorShortName "Project Tor">
+<!ENTITY trademarkInfo.part1 "Firefox i jego loga są znakami towarowymi Mozilla Foundation.">
1
0

[translation/torbutton-branddtd] Update translations for torbutton-branddtd
by translation@torproject.org 06 Nov '13
by translation@torproject.org 06 Nov '13
06 Nov '13
commit bef2e0c3aed3e1373db96bf3f619b5c6e58d0033
Author: Translation commit bot <translation(a)torproject.org>
Date: Wed Nov 6 00:46:28 2013 +0000
Update translations for torbutton-branddtd
---
pl/brand.dtd | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/pl/brand.dtd b/pl/brand.dtd
index e34f480..4cc23fd 100644
--- a/pl/brand.dtd
+++ b/pl/brand.dtd
@@ -2,7 +2,7 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<!ENTITY brandShortName "">
-<!ENTITY brandFullName "">
-<!ENTITY vendorShortName "">
-<!ENTITY trademarkInfo.part1 "">
+<!ENTITY brandShortName "PrzeglądarkaTor'a">
+<!ENTITY brandFullName "Przeglądarka Tor'a">
+<!ENTITY vendorShortName "Project Tor">
+<!ENTITY trademarkInfo.part1 "Firefox i jego loga są znakami towarowymi Mozilla Foundation.">
1
0

[flashproxy/master] move common code into a separate flashproxy-common package
by infinity0@torproject.org 05 Nov '13
by infinity0@torproject.org 05 Nov '13
05 Nov '13
commit aa03e11328d69aaee0caa9bf0aca9cd47673ff45
Author: Ximin Luo <infinity0(a)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_securit…
+ # 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(a)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_securit…
- # 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@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_securit…
- # 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)
1
0

[flashproxy/master] rename setup.py to be more specific and restricted in purpose
by infinity0@torproject.org 05 Nov '13
by infinity0@torproject.org 05 Nov '13
05 Nov '13
commit 202faaec39faf95ab62453c947c29e2ca4ef9335
Author: Ximin Luo <infinity0(a)gmx.com>
Date: Thu Sep 26 18:39:27 2013 +0100
rename setup.py to be more specific and restricted in purpose
---
Makefile | 4 ++--
setup-client-exe.py | 19 +++++++++++++++++++
setup.py | 18 ------------------
3 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/Makefile b/Makefile
index fb5a38b..d8c85cb 100644
--- a/Makefile
+++ b/Makefile
@@ -50,14 +50,14 @@ sign: dist/$(DISTNAME).zip
$(PY2EXE_TMPDIR)/dist: $(CLIENT_BIN)
rm -rf $(PY2EXE_TMPDIR)
- $(PYTHON) setup.py py2exe -q
+ $(PYTHON) setup-client-exe.py py2exe -q
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
+dist-exe: $(PY2EXE_TMPDIR)/dist setup-client-exe.py dist
clean:
rm -f *.pyc
diff --git a/setup-client-exe.py b/setup-client-exe.py
new file mode 100755
index 0000000..5baf71d
--- /dev/null
+++ b/setup-client-exe.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+from distutils.core import setup
+import os
+import py2exe
+
+build_path = os.path.join(os.environ["PY2EXE_TMPDIR"], "build")
+dist_path = os.path.join(os.environ["PY2EXE_TMPDIR"], "dist")
+
+setup(
+ console=["flashproxy-client", "flashproxy-reg-appspot", "flashproxy-reg-email", "flashproxy-reg-http", "flashproxy-reg-url"],
+ zipfile="py2exe-flashproxy.zip",
+ options={
+ "build": { "build_base": build_path },
+ "py2exe": {
+ "includes": ["M2Crypto"],
+ "dist_dir": dist_path
+ }
+ }
+)
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 89ef178..0000000
--- a/setup.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from distutils.core import setup
-import os
-import py2exe
-
-build_path = os.path.join(os.environ["PY2EXE_TMPDIR"], "build")
-dist_path = os.path.join(os.environ["PY2EXE_TMPDIR"], "dist")
-
-setup(
- console=["flashproxy-client", "flashproxy-reg-appspot", "flashproxy-reg-email", "flashproxy-reg-http", "flashproxy-reg-url"],
- zipfile="py2exe-flashproxy.zip",
- options={
- "build": { "build_base": build_path },
- "py2exe": {
- "includes": ["M2Crypto"],
- "dist_dir": dist_path
- }
- }
-)
1
0

05 Nov '13
commit 256e6962edaf218650aac54d2541c14b50c590c7
Author: Ximin Luo <infinity0(a)gmx.com>
Date: Thu Sep 26 18:39:13 2013 +0100
move common/flashproxy to top-level
---
.gitignore | 6 +++++
Makefile | 6 ++---
common/.gitignore | 5 -----
common/flashproxy/keys.py | 54 ---------------------------------------------
common/flashproxy/util.py | 52 -------------------------------------------
common/setup.py | 22 ------------------
flashproxy/keys.py | 54 +++++++++++++++++++++++++++++++++++++++++++++
flashproxy/util.py | 52 +++++++++++++++++++++++++++++++++++++++++++
setup-common.py | 22 ++++++++++++++++++
9 files changed, 137 insertions(+), 136 deletions(-)
diff --git a/.gitignore b/.gitignore
index 6195b6c..70f19a2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,13 @@
*.pyc
+
+# built by setup*.py
+/build
/dist
+/*.egg-info
/py2exe-tmp
+
/websocket-transport/websocket-client
/websocket-transport/websocket-server
/modules/nodejs/node_modules
/modules/nodejs/flashproxy.js
+
diff --git a/Makefile b/Makefile
index 62fd852..fb5a38b 100644
--- a/Makefile
+++ b/Makefile
@@ -5,14 +5,14 @@ PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man
-PYTHON ?= PYTHONPATH=common python
+PYTHON ?= 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
+CLIENT_DIST_LIB_COMMON = flashproxy/__init__.py flashproxy/keys.py flashproxy/util.py
all: $(CLIENT_DIST_FILES) $(CLIENT_MAN)
:
@@ -55,7 +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
+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
deleted file mode 100644
index b50e9ab..0000000
--- a/common/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# built by setup.py
-/build
-/dist
-/MANIFEST
-/*.egg-info
diff --git a/common/flashproxy/__init__.py b/common/flashproxy/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/common/flashproxy/keys.py b/common/flashproxy/keys.py
deleted file mode 100644
index 71525c8..0000000
--- a/common/flashproxy/keys.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# 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_securit…
- # 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
deleted file mode 100644
index 47bd87a..0000000
--- a/common/flashproxy/util.py
+++ /dev/null
@@ -1,52 +0,0 @@
-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
deleted file mode 100755
index 44c9c3e..0000000
--- a/common/setup.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-
-from setuptools import setup, find_packages
-
-setup(
- name = "flashproxy-common",
- author = "dcf",
- author_email = "dcf(a)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/__init__.py b/flashproxy/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/flashproxy/keys.py b/flashproxy/keys.py
new file mode 100644
index 0000000..71525c8
--- /dev/null
+++ b/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_securit…
+ # 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/flashproxy/util.py b/flashproxy/util.py
new file mode 100644
index 0000000..47bd87a
--- /dev/null
+++ b/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/setup-common.py b/setup-common.py
new file mode 100755
index 0000000..44c9c3e
--- /dev/null
+++ b/setup-common.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(a)torproject.org",
+ description = ("Common code for flashproxy"),
+ license = "BSD",
+ keywords = ['tor', 'flashproxy'],
+
+ packages = find_packages(),
+
+ version = "1.3",
+
+ install_requires = [
+ 'setuptools',
+ ],
+)
1
0

[flashproxy/master] get rid of dist in Makefile.client, it's not needed and causes problems in the PTBB
by infinity0@torproject.org 05 Nov '13
by infinity0@torproject.org 05 Nov '13
05 Nov '13
commit 48a19be94a175a8580308033cbd69d88e167a2dc
Author: Ximin Luo <infinity0(a)gmx.com>
Date: Mon Oct 21 18:38:42 2013 +0100
get rid of dist in Makefile.client, it's not needed and causes problems in the PTBB
- DISTNAME is propagated from Makefile, which in PTBB is set to "flashproxy-client"
- This results in a cyclic dependency since $(DISTNAME) depends on $(SRC_ALL) which includes flashproxy-client, the file
---
Makefile.client | 19 +------------------
1 file changed, 1 insertion(+), 18 deletions(-)
diff --git a/Makefile.client b/Makefile.client
index 5aec18a..ba7f733 100644
--- a/Makefile.client
+++ b/Makefile.client
@@ -5,7 +5,6 @@
PACKAGE = flashproxy-client
VERSION = 1.3
-DISTNAME = $(PACKAGE)-$(VERSION)
DESTDIR =
THISFILE = $(lastword $(MAKEFILE_LIST))
@@ -72,27 +71,11 @@ clean:
rm -f *.pyc
distclean: clean
- rm -rf $(DISTNAME)
- rm -f $(DISTNAME).tar.gz
maintainer-clean: distclean
rm -f $(DST_MAN1)
-$(DISTNAME): $(SRC_ALL) $(TEST_ALL) $(THISFILE)
- mkdir -p $@
- cp --parents -t "$@" $^
-
-$(DISTNAME).tar.gz: $(DISTNAME)
- tar czf "$@" "$<"
-
-# we never actually use this target, but it is given for completeness, in case
-# distro packagers want to do something with a client-only source tarball
-dist: force-dist $(DISTNAME).tar.gz
-
check: $(THISFILE)
for i in $(TEST_PY); do $(PYTHON) "$$i"; done
-force-dist:
- rm -rf $(DISTNAME) $(DISTNAME).tar.gz
-
-.PHONY: all install uninstall clean distclean maintainer-clean dist check force-dist
+.PHONY: all install uninstall clean distclean maintainer-clean dist check
1
0

[flashproxy/master] split Makefile into source-level vs binary-level packaging scripts
by infinity0@torproject.org 05 Nov '13
by infinity0@torproject.org 05 Nov '13
05 Nov '13
commit f6ca5f1d2cfd7b32a957cba14624773089a3e27f
Author: Ximin Luo <infinity0(a)gmx.com>
Date: Tue Oct 15 23:18:11 2013 +0100
split Makefile into source-level vs binary-level packaging scripts
- Makefile retains the same behaviour as before and builds dist/dist-exe
- Makefile.client acts on the client component only, following GNU standards
---
Makefile | 133 ++++++++-------
Makefile.client | 98 +++++++++++
flashproxy-client-test | 402 ---------------------------------------------
flashproxy-client-test.py | 401 ++++++++++++++++++++++++++++++++++++++++++++
setup-client-exe.py | 1 +
setup-common.py | 20 +++
6 files changed, 595 insertions(+), 460 deletions(-)
diff --git a/Makefile b/Makefile
index d8c85cb..24ef960 100644
--- a/Makefile
+++ b/Makefile
@@ -1,71 +1,88 @@
+# Makefile for a self-contained binary distribution of flashproxy-client.
+#
+# This builds two zipball targets, dist and dist-exe, for POSIX and Windows
+# respectively. Both can be extracted and run in-place by the end user.
+# (PGP-signed forms also exist, sign and sign-exe.)
+#
+# If you are a distro packager, instead see the separate build scripts for each
+# source component, all of which have an `install` target:
+# - client: Makefile.client
+# - common: setup-common.py
+# - facilitator: facilitator/{configure.ac,Makefile.am}
+#
+# Not for the faint-hearted: it is possible to build dist-exe on GNU/Linux by
+# using wine to install the windows versions of Python, py2exe, and m2crypto,
+# then running `make PYTHON_W32="wine python" dist-exe`.
+
+PACKAGE = flashproxy-client
VERSION = 1.3
+DISTNAME = $(PACKAGE)-$(VERSION)
-DESTDIR =
-PREFIX = /usr/local
-BINDIR = $(PREFIX)/bin
-MANDIR = $(PREFIX)/share/man
+THISFILE = $(lastword $(MAKEFILE_LIST))
+PYTHON = python
+PYTHON_W32 = $(PYTHON)
-PYTHON ?= python
-export PY2EXE_TMPDIR = py2exe-tmp
+MAKE_CLIENT = $(MAKE) -f Makefile.client PYTHON="$(PYTHON)"
-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 = flashproxy/__init__.py flashproxy/keys.py flashproxy/util.py
+# all is N/A for a binary package, but include for completeness
+all: dist
-all: $(CLIENT_DIST_FILES) $(CLIENT_MAN)
- :
+DISTDIR = dist/$(DISTNAME)
+$(DISTDIR): Makefile.client setup-common.py $(THISFILE)
+ mkdir -p $(DISTDIR)
+ $(MAKE_CLIENT) DESTDIR=$(DISTDIR) bindir=/ docdir=/ man1dir=/doc/ \
+ install
+ $(PYTHON) setup-common.py build_py -d $(DISTDIR)
-%.1: %.1.txt
- rm -f $@
- a2x --no-xmllint --xsltproc-opts "--stringparam man.th.title.max.length 24" -d manpage -f manpage $<
+dist/%.zip: dist/%
+ cd dist && zip -q -r -9 "$(@:dist/%=%)" "$(<:dist/%=%)"
-install:
- mkdir -p $(DESTDIR)$(BINDIR)
- mkdir -p $(DESTDIR)$(MANDIR)/man1
- cp -f $(CLIENT_BIN) $(DESTDIR)$(BINDIR)
- cp -f $(CLIENT_MAN) $(DESTDIR)$(MANDIR)/man1
+dist/%.zip.asc: dist/%.zip
+ rm -f "$@"
+ gpg --sign --detach-sign --armor "$<"
+ gpg --verify "$@" "$<"
-DISTNAME = flashproxy-client-$(VERSION)
-DISTDIR = dist/$(DISTNAME)
-dist: $(CLIENT_MAN)
- rm -rf dist
- mkdir -p $(DISTDIR)
- 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)
- $(MAKE) dist
-
-sign: dist/$(DISTNAME).zip
- rm -f dist/$(DISTNAME).zip.asc
- cd dist && gpg --sign --detach-sign --armor $(DISTNAME).zip
- cd dist && gpg --verify $(DISTNAME).zip.asc $(DISTNAME).zip
-
-$(PY2EXE_TMPDIR)/dist: $(CLIENT_BIN)
- rm -rf $(PY2EXE_TMPDIR)
- $(PYTHON) setup-client-exe.py py2exe -q
-
-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-client-exe.py dist
-
-clean:
- rm -f *.pyc
+dist: force-dist $(DISTDIR).zip
+
+sign: force-dist $(DISTDIR).zip.asc
+
+PY2EXE_TMPDIR = py2exe-tmp
+export PY2EXE_TMPDIR
+$(PY2EXE_TMPDIR): setup-client-exe.py
+ $(PYTHON_W32) setup-client-exe.py py2exe -q
+
+DISTDIR_W32 = $(DISTDIR)-win32
+# below, we override DST_SCRIPT and DST_MAN1 for windows
+$(DISTDIR_W32): $(PY2EXE_TMPDIR) $(THISFILE)
+ mkdir -p $(DISTDIR_W32)
+ $(MAKE_CLIENT) DESTDIR=$(DISTDIR_W32) bindir=/ docdir=/ man1dir=/doc/ \
+ DST_SCRIPT= DST_MAN1='$$(SRC_MAN1)' \
+ install
+ cp -t $(DISTDIR_W32) $(PY2EXE_TMPDIR)/dist/*
+
+dist-exe: force-dist-exe $(DISTDIR_W32).zip
+
+sign-exe: force-dist-exe $(DISTDIR_W32).zip.asc
+
+# clean is N/A for a binary package, but include for completeness
+clean: distclean
+
+distclean:
+ $(MAKE_CLIENT) clean
+ $(PYTHON) setup-common.py clean --all
rm -rf dist $(PY2EXE_TMPDIR)
-test:
- ./flashproxy-client-test
+test: check
+check:
+ $(MAKE_CLIENT) check
+ $(PYTHON) setup-common.py check
cd facilitator && ./facilitator-test
cd proxy && ./flashproxy-test.js
-.PHONY: all install dist sign dist-exe clean test
+force-dist:
+ rm -rf $(DISTDIR) $(DISTDIR).zip
+
+force-dist-exe:
+ rm -rf $(DISTDIR_W32) $(DISTDIR_W32).zip $(PY2EXE_TMPDIR)
+
+.PHONY: all dist sign dist-exe sign-exe clean distclean test check force-dist force-dist-exe
diff --git a/Makefile.client b/Makefile.client
new file mode 100644
index 0000000..5aec18a
--- /dev/null
+++ b/Makefile.client
@@ -0,0 +1,98 @@
+# Makefile for a source distribution of flashproxy-client.
+#
+# This package is not self-contained and the build products may require other
+# dependencies to function; it is given as a reference for distro packagers.
+
+PACKAGE = flashproxy-client
+VERSION = 1.3
+DISTNAME = $(PACKAGE)-$(VERSION)
+DESTDIR =
+
+THISFILE = $(lastword $(MAKEFILE_LIST))
+PYTHON = python
+
+# GNU command variables
+# see http://www.gnu.org/prep/standards/html_node/Command-Variables.html
+
+INSTALL = install
+INSTALL_DATA = $(INSTALL) -m 644
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_SCRIPT = $(INSTALL)
+
+# GNU directory variables
+# see http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
+
+prefix = /usr/local
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+
+datarootdir = $(prefix)/share
+datadir = $(datarootdir)
+sysconfdir = $(prefix)/etc
+
+docdir = $(datarootdir)/doc/$(PACKAGE)
+mandir = $(datarootdir)/man
+man1dir = $(mandir)/man1
+
+srcdir = .
+
+SRC_MAN1 = doc/flashproxy-client.1.txt doc/flashproxy-reg-appspot.1.txt doc/flashproxy-reg-email.1.txt doc/flashproxy-reg-http.1.txt doc/flashproxy-reg-url.1.txt
+SRC_SCRIPT = flashproxy-client flashproxy-reg-appspot flashproxy-reg-email flashproxy-reg-http flashproxy-reg-url
+SRC_DOC = README LICENSE ChangeLog torrc
+SRC_ALL = $(SRC_SCRIPT) $(SRC_DOC) $(SRC_MAN1)
+
+DST_MAN1 = $(SRC_MAN1:%.1.txt=%.1)
+DST_SCRIPT = $(SRC_SCRIPT)
+DST_DOC = $(SRC_DOC)
+DST_ALL = $(DST_SCRIPT) $(DST_DOC) $(DST_MAN1)
+
+TEST_PY = flashproxy-client-test.py
+TEST_ALL = $(TEST_PY)
+
+all: $(DST_ALL) $(THISFILE)
+
+%.1: %.1.txt $(THISFILE)
+ rm -f $@
+ a2x --no-xmllint --xsltproc-opts "--stringparam man.th.title.max.length 24" -d manpage -f manpage $<
+
+install: all
+ mkdir -p $(DESTDIR)$(bindir)
+ for i in $(DST_SCRIPT); do $(INSTALL_SCRIPT) "$$i" $(DESTDIR)$(bindir); done
+ mkdir -p $(DESTDIR)$(docdir)
+ for i in $(DST_DOC); do $(INSTALL_DATA) "$$i" $(DESTDIR)$(docdir); done
+ mkdir -p $(DESTDIR)$(man1dir)
+ for i in $(DST_MAN1); do $(INSTALL_DATA) "$$i" $(DESTDIR)$(man1dir); done
+
+uninstall:
+ for i in $(notdir $(DST_SCRIPT)); do rm $(DESTDIR)$(bindir)/"$$i"; done
+ for i in $(notdir $(DST_DOC)); do rm $(DESTDIR)$(docdir)/"$$i"; done
+ for i in $(notdir $(DST_MAN1)); do rm $(DESTDIR)$(man1dir)/"$$i"; done
+
+clean:
+ rm -f *.pyc
+
+distclean: clean
+ rm -rf $(DISTNAME)
+ rm -f $(DISTNAME).tar.gz
+
+maintainer-clean: distclean
+ rm -f $(DST_MAN1)
+
+$(DISTNAME): $(SRC_ALL) $(TEST_ALL) $(THISFILE)
+ mkdir -p $@
+ cp --parents -t "$@" $^
+
+$(DISTNAME).tar.gz: $(DISTNAME)
+ tar czf "$@" "$<"
+
+# we never actually use this target, but it is given for completeness, in case
+# distro packagers want to do something with a client-only source tarball
+dist: force-dist $(DISTNAME).tar.gz
+
+check: $(THISFILE)
+ for i in $(TEST_PY); do $(PYTHON) "$$i"; done
+
+force-dist:
+ rm -rf $(DISTNAME) $(DISTNAME).tar.gz
+
+.PHONY: all install uninstall clean distclean maintainer-clean dist check force-dist
diff --git a/flashproxy-client-test b/flashproxy-client-test
deleted file mode 100755
index e3c6644..0000000
--- a/flashproxy-client-test
+++ /dev/null
@@ -1,402 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import base64
-import cStringIO
-import httplib
-import socket
-import subprocess
-import sys
-import unittest
-print sys.path
-try:
- from hashlib import sha1
-except ImportError:
- # Python 2.4 uses this name.
- from sha import sha as sha1
-
-# Special tricks to load a module whose filename contains a dash and doesn't end
-# in ".py".
-import imp
-dont_write_bytecode = sys.dont_write_bytecode
-sys.dont_write_bytecode = True
-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 fp_client
-
-LOCAL_ADDRESS = ("127.0.0.1", 40000)
-REMOTE_ADDRESS = ("127.0.0.1", 40001)
-
-class TestSocks(unittest.TestCase):
- def test_parse_socks_request_empty(self):
- self.assertRaises(ValueError, parse_socks_request, "")
- def test_parse_socks_request_short(self):
- self.assertRaises(ValueError, parse_socks_request, "\x04\x01\x99\x99\x01\x02\x03\x04")
- def test_parse_socks_request_ip_userid_missing(self):
- dest, port = parse_socks_request("\x04\x01\x99\x99\x01\x02\x03\x04\x00")
- dest, port = parse_socks_request("\x04\x01\x99\x99\x01\x02\x03\x04\x00userid")
- self.assertEqual((dest, port), ("1.2.3.4", 0x9999))
- def test_parse_socks_request_ip(self):
- dest, port = parse_socks_request("\x04\x01\x99\x99\x01\x02\x03\x04userid\x00")
- self.assertEqual((dest, port), ("1.2.3.4", 0x9999))
- def test_parse_socks_request_hostname_missing(self):
- self.assertRaises(ValueError, parse_socks_request, "\x04\x01\x99\x99\x00\x00\x00\x01userid\x00")
- self.assertRaises(ValueError, parse_socks_request, "\x04\x01\x99\x99\x00\x00\x00\x01userid\x00abc")
- def test_parse_socks_request_hostname(self):
- dest, port = parse_socks_request("\x04\x01\x99\x99\x00\x00\x00\x01userid\x00abc\x00")
-
-class DummySocket(object):
- def __init__(self, read_fd, write_fd):
- self.read_fd = read_fd
- self.write_fd = write_fd
- self.readp = 0
-
- def read(self, *args, **kwargs):
- self.read_fd.seek(self.readp, 0)
- data = self.read_fd.read(*args, **kwargs)
- self.readp = self.read_fd.tell()
- return data
-
- def readline(self, *args, **kwargs):
- self.read_fd.seek(self.readp, 0)
- data = self.read_fd.readline(*args, **kwargs)
- self.readp = self.read_fd.tell()
- return data
-
- def recv(self, size, *args, **kwargs):
- return self.read(size)
-
- def write(self, data):
- self.write_fd.seek(0, 2)
- self.write_fd.write(data)
-
- def send(self, data, *args, **kwargs):
- return self.write(data)
-
- def sendall(self, data, *args, **kwargs):
- return self.write(data)
-
- def makefile(self, *args, **kwargs):
- return self
-
-def dummy_socketpair():
- f1 = cStringIO.StringIO()
- f2 = cStringIO.StringIO()
- return (DummySocket(f1, f2), DummySocket(f2, f1))
-
-class HTTPRequest(object):
- def __init__(self):
- self.method = "GET"
- self.path = "/"
- self.headers = {}
-
-def transact_http(req):
- l, r = dummy_socketpair()
- r.send("%s %s HTTP/1.0\r\n" % (req.method, req.path))
- for k, v in req.headers.items():
- r.send("%s: %s\r\n" % (k, v))
- r.send("\r\n")
- protocols = handle_websocket_request(l)
-
- resp = httplib.HTTPResponse(r)
- resp.begin()
- return resp, protocols
-
-class TestHandleWebSocketRequest(unittest.TestCase):
- DEFAULT_KEY = "0123456789ABCDEF"
- DEFAULT_KEY_BASE64 = base64.b64encode(DEFAULT_KEY)
- MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
-
- @staticmethod
- def default_req():
- req = HTTPRequest()
- req.method = "GET"
- req.path = "/"
- req.headers["Upgrade"] = "websocket"
- req.headers["Connection"] = "Upgrade"
- req.headers["Sec-WebSocket-Key"] = TestHandleWebSocketRequest.DEFAULT_KEY_BASE64
- req.headers["Sec-WebSocket-Version"] = "13"
-
- return req
-
- def assert_ok(self, req):
- resp, protocols = transact_http(req)
- self.assertEqual(resp.status, 101)
- self.assertEqual(resp.getheader("Upgrade").lower(), "websocket")
- self.assertEqual(resp.getheader("Connection").lower(), "upgrade")
- self.assertEqual(resp.getheader("Sec-WebSocket-Accept"), base64.b64encode(sha1(self.DEFAULT_KEY_BASE64 + self.MAGIC_GUID).digest()))
- self.assertEqual(protocols, [])
-
- def assert_not_ok(self, req):
- resp, protocols = transact_http(req)
- self.assertEqual(resp.status // 100, 4)
- self.assertEqual(protocols, None)
-
- def test_default(self):
- req = self.default_req()
- self.assert_ok(req)
-
- def test_missing_upgrade(self):
- req = self.default_req()
- del req.headers["Upgrade"]
- self.assert_not_ok(req)
-
- def test_missing_connection(self):
- req = self.default_req()
- del req.headers["Connection"]
- self.assert_not_ok(req)
-
- def test_case_insensitivity(self):
- """Test that the values of the Upgrade and Connection headers are
- case-insensitive."""
- req = self.default_req()
- req.headers["Upgrade"] = req.headers["Upgrade"].lower()
- self.assert_ok(req)
- req.headers["Upgrade"] = req.headers["Upgrade"].upper()
- self.assert_ok(req)
- req.headers["Connection"] = req.headers["Connection"].lower()
- self.assert_ok(req)
- req.headers["Connection"] = req.headers["Connection"].upper()
- self.assert_ok(req)
-
- def test_bogus_key(self):
- req = self.default_req()
- req.headers["Sec-WebSocket-Key"] = base64.b64encode(self.DEFAULT_KEY[:-1])
- self.assert_not_ok(req)
-
- req.headers["Sec-WebSocket-Key"] = "///"
- self.assert_not_ok(req)
-
- def test_versions(self):
- req = self.default_req()
- req.headers["Sec-WebSocket-Version"] = "13"
- self.assert_ok(req)
- req.headers["Sec-WebSocket-Version"] = "8"
- self.assert_ok(req)
-
- req.headers["Sec-WebSocket-Version"] = "7"
- self.assert_not_ok(req)
- req.headers["Sec-WebSocket-Version"] = "9"
- self.assert_not_ok(req)
-
- del req.headers["Sec-WebSocket-Version"]
- self.assert_not_ok(req)
-
- def test_protocols(self):
- req = self.default_req()
- req.headers["Sec-WebSocket-Protocol"] = "base64"
- resp, protocols = transact_http(req)
- self.assertEqual(resp.status, 101)
- self.assertEqual(protocols, ["base64"])
- self.assertEqual(resp.getheader("Sec-WebSocket-Protocol"), "base64")
-
- req = self.default_req()
- req.headers["Sec-WebSocket-Protocol"] = "cat"
- resp, protocols = transact_http(req)
- self.assertEqual(resp.status, 101)
- self.assertEqual(protocols, ["cat"])
- self.assertEqual(resp.getheader("Sec-WebSocket-Protocol"), None)
-
- req = self.default_req()
- req.headers["Sec-WebSocket-Protocol"] = "cat, base64"
- resp, protocols = transact_http(req)
- self.assertEqual(resp.status, 101)
- self.assertEqual(protocols, ["cat", "base64"])
- self.assertEqual(resp.getheader("Sec-WebSocket-Protocol"), "base64")
-
-def read_frames(dec):
- frames = []
- while True:
- frame = dec.read_frame()
- if frame is None:
- break
- frames.append((frame.fin, frame.opcode, frame.payload))
- return frames
-
-def read_messages(dec):
- messages = []
- while True:
- message = dec.read_message()
- if message is None:
- break
- messages.append((message.opcode, message.payload))
- return messages
-
-class TestWebSocketDecoder(unittest.TestCase):
- def test_rfc(self):
- """Test samples from RFC 6455 section 5.7."""
- TESTS = [
- ("\x81\x05\x48\x65\x6c\x6c\x6f", False,
- [(True, 1, "Hello")],
- [(1, u"Hello")]),
- ("\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", True,
- [(True, 1, "Hello")],
- [(1, u"Hello")]),
- ("\x01\x03\x48\x65\x6c\x80\x02\x6c\x6f", False,
- [(False, 1, "Hel"), (True, 0, "lo")],
- [(1, u"Hello")]),
- ("\x89\x05\x48\x65\x6c\x6c\x6f", False,
- [(True, 9, "Hello")],
- [(9, u"Hello")]),
- ("\x8a\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", True,
- [(True, 10, "Hello")],
- [(10, u"Hello")]),
- ("\x82\x7e\x01\x00" + "\x00" * 256, False,
- [(True, 2, "\x00" * 256)],
- [(2, "\x00" * 256)]),
- ("\x82\x7f\x00\x00\x00\x00\x00\x01\x00\x00" + "\x00" * 65536, False,
- [(True, 2, "\x00" * 65536)],
- [(2, "\x00" * 65536)]),
- ("\x82\x7f\x00\x00\x00\x00\x00\x01\x00\x03" + "ABCD" * 16384 + "XYZ", False,
- [(True, 2, "ABCD" * 16384 + "XYZ")],
- [(2, "ABCD" * 16384 + "XYZ")]),
- ]
- for data, use_mask, expected_frames, expected_messages in TESTS:
- dec = WebSocketDecoder(use_mask = use_mask)
- dec.feed(data)
- actual_frames = read_frames(dec)
- self.assertEqual(actual_frames, expected_frames)
-
- dec = WebSocketDecoder(use_mask = use_mask)
- dec.feed(data)
- actual_messages = read_messages(dec)
- self.assertEqual(actual_messages, expected_messages)
-
- dec = WebSocketDecoder(use_mask = not use_mask)
- dec.feed(data)
- self.assertRaises(WebSocketDecoder.MaskingError, dec.read_frame)
-
- def test_empty_feed(self):
- """Test that the decoder can handle a zero-byte feed."""
- dec = WebSocketDecoder()
- self.assertEqual(dec.read_frame(), None)
- dec.feed("")
- self.assertEqual(dec.read_frame(), None)
- dec.feed("\x81\x05H")
- self.assertEqual(dec.read_frame(), None)
- dec.feed("ello")
- self.assertEqual(read_frames(dec), [(True, 1, u"Hello")])
-
- def test_empty_frame(self):
- """Test that a frame may contain a zero-byte payload."""
- dec = WebSocketDecoder()
- dec.feed("\x81\x00")
- self.assertEqual(read_frames(dec), [(True, 1, u"")])
- dec.feed("\x82\x00")
- self.assertEqual(read_frames(dec), [(True, 2, "")])
-
- def test_empty_message(self):
- """Test that a message may have a zero-byte payload."""
- dec = WebSocketDecoder()
- dec.feed("\x01\x00\x00\x00\x80\x00")
- self.assertEqual(read_messages(dec), [(1, u"")])
- dec.feed("\x02\x00\x00\x00\x80\x00")
- self.assertEqual(read_messages(dec), [(2, "")])
-
- def test_interleaved_control(self):
- """Test that control messages interleaved with fragmented messages are
- returned."""
- dec = WebSocketDecoder()
- dec.feed("\x89\x04PING\x01\x03Hel\x8a\x04PONG\x80\x02lo\x89\x04PING")
- self.assertEqual(read_messages(dec), [(9, "PING"), (10, "PONG"), (1, u"Hello"), (9, "PING")])
-
- def test_fragmented_control(self):
- """Test that illegal fragmented control messages cause an error."""
- dec = WebSocketDecoder()
- dec.feed("\x09\x04PING")
- self.assertRaises(ValueError, dec.read_message)
-
- def test_zero_opcode(self):
- """Test that it is an error for the first frame in a message to have an
- opcode of 0."""
- dec = WebSocketDecoder()
- dec.feed("\x80\x05Hello")
- self.assertRaises(ValueError, dec.read_message)
- dec = WebSocketDecoder()
- dec.feed("\x00\x05Hello")
- self.assertRaises(ValueError, dec.read_message)
-
- def test_nonzero_opcode(self):
- """Test that every frame after the first must have a zero opcode."""
- dec = WebSocketDecoder()
- dec.feed("\x01\x01H\x01\x02el\x80\x02lo")
- self.assertRaises(ValueError, dec.read_message)
- dec = WebSocketDecoder()
- dec.feed("\x01\x01H\x00\x02el\x01\x02lo")
- self.assertRaises(ValueError, dec.read_message)
-
- def test_utf8(self):
- """Test that text frames (opcode 1) are decoded from UTF-8."""
- text = u"Hello World or Καλημέρα κόσμε or こんにちは 世界 or \U0001f639"
- utf8_text = text.encode("utf-8")
- dec = WebSocketDecoder()
- dec.feed("\x81" + chr(len(utf8_text)) + utf8_text)
- self.assertEqual(read_messages(dec), [(1, text)])
-
- def test_wrong_utf8(self):
- """Test that failed UTF-8 decoding causes an error."""
- TESTS = [
- "\xc0\x41", # Non-shortest form.
- "\xc2", # Unfinished sequence.
- ]
- for test in TESTS:
- dec = WebSocketDecoder()
- dec.feed("\x81" + chr(len(test)) + test)
- self.assertRaises(ValueError, dec.read_message)
-
- def test_overly_large_payload(self):
- """Test that large payloads are rejected."""
- dec = WebSocketDecoder()
- dec.feed("\x82\x7f\x00\x00\x00\x00\x01\x00\x00\x00")
- self.assertRaises(ValueError, dec.read_frame)
-
-class TestWebSocketEncoder(unittest.TestCase):
- def test_length(self):
- """Test that payload lengths are encoded using the smallest number of
- bytes."""
- TESTS = [(0, 0), (125, 0), (126, 2), (65535, 2), (65536, 8)]
- for length, encoded_length in TESTS:
- enc = WebSocketEncoder(use_mask = False)
- eframe = enc.encode_frame(2, "\x00" * length)
- self.assertEqual(len(eframe), 1 + 1 + encoded_length + length)
- enc = WebSocketEncoder(use_mask = True)
- eframe = enc.encode_frame(2, "\x00" * length)
- self.assertEqual(len(eframe), 1 + 1 + encoded_length + 4 + length)
-
- def test_roundtrip(self):
- TESTS = [
- (1, u"Hello world"),
- (1, u"Hello \N{WHITE SMILING FACE}"),
- ]
- for opcode, payload in TESTS:
- for use_mask in (False, True):
- enc = WebSocketEncoder(use_mask = use_mask)
- enc_message = enc.encode_message(opcode, payload)
- dec = WebSocketDecoder(use_mask = use_mask)
- dec.feed(enc_message)
- self.assertEqual(read_messages(dec), [(opcode, payload)])
-
-def format_address(addr):
- return "%s:%d" % addr
-
-class TestConnectionLimit(unittest.TestCase):
- def setUp(self):
- self.p = subprocess.Popen(["./flashproxy-client", format_address(LOCAL_ADDRESS), format_address(REMOTE_ADDRESS)])
-
- def tearDown(self):
- self.p.terminate()
-
-# def test_remote_limit(self):
-# """Test that the client transport plugin limits the number of remote
-# connections that it will accept."""
-# for i in range(5):
-# s = socket.create_connection(REMOTE_ADDRESS, 2)
-# self.assertRaises(socket.error, socket.create_connection, REMOTE_ADDRESS)
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/flashproxy-client-test.py b/flashproxy-client-test.py
new file mode 100755
index 0000000..0281f42
--- /dev/null
+++ b/flashproxy-client-test.py
@@ -0,0 +1,401 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import base64
+import cStringIO
+import httplib
+import socket
+import subprocess
+import sys
+import unittest
+try:
+ from hashlib import sha1
+except ImportError:
+ # Python 2.4 uses this name.
+ from sha import sha as sha1
+
+# Special tricks to load a module whose filename contains a dash and doesn't end
+# in ".py".
+import imp
+dont_write_bytecode = sys.dont_write_bytecode
+sys.dont_write_bytecode = True
+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 fp_client
+
+LOCAL_ADDRESS = ("127.0.0.1", 40000)
+REMOTE_ADDRESS = ("127.0.0.1", 40001)
+
+class TestSocks(unittest.TestCase):
+ def test_parse_socks_request_empty(self):
+ self.assertRaises(ValueError, parse_socks_request, "")
+ def test_parse_socks_request_short(self):
+ self.assertRaises(ValueError, parse_socks_request, "\x04\x01\x99\x99\x01\x02\x03\x04")
+ def test_parse_socks_request_ip_userid_missing(self):
+ dest, port = parse_socks_request("\x04\x01\x99\x99\x01\x02\x03\x04\x00")
+ dest, port = parse_socks_request("\x04\x01\x99\x99\x01\x02\x03\x04\x00userid")
+ self.assertEqual((dest, port), ("1.2.3.4", 0x9999))
+ def test_parse_socks_request_ip(self):
+ dest, port = parse_socks_request("\x04\x01\x99\x99\x01\x02\x03\x04userid\x00")
+ self.assertEqual((dest, port), ("1.2.3.4", 0x9999))
+ def test_parse_socks_request_hostname_missing(self):
+ self.assertRaises(ValueError, parse_socks_request, "\x04\x01\x99\x99\x00\x00\x00\x01userid\x00")
+ self.assertRaises(ValueError, parse_socks_request, "\x04\x01\x99\x99\x00\x00\x00\x01userid\x00abc")
+ def test_parse_socks_request_hostname(self):
+ dest, port = parse_socks_request("\x04\x01\x99\x99\x00\x00\x00\x01userid\x00abc\x00")
+
+class DummySocket(object):
+ def __init__(self, read_fd, write_fd):
+ self.read_fd = read_fd
+ self.write_fd = write_fd
+ self.readp = 0
+
+ def read(self, *args, **kwargs):
+ self.read_fd.seek(self.readp, 0)
+ data = self.read_fd.read(*args, **kwargs)
+ self.readp = self.read_fd.tell()
+ return data
+
+ def readline(self, *args, **kwargs):
+ self.read_fd.seek(self.readp, 0)
+ data = self.read_fd.readline(*args, **kwargs)
+ self.readp = self.read_fd.tell()
+ return data
+
+ def recv(self, size, *args, **kwargs):
+ return self.read(size)
+
+ def write(self, data):
+ self.write_fd.seek(0, 2)
+ self.write_fd.write(data)
+
+ def send(self, data, *args, **kwargs):
+ return self.write(data)
+
+ def sendall(self, data, *args, **kwargs):
+ return self.write(data)
+
+ def makefile(self, *args, **kwargs):
+ return self
+
+def dummy_socketpair():
+ f1 = cStringIO.StringIO()
+ f2 = cStringIO.StringIO()
+ return (DummySocket(f1, f2), DummySocket(f2, f1))
+
+class HTTPRequest(object):
+ def __init__(self):
+ self.method = "GET"
+ self.path = "/"
+ self.headers = {}
+
+def transact_http(req):
+ l, r = dummy_socketpair()
+ r.send("%s %s HTTP/1.0\r\n" % (req.method, req.path))
+ for k, v in req.headers.items():
+ r.send("%s: %s\r\n" % (k, v))
+ r.send("\r\n")
+ protocols = handle_websocket_request(l)
+
+ resp = httplib.HTTPResponse(r)
+ resp.begin()
+ return resp, protocols
+
+class TestHandleWebSocketRequest(unittest.TestCase):
+ DEFAULT_KEY = "0123456789ABCDEF"
+ DEFAULT_KEY_BASE64 = base64.b64encode(DEFAULT_KEY)
+ MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+
+ @staticmethod
+ def default_req():
+ req = HTTPRequest()
+ req.method = "GET"
+ req.path = "/"
+ req.headers["Upgrade"] = "websocket"
+ req.headers["Connection"] = "Upgrade"
+ req.headers["Sec-WebSocket-Key"] = TestHandleWebSocketRequest.DEFAULT_KEY_BASE64
+ req.headers["Sec-WebSocket-Version"] = "13"
+
+ return req
+
+ def assert_ok(self, req):
+ resp, protocols = transact_http(req)
+ self.assertEqual(resp.status, 101)
+ self.assertEqual(resp.getheader("Upgrade").lower(), "websocket")
+ self.assertEqual(resp.getheader("Connection").lower(), "upgrade")
+ self.assertEqual(resp.getheader("Sec-WebSocket-Accept"), base64.b64encode(sha1(self.DEFAULT_KEY_BASE64 + self.MAGIC_GUID).digest()))
+ self.assertEqual(protocols, [])
+
+ def assert_not_ok(self, req):
+ resp, protocols = transact_http(req)
+ self.assertEqual(resp.status // 100, 4)
+ self.assertEqual(protocols, None)
+
+ def test_default(self):
+ req = self.default_req()
+ self.assert_ok(req)
+
+ def test_missing_upgrade(self):
+ req = self.default_req()
+ del req.headers["Upgrade"]
+ self.assert_not_ok(req)
+
+ def test_missing_connection(self):
+ req = self.default_req()
+ del req.headers["Connection"]
+ self.assert_not_ok(req)
+
+ def test_case_insensitivity(self):
+ """Test that the values of the Upgrade and Connection headers are
+ case-insensitive."""
+ req = self.default_req()
+ req.headers["Upgrade"] = req.headers["Upgrade"].lower()
+ self.assert_ok(req)
+ req.headers["Upgrade"] = req.headers["Upgrade"].upper()
+ self.assert_ok(req)
+ req.headers["Connection"] = req.headers["Connection"].lower()
+ self.assert_ok(req)
+ req.headers["Connection"] = req.headers["Connection"].upper()
+ self.assert_ok(req)
+
+ def test_bogus_key(self):
+ req = self.default_req()
+ req.headers["Sec-WebSocket-Key"] = base64.b64encode(self.DEFAULT_KEY[:-1])
+ self.assert_not_ok(req)
+
+ req.headers["Sec-WebSocket-Key"] = "///"
+ self.assert_not_ok(req)
+
+ def test_versions(self):
+ req = self.default_req()
+ req.headers["Sec-WebSocket-Version"] = "13"
+ self.assert_ok(req)
+ req.headers["Sec-WebSocket-Version"] = "8"
+ self.assert_ok(req)
+
+ req.headers["Sec-WebSocket-Version"] = "7"
+ self.assert_not_ok(req)
+ req.headers["Sec-WebSocket-Version"] = "9"
+ self.assert_not_ok(req)
+
+ del req.headers["Sec-WebSocket-Version"]
+ self.assert_not_ok(req)
+
+ def test_protocols(self):
+ req = self.default_req()
+ req.headers["Sec-WebSocket-Protocol"] = "base64"
+ resp, protocols = transact_http(req)
+ self.assertEqual(resp.status, 101)
+ self.assertEqual(protocols, ["base64"])
+ self.assertEqual(resp.getheader("Sec-WebSocket-Protocol"), "base64")
+
+ req = self.default_req()
+ req.headers["Sec-WebSocket-Protocol"] = "cat"
+ resp, protocols = transact_http(req)
+ self.assertEqual(resp.status, 101)
+ self.assertEqual(protocols, ["cat"])
+ self.assertEqual(resp.getheader("Sec-WebSocket-Protocol"), None)
+
+ req = self.default_req()
+ req.headers["Sec-WebSocket-Protocol"] = "cat, base64"
+ resp, protocols = transact_http(req)
+ self.assertEqual(resp.status, 101)
+ self.assertEqual(protocols, ["cat", "base64"])
+ self.assertEqual(resp.getheader("Sec-WebSocket-Protocol"), "base64")
+
+def read_frames(dec):
+ frames = []
+ while True:
+ frame = dec.read_frame()
+ if frame is None:
+ break
+ frames.append((frame.fin, frame.opcode, frame.payload))
+ return frames
+
+def read_messages(dec):
+ messages = []
+ while True:
+ message = dec.read_message()
+ if message is None:
+ break
+ messages.append((message.opcode, message.payload))
+ return messages
+
+class TestWebSocketDecoder(unittest.TestCase):
+ def test_rfc(self):
+ """Test samples from RFC 6455 section 5.7."""
+ TESTS = [
+ ("\x81\x05\x48\x65\x6c\x6c\x6f", False,
+ [(True, 1, "Hello")],
+ [(1, u"Hello")]),
+ ("\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", True,
+ [(True, 1, "Hello")],
+ [(1, u"Hello")]),
+ ("\x01\x03\x48\x65\x6c\x80\x02\x6c\x6f", False,
+ [(False, 1, "Hel"), (True, 0, "lo")],
+ [(1, u"Hello")]),
+ ("\x89\x05\x48\x65\x6c\x6c\x6f", False,
+ [(True, 9, "Hello")],
+ [(9, u"Hello")]),
+ ("\x8a\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", True,
+ [(True, 10, "Hello")],
+ [(10, u"Hello")]),
+ ("\x82\x7e\x01\x00" + "\x00" * 256, False,
+ [(True, 2, "\x00" * 256)],
+ [(2, "\x00" * 256)]),
+ ("\x82\x7f\x00\x00\x00\x00\x00\x01\x00\x00" + "\x00" * 65536, False,
+ [(True, 2, "\x00" * 65536)],
+ [(2, "\x00" * 65536)]),
+ ("\x82\x7f\x00\x00\x00\x00\x00\x01\x00\x03" + "ABCD" * 16384 + "XYZ", False,
+ [(True, 2, "ABCD" * 16384 + "XYZ")],
+ [(2, "ABCD" * 16384 + "XYZ")]),
+ ]
+ for data, use_mask, expected_frames, expected_messages in TESTS:
+ dec = WebSocketDecoder(use_mask = use_mask)
+ dec.feed(data)
+ actual_frames = read_frames(dec)
+ self.assertEqual(actual_frames, expected_frames)
+
+ dec = WebSocketDecoder(use_mask = use_mask)
+ dec.feed(data)
+ actual_messages = read_messages(dec)
+ self.assertEqual(actual_messages, expected_messages)
+
+ dec = WebSocketDecoder(use_mask = not use_mask)
+ dec.feed(data)
+ self.assertRaises(WebSocketDecoder.MaskingError, dec.read_frame)
+
+ def test_empty_feed(self):
+ """Test that the decoder can handle a zero-byte feed."""
+ dec = WebSocketDecoder()
+ self.assertEqual(dec.read_frame(), None)
+ dec.feed("")
+ self.assertEqual(dec.read_frame(), None)
+ dec.feed("\x81\x05H")
+ self.assertEqual(dec.read_frame(), None)
+ dec.feed("ello")
+ self.assertEqual(read_frames(dec), [(True, 1, u"Hello")])
+
+ def test_empty_frame(self):
+ """Test that a frame may contain a zero-byte payload."""
+ dec = WebSocketDecoder()
+ dec.feed("\x81\x00")
+ self.assertEqual(read_frames(dec), [(True, 1, u"")])
+ dec.feed("\x82\x00")
+ self.assertEqual(read_frames(dec), [(True, 2, "")])
+
+ def test_empty_message(self):
+ """Test that a message may have a zero-byte payload."""
+ dec = WebSocketDecoder()
+ dec.feed("\x01\x00\x00\x00\x80\x00")
+ self.assertEqual(read_messages(dec), [(1, u"")])
+ dec.feed("\x02\x00\x00\x00\x80\x00")
+ self.assertEqual(read_messages(dec), [(2, "")])
+
+ def test_interleaved_control(self):
+ """Test that control messages interleaved with fragmented messages are
+ returned."""
+ dec = WebSocketDecoder()
+ dec.feed("\x89\x04PING\x01\x03Hel\x8a\x04PONG\x80\x02lo\x89\x04PING")
+ self.assertEqual(read_messages(dec), [(9, "PING"), (10, "PONG"), (1, u"Hello"), (9, "PING")])
+
+ def test_fragmented_control(self):
+ """Test that illegal fragmented control messages cause an error."""
+ dec = WebSocketDecoder()
+ dec.feed("\x09\x04PING")
+ self.assertRaises(ValueError, dec.read_message)
+
+ def test_zero_opcode(self):
+ """Test that it is an error for the first frame in a message to have an
+ opcode of 0."""
+ dec = WebSocketDecoder()
+ dec.feed("\x80\x05Hello")
+ self.assertRaises(ValueError, dec.read_message)
+ dec = WebSocketDecoder()
+ dec.feed("\x00\x05Hello")
+ self.assertRaises(ValueError, dec.read_message)
+
+ def test_nonzero_opcode(self):
+ """Test that every frame after the first must have a zero opcode."""
+ dec = WebSocketDecoder()
+ dec.feed("\x01\x01H\x01\x02el\x80\x02lo")
+ self.assertRaises(ValueError, dec.read_message)
+ dec = WebSocketDecoder()
+ dec.feed("\x01\x01H\x00\x02el\x01\x02lo")
+ self.assertRaises(ValueError, dec.read_message)
+
+ def test_utf8(self):
+ """Test that text frames (opcode 1) are decoded from UTF-8."""
+ text = u"Hello World or Καλημέρα κόσμε or こんにちは 世界 or \U0001f639"
+ utf8_text = text.encode("utf-8")
+ dec = WebSocketDecoder()
+ dec.feed("\x81" + chr(len(utf8_text)) + utf8_text)
+ self.assertEqual(read_messages(dec), [(1, text)])
+
+ def test_wrong_utf8(self):
+ """Test that failed UTF-8 decoding causes an error."""
+ TESTS = [
+ "\xc0\x41", # Non-shortest form.
+ "\xc2", # Unfinished sequence.
+ ]
+ for test in TESTS:
+ dec = WebSocketDecoder()
+ dec.feed("\x81" + chr(len(test)) + test)
+ self.assertRaises(ValueError, dec.read_message)
+
+ def test_overly_large_payload(self):
+ """Test that large payloads are rejected."""
+ dec = WebSocketDecoder()
+ dec.feed("\x82\x7f\x00\x00\x00\x00\x01\x00\x00\x00")
+ self.assertRaises(ValueError, dec.read_frame)
+
+class TestWebSocketEncoder(unittest.TestCase):
+ def test_length(self):
+ """Test that payload lengths are encoded using the smallest number of
+ bytes."""
+ TESTS = [(0, 0), (125, 0), (126, 2), (65535, 2), (65536, 8)]
+ for length, encoded_length in TESTS:
+ enc = WebSocketEncoder(use_mask = False)
+ eframe = enc.encode_frame(2, "\x00" * length)
+ self.assertEqual(len(eframe), 1 + 1 + encoded_length + length)
+ enc = WebSocketEncoder(use_mask = True)
+ eframe = enc.encode_frame(2, "\x00" * length)
+ self.assertEqual(len(eframe), 1 + 1 + encoded_length + 4 + length)
+
+ def test_roundtrip(self):
+ TESTS = [
+ (1, u"Hello world"),
+ (1, u"Hello \N{WHITE SMILING FACE}"),
+ ]
+ for opcode, payload in TESTS:
+ for use_mask in (False, True):
+ enc = WebSocketEncoder(use_mask = use_mask)
+ enc_message = enc.encode_message(opcode, payload)
+ dec = WebSocketDecoder(use_mask = use_mask)
+ dec.feed(enc_message)
+ self.assertEqual(read_messages(dec), [(opcode, payload)])
+
+def format_address(addr):
+ return "%s:%d" % addr
+
+class TestConnectionLimit(unittest.TestCase):
+ def setUp(self):
+ self.p = subprocess.Popen(["./flashproxy-client", format_address(LOCAL_ADDRESS), format_address(REMOTE_ADDRESS)])
+
+ def tearDown(self):
+ self.p.terminate()
+
+# def test_remote_limit(self):
+# """Test that the client transport plugin limits the number of remote
+# connections that it will accept."""
+# for i in range(5):
+# s = socket.create_connection(REMOTE_ADDRESS, 2)
+# self.assertRaises(socket.error, socket.create_connection, REMOTE_ADDRESS)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/setup-client-exe.py b/setup-client-exe.py
index 5baf71d..62b9c87 100755
--- a/setup-client-exe.py
+++ b/setup-client-exe.py
@@ -1,4 +1,5 @@
#!/usr/bin/python
+"""Setup file for the flashproxy-common python module."""
from distutils.core import setup
import os
import py2exe
diff --git a/setup-common.py b/setup-common.py
index 44c9c3e..85bb325 100755
--- a/setup-common.py
+++ b/setup-common.py
@@ -1,4 +1,24 @@
#!/usr/bin/env python
+"""Setup file for the flashproxy-common python module.
+
+To build/install a self-contained binary distribution of flashproxy-client
+(which integrates this module within it), see Makefile.
+"""
+# Note to future developers:
+#
+# We place flashproxy-common in the same directory as flashproxy-client for
+# convenience, so that it's possible to run the client programs directly from
+# a source checkout without needing to set PYTHONPATH. This works OK currently
+# because flashproxy-client does not contain python modules, only programs, and
+# therefore doesn't conflict with the flashproxy-common module.
+#
+# If we ever need to have a python module specific to flashproxy-client, the
+# natural thing would be to add a setup.py for it. That is the reason why this
+# file is called setup-common.py instead. However, there are still issues that
+# arise from having two setup*.py files in the same directory, which is an
+# unfortunate limitation of python's setuptools.
+#
+# See discussion on #6810 for more details.
import sys
1
0

05 Nov '13
commit 16550e66500ac3a81515a9953cb80607822ff88a
Author: Ximin Luo <infinity0(a)gmx.com>
Date: Tue Nov 5 22:05:27 2013 +0000
re-fix #9940 on the new split Makefiles
---
Makefile | 6 ++++--
Makefile.client | 8 +++++++-
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
index 3777271..2429f33 100644
--- a/Makefile
+++ b/Makefile
@@ -23,6 +23,8 @@ PYTHON = python
PYTHON_W32 = $(PYTHON)
MAKE_CLIENT = $(MAKE) -f Makefile.client PYTHON="$(PYTHON)"
+# don't rebuild man pages due to VCS giving spurious timestamps, see #9940
+REBUILD_MAN = 0
# all is N/A for a binary package, but include for completeness
all: dist
@@ -31,7 +33,7 @@ DISTDIR = dist/$(DISTNAME)
$(DISTDIR): Makefile.client setup-common.py $(THISFILE)
mkdir -p $(DISTDIR)
$(MAKE_CLIENT) DESTDIR=$(DISTDIR) bindir=/ docdir=/ man1dir=/doc/ \
- install
+ REBUILD_MAN="$(REBUILD_MAN)" install
$(PYTHON) setup-common.py build_py -d $(DISTDIR)
dist/%.zip: dist/%
@@ -57,7 +59,7 @@ $(DISTDIR_W32): $(PY2EXE_TMPDIR) $(THISFILE)
mkdir -p $(DISTDIR_W32)
$(MAKE_CLIENT) DESTDIR=$(DISTDIR_W32) bindir=/ docdir=/ man1dir=/doc/ \
DST_SCRIPT= DST_MAN1='$$(SRC_MAN1)' \
- install
+ REBUILD_MAN="$(REBUILD_MAN)" install
cp -t $(DISTDIR_W32) $(PY2EXE_TMPDIR)/dist/*
dist-exe: force-dist-exe $(DISTDIR_W32).zip
diff --git a/Makefile.client b/Makefile.client
index 0cb676c..9ebc576 100644
--- a/Makefile.client
+++ b/Makefile.client
@@ -48,11 +48,17 @@ DST_ALL = $(DST_SCRIPT) $(DST_DOC) $(DST_MAN1)
TEST_PY = flashproxy-client-test.py
TEST_ALL = $(TEST_PY)
+REBUILD_MAN = 1
+
all: $(DST_ALL) $(THISFILE)
-%.1: %.1.txt $(THISFILE)
+%.1: %.1.txt
+ifeq ($(REBUILD_MAN),0)
+ @echo "warning: $@ *may* be out-of-date; if so then rm and re-checkout from VCS or force a re-build with REBUILD_MAN=1"
+else
rm -f $@
a2x --no-xmllint --xsltproc-opts "--stringparam man.th.title.max.length 24" -d manpage -f manpage $<
+endif
install: all
mkdir -p $(DESTDIR)$(bindir)
1
0