[Pkg-privacy-commits] [flashproxy] 37/65: Imported Upstream version 1.7
Ximin Luo
infinity0 at moszumanska.debian.org
Fri Aug 21 13:49:43 UTC 2015
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch _volatile-rc
in repository flashproxy.
commit 9b2bfcbe64263544c965b635807fa62111b29ead
Author: Ximin Luo <infinity0 at pwned.gg>
Date: Tue Jul 22 19:35:13 2014 +0100
Imported Upstream version 1.7
---
ChangeLog | 17 ++
doc/flashproxy-client.1 | 6 +-
doc/flashproxy-client.1.txt | 2 -
doc/flashproxy-reg-appspot.1 | 6 +-
doc/flashproxy-reg-appspot.1.txt | 2 -
doc/flashproxy-reg-email.1 | 6 +-
doc/flashproxy-reg-email.1.txt | 2 -
doc/flashproxy-reg-http.1 | 6 +-
doc/flashproxy-reg-http.1.txt | 2 -
doc/flashproxy-reg-url.1 | 8 +-
doc/flashproxy-reg-url.1.txt | 2 -
experiments/exercise/exercise.sh | 2 +-
facilitator/.gitignore | 6 +-
facilitator/INSTALL | 4 +-
facilitator/Makefile.am | 38 +--
facilitator/README | 10 +-
facilitator/configure.ac | 8 +-
.../default/{facilitator => fp-facilitator} | 0
.../{facilitator-reg-daemon => fp-reg-decryptd} | 0
...facilitator-email-poller => fp-registrar-email} | 0
facilitator/doc/appspot-howto.txt | 2 +-
facilitator/doc/email-howto.txt | 40 ++-
facilitator/doc/facilitator-design.txt | 22 +-
facilitator/doc/http-howto.txt | 2 +-
facilitator/examples/facilitator-relays | 8 +-
facilitator/examples/fp-facilitator.conf.in | 2 +-
facilitator/{facilitator => fp-facilitator} | 2 +-
...{facilitator-test.py => fp-facilitator-test.py} | 4 +-
facilitator/{facilitator-reg => fp-reg-decrypt} | 4 +-
.../{facilitator-reg-daemon => fp-reg-decryptd} | 2 +-
...facilitator-email-poller => fp-registrar-email} | 8 +-
facilitator/{facilitator.cgi => fp-registrar.cgi} | 4 +-
.../init.d/{facilitator.in => fp-facilitator.in} | 6 +-
...acilitator-reg-daemon.in => fp-reg-decryptd.in} | 6 +-
...tator-email-poller.in => fp-registrar-email.in} | 6 +-
flashproxy-client | 310 +++++++++------------
flashproxy-reg-appspot | 145 ++--------
flashproxy-reg-email | 196 +++----------
flashproxy-reg-http | 120 ++------
flashproxy-reg-url | 111 ++------
flashproxy/keys.py | 66 +++--
flashproxy/reg.py | 58 +++-
flashproxy/util.py | 41 +++
mkman.sh | 9 +-
proxy/flashproxy-test.js | 27 ++
proxy/flashproxy.js | 65 +++--
torrc | 8 +-
47 files changed, 599 insertions(+), 802 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5c8e54d..b778a38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+Changes in version 1.7
+ o Made the badge color reflect what's going on when it encounters a
+ network error and tries to reconnect. Fixes bug 11400.
+
+ o Renamed facilitator programs:
+ facilitator → fp-facilitator
+ facilitator.cgi → fp-registrar.cgi
+ facilitator-email-poller → fp-registrar-email
+ facilitator-reg → fp-reg-decrypt
+ facilitator-reg-daemon → fp-reg-decryptd
+
+ o Fixed a bug in the browser proxy which caused it to stop accepting
+ new connections once it had failed 5 previous connections.
+
+ o Updated the Tor Browser detection for the Firefox 24.0 User-Agent
+ string. Patch by Arlo Breault. Fixes bug 11290.
+
Changes in version 1.6
o Allowed the --port-forwarding option to work when the remote port
number is given as 0.
diff --git a/doc/flashproxy-client.1 b/doc/flashproxy-client.1
index 74b0d30..ca90286 100644
--- a/doc/flashproxy-client.1
+++ b/doc/flashproxy-client.1
@@ -2,12 +2,12 @@
.\" Title: flashproxy-client
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 10/09/2013
+.\" Date: 05/07/2014
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "FLASHPROXY\-CLIENT" "1" "10/09/2013" "\ \&" "\ \&"
+.TH "FLASHPROXY\-CLIENT" "1" "05/07/2014" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -149,8 +149,6 @@ Don\(cqt scrub IP addresses from logs\&.
.SH "SEE ALSO"
.sp
\fBhttp://crypto\&.stanford\&.edu/flashproxy/\fR
-.sp
-\fBhttps://www\&.torproject\&.org/docs/pluggable\-transports\&.html\&.en\fR
.SH "BUGS"
.sp
Please report using \fBhttps://trac\&.torproject\&.org/projects/tor\fR\&.
diff --git a/doc/flashproxy-client.1.txt b/doc/flashproxy-client.1.txt
index b4779a2..78a3598 100644
--- a/doc/flashproxy-client.1.txt
+++ b/doc/flashproxy-client.1.txt
@@ -99,8 +99,6 @@ SEE ALSO
--------
**http://crypto.stanford.edu/flashproxy/**
-**https://www.torproject.org/docs/pluggable-transports.html.en**
-
BUGS
----
Please report using **https://trac.torproject.org/projects/tor**.
diff --git a/doc/flashproxy-reg-appspot.1 b/doc/flashproxy-reg-appspot.1
index 9af7346..551bf37 100644
--- a/doc/flashproxy-reg-appspot.1
+++ b/doc/flashproxy-reg-appspot.1
@@ -2,12 +2,12 @@
.\" Title: flashproxy-reg-appspot
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 10/10/2013
+.\" Date: 05/07/2014
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "FLASHPROXY\-REG\-APPSPOT" "1" "10/10/2013" "\ \&" "\ \&"
+.TH "FLASHPROXY\-REG\-APPSPOT" "1" "05/07/2014" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -80,8 +80,6 @@ Don\(cqt scrub IP addresses from logs\&.
.SH "SEE ALSO"
.sp
\fBhttp://crypto\&.stanford\&.edu/flashproxy/\fR
-.sp
-\fBhttps://www\&.torproject\&.org/docs/pluggable\-transports\&.html\&.en\fR
.SH "BUGS"
.sp
Please report using \fBhttps://trac\&.torproject\&.org/projects/tor\fR\&.
diff --git a/doc/flashproxy-reg-appspot.1.txt b/doc/flashproxy-reg-appspot.1.txt
index 9b5a124..bc3a4d5 100644
--- a/doc/flashproxy-reg-appspot.1.txt
+++ b/doc/flashproxy-reg-appspot.1.txt
@@ -57,8 +57,6 @@ SEE ALSO
--------
**http://crypto.stanford.edu/flashproxy/**
-**https://www.torproject.org/docs/pluggable-transports.html.en**
-
BUGS
----
Please report using **https://trac.torproject.org/projects/tor**.
diff --git a/doc/flashproxy-reg-email.1 b/doc/flashproxy-reg-email.1
index eac32cc..69eb146 100644
--- a/doc/flashproxy-reg-email.1
+++ b/doc/flashproxy-reg-email.1
@@ -2,12 +2,12 @@
.\" Title: flashproxy-reg-email
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 10/10/2013
+.\" Date: 05/07/2014
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "FLASHPROXY\-REG\-EMAIL" "1" "10/10/2013" "\ \&" "\ \&"
+.TH "FLASHPROXY\-REG\-EMAIL" "1" "05/07/2014" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -99,8 +99,6 @@ Don\(cqt scrub IP addresses from logs\&.
.SH "SEE ALSO"
.sp
\fBhttp://crypto\&.stanford\&.edu/flashproxy/\fR
-.sp
-\fBhttps://www\&.torproject\&.org/docs/pluggable\-transports\&.html\&.en\fR
.SH "BUGS"
.sp
Please report using \fBhttps://trac\&.torproject\&.org/projects/tor\fR\&.
diff --git a/doc/flashproxy-reg-email.1.txt b/doc/flashproxy-reg-email.1.txt
index 1adc242..2e2bfd5 100644
--- a/doc/flashproxy-reg-email.1.txt
+++ b/doc/flashproxy-reg-email.1.txt
@@ -68,8 +68,6 @@ SEE ALSO
--------
**http://crypto.stanford.edu/flashproxy/**
-**https://www.torproject.org/docs/pluggable-transports.html.en**
-
BUGS
----
Please report using **https://trac.torproject.org/projects/tor**.
diff --git a/doc/flashproxy-reg-http.1 b/doc/flashproxy-reg-http.1
index ea88705..1d70158 100644
--- a/doc/flashproxy-reg-http.1
+++ b/doc/flashproxy-reg-http.1
@@ -2,12 +2,12 @@
.\" Title: flashproxy-reg-http
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 10/10/2013
+.\" Date: 05/07/2014
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "FLASHPROXY\-REG\-HTTP" "1" "10/10/2013" "\ \&" "\ \&"
+.TH "FLASHPROXY\-REG\-HTTP" "1" "05/07/2014" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -71,8 +71,6 @@ Don\(cqt scrub IP addresses from logs\&.
.SH "SEE ALSO"
.sp
\fBhttp://crypto\&.stanford\&.edu/flashproxy/\fR
-.sp
-\fBhttps://www\&.torproject\&.org/docs/pluggable\-transports\&.html\&.en\fR
.SH "BUGS"
.sp
Please report using \fBhttps://trac\&.torproject\&.org/projects/tor\fR\&.
diff --git a/doc/flashproxy-reg-http.1.txt b/doc/flashproxy-reg-http.1.txt
index cae719c..0acbeec 100644
--- a/doc/flashproxy-reg-http.1.txt
+++ b/doc/flashproxy-reg-http.1.txt
@@ -43,8 +43,6 @@ SEE ALSO
--------
**http://crypto.stanford.edu/flashproxy/**
-**https://www.torproject.org/docs/pluggable-transports.html.en**
-
BUGS
----
Please report using **https://trac.torproject.org/projects/tor**.
diff --git a/doc/flashproxy-reg-url.1 b/doc/flashproxy-reg-url.1
index ec3cf1d..331b2c2 100644
--- a/doc/flashproxy-reg-url.1
+++ b/doc/flashproxy-reg-url.1
@@ -2,12 +2,12 @@
.\" Title: flashproxy-reg-url
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 10/09/2013
+.\" Date: 05/07/2014
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "FLASHPROXY\-REG\-URL" "1" "10/09/2013" "\ \&" "\ \&"
+.TH "FLASHPROXY\-REG\-URL" "1" "05/07/2014" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -39,7 +39,7 @@ Print a URL, which, when retrieved, will cause the client address \fIREMOTE\fR[:
.PP
\fB\-f\fR, \fB\-\-facilitator\fR=\fIURL\fR
.RS 4
-Register with the given facilitator (by default "https://fp\-facilitator\&.org/")\&.
+Register with the given facilitator (default "https://fp\-facilitator\&.org/")\&.
.RE
.PP
\fB\-\-facilitator\-pubkey\fR=\fIFILENAME\fR
@@ -80,8 +80,6 @@ Copy this string and paste it into any URL fetching website or program\&. Once t
.SH "SEE ALSO"
.sp
\fBhttp://crypto\&.stanford\&.edu/flashproxy/\fR
-.sp
-\fBhttps://www\&.torproject\&.org/docs/pluggable\-transports\&.html\&.en\fR
.SH "BUGS"
.sp
Please report using \fBhttps://trac\&.torproject\&.org/projects/tor\fR\&.
diff --git a/doc/flashproxy-reg-url.1.txt b/doc/flashproxy-reg-url.1.txt
index 42757c9..5465dfa 100644
--- a/doc/flashproxy-reg-url.1.txt
+++ b/doc/flashproxy-reg-url.1.txt
@@ -53,8 +53,6 @@ SEE ALSO
--------
**http://crypto.stanford.edu/flashproxy/**
-**https://www.torproject.org/docs/pluggable-transports.html.en**
-
BUGS
----
Please report using **https://trac.torproject.org/projects/tor**.
diff --git a/experiments/exercise/exercise.sh b/experiments/exercise/exercise.sh
index efefde7..1f46d96 100755
--- a/experiments/exercise/exercise.sh
+++ b/experiments/exercise/exercise.sh
@@ -26,7 +26,7 @@ PIDS_TO_KILL+=($!)
sleep 20
-"$TOR" ClientTransportPlugin "flashproxy socks4 127.0.0.1:$LOCAL_PORT" UseBridges 1 Bridge "flashproxy 0.0.1.0:1" LearnCircuitBuildTimeout 0 CircuitBuildTimeout 60 &
+"$TOR" ClientTransportPlugin "flashproxy socks4 127.0.0.1:$LOCAL_PORT" UseBridges 1 Bridge "flashproxy 0.0.1.0:1" &
PIDS_TO_KILL+=($!)
sleep 60
diff --git a/facilitator/.gitignore b/facilitator/.gitignore
index 3c413c1..5628824 100644
--- a/facilitator/.gitignore
+++ b/facilitator/.gitignore
@@ -9,9 +9,9 @@
/Makefile.in
# files built by ./configure
-/init.d/facilitator
-/init.d/facilitator-email-poller
-/init.d/facilitator-reg-daemon
+/init.d/fp-facilitator
+/init.d/fp-registrar-email
+/init.d/fp-reg-decryptd
/Makefile
/config.status
/config.log
diff --git a/facilitator/INSTALL b/facilitator/INSTALL
index a68bffa..4b954bb 100644
--- a/facilitator/INSTALL
+++ b/facilitator/INSTALL
@@ -22,8 +22,8 @@ Configure and install.
$ ./configure --localstatedir=/var/local --enable-initscripts && make
# make pre-install install post-install
-This installs facilitator.cgi, facilitator, facilitator-email-poller,
-facilitator-reg-daemon, facilitator-reg, and fac.py to /usr/local/bin.
+This installs fp-registrar.cgi, fp-facilitator, fp-registrar-email,
+fp-reg-decryptd, and fp-reg-decrypt to /usr/local/bin.
It also installs System V init files to /etc/init.d/.
The pre/post-install scripts create a user for the daemon to as, and
diff --git a/facilitator/Makefile.am b/facilitator/Makefile.am
index 268fec4..c1cc6f1 100644
--- a/facilitator/Makefile.am
+++ b/facilitator/Makefile.am
@@ -7,7 +7,7 @@ cgibindir = @cgibindir@
# unfortunately sysvinit does not support having initscripts in /usr/local/etc
# yet, so we have to hard code a path here. :(
initscriptdir = /etc/init.d
-exampledir = $(pkgdatadir)/examples
+exampledir = $(docdir)/examples
appenginedir = $(pkgdatadir)/appengine
pkgconfdir = $(sysconfdir)/flashproxy
appengineconfdir = $(pkgconfdir)/reg-appspot
@@ -16,12 +16,13 @@ PYENV = PYTHONPATH='$(srcdir):$(PYTHONPATH)'; export PYTHONPATH;
# automake PLVs
-dist_bin_SCRIPTS = facilitator facilitator-email-poller facilitator-reg-daemon facilitator-reg
-man1_MANS = doc/facilitator.1 doc/facilitator-email-poller.1 doc/facilitator-reg-daemon.1 doc/facilitator-reg.1
-dist_cgibin_SCRIPTS = facilitator.cgi
+dist_bin_SCRIPTS = fp-facilitator fp-registrar-email fp-reg-decryptd fp-reg-decrypt
+man1_MANS = $(dist_bin_SCRIPTS:%=doc/%.1)
+dist_cgibin_SCRIPTS = fp-registrar.cgi
if DO_INITSCRIPTS
-initscript_SCRIPTS = init.d/facilitator init.d/facilitator-email-poller init.d/facilitator-reg-daemon
-dist_initconf_DATA = default/facilitator default/facilitator-email-poller default/facilitator-reg-daemon
+initscript_names = fp-facilitator fp-registrar-email fp-reg-decryptd
+initscript_SCRIPTS = $(initscript_names:%=init.d/%)
+dist_initconf_DATA = $(initscript_names:%=default/%)
endif
dist_doc_DATA = doc/appspot-howto.txt doc/facilitator-design.txt doc/email-howto.txt doc/http-howto.txt doc/server-howto.txt README
@@ -32,7 +33,7 @@ appengineconf_DATA = appengine/config.go
CLEANFILES = examples/fp-facilitator.conf $(man1_MANS)
EXTRA_DIST = examples/fp-facilitator.conf.in mkman.sh mkman.inc HACKING $(TESTS)
-TESTS = facilitator-test.py
+TESTS = fp-facilitator-test.py
# see http://www.gnu.org/software/automake/manual/html_node/Parallel-Test-Harness.html#index-TEST_005fEXTENSIONS
TEST_EXTENSIONS = .py
PY_LOG_COMPILER = $(PYTHON)
@@ -46,17 +47,25 @@ subst_vars = sed -e 's,[@]cgibindir[@],$(cgibindir),g'
# our own targets
doc/%.1: % mkman.sh mkman.inc Makefile
+# mkdir needed for out-of-source build
+ $(MKDIR_P) $$(dirname "$@")
{ $(PYENV) $(PYTHON) "$<" --help; } \
- | { $(PYENV) ./mkman.sh "$<" $(VERSION) > "$@"; }
+ | { $(PYENV) $(srcdir)/mkman.sh "$<" $(VERSION) > "$@"; }
examples/fp-facilitator.conf: examples/fp-facilitator.conf.in Makefile
# mkdir needed for out-of-source build
- mkdir -p $$(dirname "$@")
+ $(MKDIR_P) $$(dirname "$@")
$(subst_vars) "$<" > "$@"
pylint: $(dist_bin_SCRIPTS)
pylint -E $^
+install-data-local:
+ $(INSTALL_DATA) -m 600 -t $(DESTDIR)$(pkgconfdir) $(srcdir)/examples/reg-email.pass
+
+uninstall-local:
+ rm $(DESTDIR)$(pkgconfdir)/reg-email.pass
+
# The {pre,post}-{install,remove} targets are just given as reference, and
# ought to be separate scripts as part of your distro's installation process.
# They are intentionally not linked to the install target since they require
@@ -107,12 +116,9 @@ install-secrets:
install -m 600 /dev/null ${pkgconfdir}/reg-daemon.key && \
openssl genrsa 2048 | tee ${pkgconfdir}/reg-daemon.key | \
openssl rsa -pubout > ${pkgconfdir}/reg-daemon.pub; }
- test -f ${pkgconfdir}/reg-email.pass || { \
- install -m 600 /dev/null ${pkgconfdir}/reg-email.pass && \
- cat ${exampledir}/reg-email.pass > ${pkgconfdir}/reg-email.pass; }
remove-secrets:
- for i in reg-daemon.key reg-daemon.pub reg-email.pass; do \
+ for i in reg-daemon.key reg-daemon.pub; do \
rm -f ${pkgconfdir}/$$i; \
done
@@ -137,7 +143,7 @@ if DO_INITSCRIPTS
# initscripts use these directories for logs and runtime data
mkdir -p ${localstatedir}/log
mkdir -p ${localstatedir}/run
- for i in facilitator facilitator-email-poller facilitator-reg-daemon; do \
+ for i in ${initscript_names}; do \
update-rc.d $$i defaults; \
invoke-rc.d $$i start; \
done
@@ -146,7 +152,7 @@ endif
remove-daemon:
if DO_INITSCRIPTS
# we don't rm created directories since they might be system-managed
- for i in facilitator facilitator-email-poller facilitator-reg-daemon; do \
+ for i in ${initscript_names}; do \
invoke-rc.d $$i stop; \
update-rc.d $$i remove; \
done
@@ -154,7 +160,7 @@ endif
remove-daemon-data:
if DO_INITSCRIPTS
- for i in facilitator facilitator-email-poller facilitator-reg-daemon; do \
+ for i in ${initscript_names}; do \
rm -f ${localstatedir}/log/$$i.log* \
rm -f ${localstatedir}/run/$$i.pid \
done
diff --git a/facilitator/README b/facilitator/README
index e2fc857..58d8247 100644
--- a/facilitator/README
+++ b/facilitator/README
@@ -10,11 +10,11 @@ The flashproxy config directory is installation-dependant, usually at
/etc/flashproxy or /usr/local/etc/flashproxy. You are strongly
recommended to keep this on encrypted storage.
-The main backends, facilitator and facilitator-reg-daemon, are installed
-as system services, and you should be able to configure them in the
-appropriate place for your system (e.g. /etc/default/facilitator for a
-Debian-based system using initscripts). You probably need to at least
-set RUN_DAEMON=yes to enable the services.
+The main backends, fp-facilitator and fp-reg-decryptd, are
+installed as system services, and you should be able to configure them
+in the normal place for your system (e.g. /etc/default/fp-facilitator
+for a Debian-based system using initscripts). You probably need to at
+least set RUN_DAEMON=yes to enable the services.
Each installation has its own public-private keypair, stored in the
flashproxy config directory. You will need to securely distribute the
diff --git a/facilitator/configure.ac b/facilitator/configure.ac
index 32fbc1f..2f56c1a 100644
--- a/facilitator/configure.ac
+++ b/facilitator/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ([2.68])
-AC_INIT([flashproxy-facilitator], [1.5])
+AC_INIT([flashproxy-facilitator], [1.7])
AM_INIT_AUTOMAKE([-Wall foreign])
AC_ARG_VAR(fpfacilitatoruser, [the user/group for the facilitator to run as])
@@ -42,8 +42,8 @@ AC_PROG_LN_S
AM_PATH_PYTHON
AC_CONFIG_FILES([Makefile
- init.d/facilitator
- init.d/facilitator-email-poller
- init.d/facilitator-reg-daemon])
+ init.d/fp-facilitator
+ init.d/fp-registrar-email
+ init.d/fp-reg-decryptd])
AC_OUTPUT
diff --git a/facilitator/default/facilitator b/facilitator/default/fp-facilitator
similarity index 100%
rename from facilitator/default/facilitator
rename to facilitator/default/fp-facilitator
diff --git a/facilitator/default/facilitator-reg-daemon b/facilitator/default/fp-reg-decryptd
similarity index 100%
rename from facilitator/default/facilitator-reg-daemon
rename to facilitator/default/fp-reg-decryptd
diff --git a/facilitator/default/facilitator-email-poller b/facilitator/default/fp-registrar-email
similarity index 100%
rename from facilitator/default/facilitator-email-poller
rename to facilitator/default/fp-registrar-email
diff --git a/facilitator/doc/appspot-howto.txt b/facilitator/doc/appspot-howto.txt
index 458f1c0..2c59055 100644
--- a/facilitator/doc/appspot-howto.txt
+++ b/facilitator/doc/appspot-howto.txt
@@ -57,7 +57,7 @@ The --no_cookies flag stops authentication cookies from being written
to disk, in ~/.appcfg_cookies. We recommend this for security, since no
long-running services need this password, only the update process above
which is run once. However, if this reasoning doesn't apply to you
-(e.g. if your facilitator-email-poller uses the same account, so that
+(e.g. if your fp-registrar-email uses the same account, so that
the password is already on the disk) *and* you find yourself running
update a lot for some reason, then you may at your own risk omit it for
convenience.
diff --git a/facilitator/doc/email-howto.txt b/facilitator/doc/email-howto.txt
index 9cbfdb6..1e872bd 100644
--- a/facilitator/doc/email-howto.txt
+++ b/facilitator/doc/email-howto.txt
@@ -1,5 +1,5 @@
These are instructions for setting up an email account for use with the
-email-based rendezvous (facilitator-email-poller / flashproxy-reg-email).
+email rendezvous (fp-registrar-email / flashproxy-reg-email).
You are strongly advised to use an email account dedicated for this
purpose. If your email provider supports it, we advise you to use an
@@ -60,16 +60,28 @@ Click "Save Changes".
Enable two-factor authentication. We do this not so much for the
two-factor, but because it allows creating an independent password that
is used only for IMAP and does not have access to the web interface of
-Gmail. Click the email address in the upper right, then "Account". Click
-"Security". By "2-step verification" click "Edit". Click through until
-it lets you set up. The phone number you provided when the account was
-created will be automatically filled in. Choose "Text message (SMS)"
-then click "Send code". Get your text message, type it in, and hit
-"Verify". Uncheck "Trust this computer" on the next screen. Finally
-"Confirm". On the following summary page, click "Show backup codes" and
-save the codes to encrypted storage. Future codes can be generated at
-https://www.google.com/accounts/SmsAuthConfig.
-
-Still on the 2-step summary page, click "Manage application-specific
-passwords". Enter "IMAP" for the name and click "Generate password".
-Now store this in reg-email.pass, as mentioned in the introduction.
+Gmail. Two-factor authentication also enables you to set up a Google
+Authenticator one-time password token and decouple the account from the
+phone number. Click the email address in the upper right, then
+"Account". Click "Security". By "2-step verification" click "Setup".
+Click through until it lets you set up. The phone number you provided
+when the account was created will be automatically filled in. Choose
+"Text message (SMS)" then click "Send code". Get your text message, type
+it in, and hit "Verify". Uncheck "Trust this computer" on the next
+screen. Finally "Confirm".
+
+Now set up a Google Authenticator secret and. Under "Primary way you
+receive codes", click "Switch to app". Choose "BlackBerry" and
+"Continue". Copy the secret key to a file. Use a program such as
+https://github.com/tadeck/onetimepass to generate a verification code
+and click "Verify and Save". Now you can remove the phone number if you
+wish by clicking "Remove" next to it.
+
+Under "Backup codes", click "Print or download", and save the codes to a
+file so you can log in if all else fails.
+
+Still on the 2-step verification page, click the "App-specific
+passwords" tab and the "Manage application-specific passwords" button.
+Under "Select app", select "Custom" and enter "IMAP" for the name. Click
+"Generate". Store the password in reg-email.pass, as mentioned in the
+introduction.
diff --git a/facilitator/doc/facilitator-design.txt b/facilitator/doc/facilitator-design.txt
index 19d5d47..546b07d 100644
--- a/facilitator/doc/facilitator-design.txt
+++ b/facilitator/doc/facilitator-design.txt
@@ -1,23 +1,23 @@
-The main facilitator program is a backend server that is essentially a
-dynamic database of client addresses, as well as helper programs that
+The main fp-facilitator program is a backend server that is essentially
+a dynamic database of client addresses, as well as helper programs that
receive client registrations from the Internet over various means and
pass them to the backend. There are three supported helper rendezvous
methods: HTTP, email, and appspot.
-facilitator-reg is a simple program that forwards its standard input to
-a locally running facilitator-reg-daemon process. It is used by other
-components as a utility, but is also useful for debugging and testing.
+fp-reg-decrypt is a simple program that forwards its standard input to
+a local fp-reg-decryptd process. It is used by other components as a
+utility, but is also useful for debugging and testing.
-facilitator-reg-daemon accepts connections containing encrypted client
+fp-reg-decryptd accepts connections containing encrypted client
registrations and forwards them to the facilitator. It exists as a
process of its own so that only one program requires access to the
facilitator's private key.
The HTTP rendezvous uses an HTTP server and a CGI program. The HTTP
-server is responsible for speaking TLS and invoking the CGI program. The
-CGI program receives client registrations and proxy requests for
+server is responsible for speaking TLS and invoking the CGI program.
+The CGI program receives client registrations and proxy requests for
clients, parses them, and forwards them to the backend. We use Apache 2
-as the HTTP server. The CGI script is facilitator.cgi. Currently this
+as the HTTP server. The CGI script is fp-registrar.cgi. Currently this
is also the only method for accepting browser proxy registrations, so
you must enable this method, otherwise your clients will not be served.
@@ -29,10 +29,10 @@ another service (e.g. reg-appspot), you must use the end-to-end format.
On the client side, you may use flashproxy-reg-url to generate
registration URLs for the end-to-end encrypted format.
-The email rendezvous uses the helper program facilitator-email-poller.
+The email rendezvous uses the helper program fp-registrar-email.
Clients use the flashproxy-reg-email program to send an encrypted
message to a Gmail address. The poller constantly checks for new
-messages and forwards them to facilitator-reg.
+messages and forwards them to fp-reg-decrypt.
The appspot rendezvous uses Google's appengine platform as a proxy for
the HTTP method, either yours or that of another facilitator. It takes
diff --git a/facilitator/doc/http-howto.txt b/facilitator/doc/http-howto.txt
index 478eb3e..28f25f1 100644
--- a/facilitator/doc/http-howto.txt
+++ b/facilitator/doc/http-howto.txt
@@ -1,5 +1,5 @@
These are instructions for how to set up an Apache Web Server for
-handling the HTTP client registration method (facilitator.cgi /
+handling the HTTP client registration method (fp-registrar.cgi /
flashproxy-reg-http / flashproxy-reg-url), as well as for browser
proxies to poll and receive a client to serve.
diff --git a/facilitator/examples/facilitator-relays b/facilitator/examples/facilitator-relays
index 0753387..e9df587 100644
--- a/facilitator/examples/facilitator-relays
+++ b/facilitator/examples/facilitator-relays
@@ -1,7 +1,7 @@
# List some relays that the facilitator will match proxies with.
# Each line contains a transport and an address, separated by space.
# See doc/design.txt for details of the transport syntax.
-#obfs3|websocket 173.255.221.44:9500
-#websocket 173.255.221.44:9901
-#obfs3|websocket [2600:3c01::f03c:91ff:fe93:6cd2]:9500
-#websocket [2600:3c01::f03c:91ff:fe93:6cd2]:9901
+#obfs3|websocket 192.81.135.242:9500
+#websocket 192.81.135.242:9901
+#obfs3|websocket [2600:3c01::f03c:91ff:fe73:b602]:9500
+#websocket [2600:3c01::f03c:91ff:fe73:b602]:9901
diff --git a/facilitator/examples/fp-facilitator.conf.in b/facilitator/examples/fp-facilitator.conf.in
index 4eb98eb..f0e3968 100644
--- a/facilitator/examples/fp-facilitator.conf.in
+++ b/facilitator/examples/fp-facilitator.conf.in
@@ -8,7 +8,7 @@ MaxClients 256
# Update this with your hostname!
ServerName fp-facilitator.example.com
DocumentRoot /dev/null
- ScriptAliasMatch ^(.*) @cgibindir@/facilitator.cgi$1
+ ScriptAliasMatch ^(.*) @cgibindir@/fp-registrar.cgi$1
# Non-Debian distros will need to tweak the log dir too
# Only log errors by default, to protect sensitive information.
diff --git a/facilitator/facilitator b/facilitator/fp-facilitator
similarity index 99%
rename from facilitator/facilitator
rename to facilitator/fp-facilitator
index 35d74be..f5246a9 100755
--- a/facilitator/facilitator
+++ b/facilitator/fp-facilitator
@@ -20,7 +20,7 @@ from flashproxy.util import parse_addr_spec, format_addr, canonical_ip
LISTEN_ADDRESS = "127.0.0.1"
DEFAULT_LISTEN_PORT = 9002
DEFAULT_RELAY_PORT = 9001
-DEFAULT_LOG_FILENAME = "facilitator.log"
+DEFAULT_LOG_FILENAME = "fp-facilitator.log"
# Tell proxies to poll for clients every POLL_INTERVAL seconds.
POLL_INTERVAL = 600
diff --git a/facilitator/facilitator-test.py b/facilitator/fp-facilitator-test.py
similarity index 98%
rename from facilitator/facilitator-test.py
rename to facilitator/fp-facilitator-test.py
index fd4ac88..9de44d3 100755
--- a/facilitator/facilitator-test.py
+++ b/facilitator/fp-facilitator-test.py
@@ -17,7 +17,7 @@ from flashproxy.util import format_addr
import imp
dont_write_bytecode = sys.dont_write_bytecode
sys.dont_write_bytecode = True
-facilitator = imp.load_source("facilitator", os.path.join(os.path.dirname(__file__), "facilitator"))
+facilitator = imp.load_source("fp-facilitator", os.path.join(os.path.dirname(__file__), "fp-facilitator"))
Endpoints = facilitator.Endpoints
parse_relay_file = facilitator.parse_relay_file
sys.dont_write_bytecode = dont_write_bytecode
@@ -207,7 +207,7 @@ class FacilitatorProcTest(unittest.TestCase):
self.relay_file.write("%s %s\n" % (RELAY_TP, format_addr(self.IPV6_RELAY_ADDR)))
self.relay_file.flush()
self.relay_file.seek(0)
- fn = os.path.join(os.path.dirname(__file__), "./facilitator")
+ fn = os.path.join(os.path.dirname(__file__), "./fp-facilitator")
self.process = subprocess.Popen(["python", fn, "-d", "-p", str(FACILITATOR_PORT), "-r", self.relay_file.name, "-l", "/dev/null"])
time.sleep(0.1)
diff --git a/facilitator/facilitator-reg b/facilitator/fp-reg-decrypt
similarity index 91%
rename from facilitator/facilitator-reg
rename to facilitator/fp-reg-decrypt
index 3a3d196..e11a23d 100755
--- a/facilitator/facilitator-reg
+++ b/facilitator/fp-reg-decrypt
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
-Forwards encrypted client registrations to a running facilitator-reg-daemon.
+Forwards encrypted client registrations to a running fp-reg-decryptd.
"""
import getopt
@@ -17,7 +17,7 @@ def usage(f = sys.stdout):
print >> f, """\
Usage: %(progname)s
Reads a base64-encoded encrypted client registration from stdin and
-feeds it to a local facilitator-reg-daemon process. Returns 0 if the
+feeds it to a local fp-reg-decryptd process. Returns 0 if the
registration was successful, 1 otherwise.
-h, --help show this help.
diff --git a/facilitator/facilitator-reg-daemon b/facilitator/fp-reg-decryptd
similarity index 99%
rename from facilitator/facilitator-reg-daemon
rename to facilitator/fp-reg-decryptd
index bba5aab..1db5627 100755
--- a/facilitator/facilitator-reg-daemon
+++ b/facilitator/fp-reg-decryptd
@@ -24,7 +24,7 @@ from M2Crypto import RSA
LISTEN_ADDRESS = "127.0.0.1"
DEFAULT_LISTEN_PORT = 9003
FACILITATOR_ADDR = ("127.0.0.1", 9002)
-DEFAULT_LOG_FILENAME = "facilitator-reg-daemon.log"
+DEFAULT_LOG_FILENAME = "fp-reg-decryptd.log"
# Don't indulge clients for more than this many seconds.
CLIENT_TIMEOUT = 1.0
diff --git a/facilitator/facilitator-email-poller b/facilitator/fp-registrar-email
similarity index 98%
rename from facilitator/facilitator-email-poller
rename to facilitator/fp-registrar-email
index b3b9b14..1f88b20 100755
--- a/facilitator/facilitator-email-poller
+++ b/facilitator/fp-registrar-email
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
-Polls a mailbox for new registrations and forwards them using facilitator-reg.
+Polls a mailbox for new registrations and forwards them using fp-reg-decrypt.
"""
import calendar
@@ -31,7 +31,7 @@ from M2Crypto import SSL
# could maybe do an MX lookup and try to guess the imap server from that.
DEFAULT_IMAP_HOST = "imap.gmail.com"
DEFAULT_IMAP_PORT = 993
-DEFAULT_LOG_FILENAME = "facilitator-email-poller.log"
+DEFAULT_LOG_FILENAME = "fp-registrar-email.log"
POLL_INTERVAL = 60
# Ignore message older than this many seconds old, or newer than this many
@@ -93,7 +93,7 @@ class IMAP4_SSL_REQUIRED(imaplib.IMAP4_SSL):
def usage(f = sys.stdout):
print >> f, """\
Usage: %(progname)s --pass=PASSFILE
-Facilitator-side helper for the facilitator-reg-email rendezvous. Polls
+Facilitator-side helper for the flashproxy-reg-email rendezvous. Polls
an IMAP server for email messages with client registrations, deletes
them, and forwards the registrations to the facilitator.
@@ -291,7 +291,7 @@ def message_ok(msg):
def handle_message(msg):
try:
- if fac.put_reg_proc(["facilitator-reg"], msg.get_payload()):
+ if fac.put_reg_proc(["fp-reg-decrypt"], msg.get_payload()):
log(u"registered client")
else:
log(u"failed to register client")
diff --git a/facilitator/facilitator.cgi b/facilitator/fp-registrar.cgi
similarity index 97%
rename from facilitator/facilitator.cgi
rename to facilitator/fp-registrar.cgi
index 10f4b19..4414f2c 100755
--- a/facilitator/facilitator.cgi
+++ b/facilitator/fp-registrar.cgi
@@ -23,7 +23,7 @@ def exit_error(status):
def send_url_reg(reg):
# Translate from url-safe base64 alphabet to the standard alphabet.
reg = reg.replace('-', '+').replace('_', '/')
- return fac.put_reg_proc(["facilitator-reg"], reg)
+ return fac.put_reg_proc(["fp-reg-decrypt"], reg)
method = os.environ.get("REQUEST_METHOD")
remote_addr = (os.environ.get("REMOTE_ADDR"), None)
@@ -96,7 +96,7 @@ def do_post():
# think that this is technically a violation of the
# application/x-www-form-urlencoded content-type the client likely used, but
# it at least matches the standard multiline registration format used by
- # facilitator-reg-daemon.
+ # fp-reg-decryptd.
try:
regs = list(fac.read_client_registrations(sys.stdin.read(), defhost=remote_addr[0]))
except ValueError:
diff --git a/facilitator/init.d/facilitator.in b/facilitator/init.d/fp-facilitator.in
similarity index 96%
rename from facilitator/init.d/facilitator.in
rename to facilitator/init.d/fp-facilitator.in
index 8ba923f..78779f7 100755
--- a/facilitator/init.d/facilitator.in
+++ b/facilitator/init.d/fp-facilitator.in
@@ -1,6 +1,6 @@
#! /bin/sh
### BEGIN INIT INFO
-# Provides: facilitator
+# Provides: fp-facilitator
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
@@ -16,7 +16,7 @@
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="Flash proxy facilitator"
-NAME=facilitator
+NAME=fp-facilitator
prefix=@prefix@
exec_prefix=@exec_prefix@
@@ -104,7 +104,7 @@ case "$1" in
esac
;;
status)
- status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+ status_of_proc -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $?
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
diff --git a/facilitator/init.d/facilitator-reg-daemon.in b/facilitator/init.d/fp-reg-decryptd.in
similarity index 96%
rename from facilitator/init.d/facilitator-reg-daemon.in
rename to facilitator/init.d/fp-reg-decryptd.in
index aa4afde..464a6c6 100755
--- a/facilitator/init.d/facilitator-reg-daemon.in
+++ b/facilitator/init.d/fp-reg-decryptd.in
@@ -1,6 +1,6 @@
#! /bin/sh
### BEGIN INIT INFO
-# Provides: facilitator-reg-daemon
+# Provides: fp-reg-decryptd
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
@@ -16,7 +16,7 @@
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="Flash proxy local registration daemon"
-NAME=facilitator-reg-daemon
+NAME=fp-reg-decryptd
prefix=@prefix@
exec_prefix=@exec_prefix@
@@ -103,7 +103,7 @@ case "$1" in
esac
;;
status)
- status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+ status_of_proc -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $?
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
diff --git a/facilitator/init.d/facilitator-email-poller.in b/facilitator/init.d/fp-registrar-email.in
similarity index 95%
rename from facilitator/init.d/facilitator-email-poller.in
rename to facilitator/init.d/fp-registrar-email.in
index 02edd08..38540d4 100755
--- a/facilitator/init.d/facilitator-email-poller.in
+++ b/facilitator/init.d/fp-registrar-email.in
@@ -1,6 +1,6 @@
#! /bin/sh
### BEGIN INIT INFO
-# Provides: facilitator-email-poller
+# Provides: fp-registrar-email
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
@@ -16,7 +16,7 @@
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="Flash proxy email rendezvous poller"
-NAME=facilitator-email-poller
+NAME=fp-registrar-email
prefix=@prefix@
exec_prefix=@exec_prefix@
@@ -102,7 +102,7 @@ case "$1" in
esac
;;
status)
- status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+ status_of_proc -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $?
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
diff --git a/flashproxy-client b/flashproxy-client
index 09630b3..05d2fdb 100755
--- a/flashproxy-client
+++ b/flashproxy-client
@@ -3,11 +3,12 @@
The flashproxy client transport plugin.
"""
+import argparse
import BaseHTTPServer
import array
import base64
import cStringIO
-import getopt
+import flashproxy
import os
import os.path
import select
@@ -19,7 +20,8 @@ import threading
import time
import traceback
-from flashproxy.util import parse_addr_spec, addr_family, format_addr
+from flashproxy.util import parse_addr_spec, addr_family, format_addr, safe_str, safe_format_addr
+from flashproxy.reg import DEFAULT_TRANSPORT
from hashlib import sha1
@@ -35,7 +37,6 @@ DEFAULT_LOCAL_PORT_EXTERNAL = 9001
DEFAULT_REMOTE_PORT = 9000
DEFAULT_REGISTER_METHODS = ["appspot", "email", "http"]
DEFAULT_PORT_FORWARDING_HELPER = "tor-fw-helper"
-DEFAULT_TRANSPORT = "websocket"
# We will re-register if we have fewer than this many waiting proxies. The
# facilitator may choose to ignore our requests.
@@ -54,10 +55,7 @@ class options(object):
managed = True
- address_family = socket.AF_UNSPEC
daemonize = False
- facilitator_url = None
- facilitator_pubkey_filename = None
log_filename = None
log_file = sys.stdout
pid_filename = None
@@ -66,79 +64,13 @@ class options(object):
port_forwarding_external = None
register = False
register_commands = []
+
+ # registration options
+ address_family = socket.AF_UNSPEC
transport = DEFAULT_TRANSPORT
safe_logging = True
-
-def usage(f = sys.stdout):
- print >> f, """\
-Usage: %(progname)s --register [LOCAL][:PORT] [REMOTE][:PORT]
-Wait for connections on a local and a remote port. When any pair of connections
-exists, data is ferried between them until one side is closed. By default
-LOCAL is localhost addresses on port %(local_port)d and REMOTE is all addresses
-on port %(remote_port)d.
-
-The local connection acts as a SOCKS4a proxy, but the host and port in the SOCKS
-request are ignored and the local connection is always linked to a remote
-connection.
-
-By default, runs as a managed proxy: informs a parent Tor process of support for
-the "flashproxy" or "websocket" pluggable transport. In managed mode,
-the LOCAL port is chosen arbitrarily instead of defaulting to
-%(local_port)d; however this can be overridden by including a LOCAL port
-in the command. This is the way the program should be invoked in a torrc
-ClientTransportPlugin "exec" line. Use the --external option to run as
-an external proxy that does not interact with Tor.
-
-If any of the --register, --register-addr, or --register-methods options are
-used, then your IP address will be sent to the facilitator so that proxies can
-connect to you. You need to register in some way in order to get any service.
-The --facilitator option allows controlling which facilitator is used; if
-omitted, it uses a public default.
-
- -4 registration helpers use IPv4.
- -6 registration helpers use IPv6.
- --daemon daemonize (Unix only).
- --external be an external proxy (don't interact with Tor using
- environment variables and stdout).
- -f, --facilitator=URL advertise willingness to receive connections to URL.
- --facilitator-pubkey=FILENAME
- encrypt registrations to the given PEM-formatted
- public key (default built-in).
- -h, --help show this help.
- -l, --log FILENAME write log to FILENAME (default stdout).
- --pidfile FILENAME write PID to FILENAME after daemonizing.
- --port-forwarding attempt to forward REMOTE port.
- --port-forwarding-helper=PROGRAM use the given PROGRAM to forward ports
- (default "%(port_forwarding_helper)s"). Implies --port-forwarding.
- --port-forwarding-external=PORT forward the external PORT to REMOTE on
- the local host (default same as REMOTE). Implies
- --port-forwarding.
- -r, --register register with the facilitator.
- --register-addr=ADDR register the given address (in case it differs from
- REMOTE). Implies --register.
- --register-methods=METHOD[,METHOD...]
- register using the given comma-separated list of
- methods. Implies --register. Possible methods are
- appspot email http
- Default is "%(reg_methods)s".
- --transport=TRANSPORT register using the given transport
- (default "%(transport)s").
- --unsafe-logging don't scrub IP addresses from logs.\
-""" % {
- "progname": sys.argv[0],
- "local_port": DEFAULT_LOCAL_PORT_EXTERNAL,
- "remote_port": DEFAULT_REMOTE_PORT,
- "reg_methods": ",".join(DEFAULT_REGISTER_METHODS),
- "port_forwarding_helper": DEFAULT_PORT_FORWARDING_HELPER,
- "transport": DEFAULT_TRANSPORT,
-}
-
-def safe_str(s):
- """Return "[scrubbed]" if options.safe_logging is true, and s otherwise."""
- if options.safe_logging:
- return "[scrubbed]"
- else:
- return s
+ facilitator_url = None
+ facilitator_pubkey_filename = None
log_lock = threading.Lock()
def log(msg):
@@ -146,9 +78,6 @@ def log(msg):
print >> options.log_file, (u"%s %s" % (time.strftime(LOG_DATE_FORMAT), msg)).encode("UTF-8")
options.log_file.flush()
-def safe_format_addr(addr):
- return safe_str(format_addr(addr))
-
def format_sockaddr(sockaddr):
host, port = socket.getnameinfo(sockaddr, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV)
port = int(port)
@@ -969,34 +898,31 @@ def build_register_command(method):
# Maybe the script was read from stdin; in any case don't guess at the directory.
raise ValueError("Can't find executable directory for registration helpers")
- # "common" is options shared by every registration helper.
- common = []
+ if method not in ("http", "appspot", "email"):
+ raise ValueError("Unknown registration method \"%s\"" % method)
+
+ args = []
+
+ # facilitator selection
+ if method == "http":
+ if options.facilitator_url is not None:
+ args += ["-f", options.facilitator_url]
+ else:
+ if options.facilitator_pubkey_filename is not None:
+ args += ["--facilitator-pubkey", options.facilitator_pubkey_filename]
+
+ # options shared by every registration helper.
if options.address_family == socket.AF_INET:
- common += ["-4"]
+ args += ["-4"]
elif options.address_family == socket.AF_INET6:
- common += ["-6"]
+ args += ["-6"]
if options.transport is not None:
- common += ["--transport", options.transport]
+ args += ["--transport", options.transport]
if not options.safe_logging:
- common += ["--unsafe-logging"]
+ args += ["--unsafe-logging"]
- if method == "appspot":
- command = [os.path.join(script_dir, "flashproxy-reg-appspot")] + common
- if options.facilitator_pubkey_filename is not None:
- command += ["--facilitator-pubkey", options.facilitator_pubkey_filename]
- return command
- elif method == "email":
- command = [os.path.join(script_dir, "flashproxy-reg-email")] + common
- if options.facilitator_pubkey_filename is not None:
- command += ["--facilitator-pubkey", options.facilitator_pubkey_filename]
- return command
- elif method == "http":
- command = [os.path.join(script_dir, "flashproxy-reg-http")] + common
- if options.facilitator_url is not None:
- command += ["-f", options.facilitator_url]
- return command
- else:
- raise ValueError("Unknown registration method \"%s\"" % method)
+ prog = os.path.join(script_dir, "flashproxy-reg-%s" % method)
+ return [prog] + args
def pt_escape(s):
result = []
@@ -1070,69 +996,98 @@ def main():
global websocket_pending, socks_pending
global unlinked_locals, unlinked_remotes
- register_addr_spec = None
- register_methods = []
-
- opts, args = getopt.gnu_getopt(sys.argv[1:], "46f:hl:r", [
- "daemon",
- "external",
- "facilitator=",
- "facilitator-pubkey=",
- "help",
- "log=",
- "pidfile=",
- "register",
- "register-addr=",
- "register-methods=",
- "port-forwarding",
- "port-forwarding-helper=",
- "port-forwarding-external=",
- "transport=",
- "unsafe-logging",
- ])
- for o, a in opts:
- if o == "-4":
- options.address_family = socket.AF_INET
- elif o == "-6":
- options.address_family = socket.AF_INET6
- elif o == "--daemon":
- options.daemonize = True
- elif o == "--external":
- options.managed = False
- elif o == "-f" or o == "--facilitator":
- options.facilitator_url = a
- elif o == "--facilitator-pubkey":
- options.facilitator_pubkey_filename = a
- elif o == "-h" or o == "--help":
- usage()
- sys.exit()
- elif o == "-l" or o == "--log":
- options.log_filename = a
- elif o == "--pidfile":
- options.pid_filename = a
- elif o == "-r" or o == "--register":
- options.register = True
- elif o == "--register-addr":
- if register_addr_spec is not None:
- print >> sys.stderr, "%s: only one --register-addr is allowed." % sys.argv[0]
- sys.exit(1)
- options.register = True
- register_addr_spec = a
- elif o == "--register-methods":
- options.register = True
- register_methods.extend(a.split(","))
- elif o == "--port-forwarding":
- options.port_forwarding = True
- elif o == "--port-forwarding-helper":
- options.port_forwarding = True
- options.port_forwarding_helper = a
- elif o == "--port-forwarding-external":
- options.port_forwarding = True
- options.port_forwarding_external = int(a)
- elif o == "--transport":
- options.transport = a
- elif o == "--unsafe-logging":
- options.safe_logging = False
+ parser = argparse.ArgumentParser(
+ usage="%(prog)s --register [OPTIONS] [LOCAL][:PORT] [REMOTE][:PORT]",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="""\
+Wait for connections on a local and a remote port. When any pair of connections
+exists, data is ferried between them until one side is closed.
+
+The local connection acts as a SOCKS4a proxy, but the host and port in the SOCKS
+request are ignored and the local connection is always linked to a remote
+connection.
+
+By default, runs as a managed proxy: informs a parent Tor process of support for
+the "flashproxy" or "websocket" pluggable transport. In managed mode, the LOCAL
+port is chosen arbitrarily instead of the default; this can be overridden by
+including a LOCAL port in the command. This is the way the program should be
+invoked in a torrc ClientTransportPlugin "exec" line. Use the --external option
+to run as an external proxy that does not interact with Tor.
+
+If any of the --register, --register-addr, or --register-methods options are
+used, then your IP address will be sent to the facilitator so that proxies can
+connect to you. You need to register in some way in order to get any service.
+The --facilitator option allows controlling which facilitator is used; if
+omitted, it uses a public default.""",
+ epilog="""\
+The -4, -6, --unsafe-logging, --transport and --facilitator-pubkey options are
+propagated to the child registration helpers. For backwards compatilibility,
+the --facilitator option is also propagated to the http registration helper.
+If you need to pass more options, use TODO #9976.""")
+ flashproxy.util.add_module_opts(parser)
+ flashproxy.reg.add_module_opts(parser)
+ parser.add_argument("-f", "--facilitator", metavar="URL",
+ help="register with the facilitator at this URL, default %(default)s. "
+ "This is passed to the http registration ONLY.")
+ # specific opts and args
+ parser.add_argument("--daemon",
+ help="daemonize (Unix only).", action="store_true")
+ parser.add_argument("--external",
+ help="be an external (non-managed) proxy - don't interact with Tor "
+ "using environment variables and stdout.", action="store_true")
+ parser.add_argument("-l", "--log", metavar="FILENAME",
+ help="write log to FILENAME (default stderr).")
+ parser.add_argument("--pidfile", metavar="FILENAME",
+ help="write PID to FILENAME after daemonizing.")
+ parser.add_argument("--port-forwarding",
+ help="attempt to forward REMOTE port.", action="store_true")
+ parser.add_argument("--port-forwarding-helper", metavar="PROGRAM",
+ help="use the given PROGRAM to forward ports, default %s. Implies "
+ "--port-forwarding." % DEFAULT_PORT_FORWARDING_HELPER)
+ parser.add_argument("--port-forwarding-external", metavar="PORT",
+ help="forward the external PORT to REMOTE on the local host, default "
+ "same as the REMOTE. Implies --port-forwarding.", type=int)
+ parser.add_argument("-r", "--register",
+ help="register with the facilitator.", action="store_true")
+ parser.add_argument("--register-addr", metavar="ADDR",
+ help="register the given address (in case it differs from REMOTE). "
+ "Implies --register.")
+ parser.add_argument("--register-methods", metavar="METHOD[,METHOD...]",
+ help="register using the given comma-separated list of methods. "
+ "Implies --register. Possible methods are appspot,email,http. Default "
+ "is %s." % ",".join(DEFAULT_REGISTER_METHODS),
+ type=lambda x: None if x is None else x.split(",") if x else [])
+ parser.add_argument("local_addr", metavar="LOCAL:PORT",
+ help="local addr+port to listen on, default all localhost addresses on "
+ "port %s. In managed mode, the port is chosen arbitrarily if not given."
+ % DEFAULT_LOCAL_PORT_EXTERNAL, default="", nargs="?")
+ parser.add_argument("remote_addr", metavar="REMOTE:PORT",
+ help="remote addr+port to listen on, default all addresses on port %s"
+ % DEFAULT_REMOTE_PORT, default="", nargs="?")
+
+ ns = parser.parse_args(sys.argv[1:])
+ # set registration options
+ options.address_family = ns.address_family
+ options.transport = ns.transport
+ options.safe_logging = not ns.unsafe_logging
+ options.facilitator_url = ns.facilitator
+ options.facilitator_pubkey_filename = ns.facilitator_pubkey
+
+ options.managed = not ns.external
+
+ # do registration if any of the register options were set
+ do_register = (ns.register or
+ ns.register_addr is not None or
+ ns.register_methods is not None)
+
+ # do port forwarding if any of the port-forwarding options were set
+ do_port_forwarding = (ns.port_forwarding or
+ ns.port_forwarding_helper is not None or
+ ns.port_forwarding_external is not None)
+
+ options.log_filename = ns.log
+ options.daemonize = ns.daemon
+ options.pid_filename = ns.pidfile
if options.log_filename:
options.log_file = open(options.log_filename, "a")
@@ -1152,18 +1107,8 @@ def main():
default_local_port = DEFAULT_LOCAL_PORT_EXTERNAL
default_remote_port = DEFAULT_REMOTE_PORT
- if len(args) == 0:
- local_addr = ("", default_local_port)
- remote_addr = ("", default_remote_port)
- elif len(args) == 1:
- local_addr = parse_addr_spec(args[0], defhost="", defport=default_local_port)
- remote_addr = ("", default_remote_port)
- elif len(args) == 2:
- local_addr = parse_addr_spec(args[0], defhost="", defport=default_local_port)
- remote_addr = parse_addr_spec(args[1], defhost="", defport=default_remote_port)
- else:
- usage(sys.stderr)
- sys.exit(1)
+ local_addr = parse_addr_spec(ns.local_addr, defhost="", defport=default_local_port)
+ remote_addr = parse_addr_spec(ns.remote_addr, defhost="", defport=default_remote_port)
if local_addr[0]:
options.local_addrs.append(local_addr)
@@ -1180,11 +1125,20 @@ def main():
if socket.has_ipv6:
options.remote_addrs.append(("::", remote_addr[1]))
+ # Determine registration info if requested.
+ options.register = do_register
+ register_addr_spec = ns.register_addr
+ register_methods = ns.register_methods
+
if not register_methods:
register_methods = DEFAULT_REGISTER_METHODS
for method in register_methods:
options.register_commands.append(build_register_command(method))
+ options.port_forwarding = do_port_forwarding
+ options.port_forwarding_helper = ns.port_forwarding_helper or DEFAULT_PORT_FORWARDING_HELPER
+ options.port_forwarding_external = ns.port_forwarding_external
+
# Remote sockets, accepting remote WebSocket connections from proxies.
remote_listen = []
for addr in options.remote_addrs:
diff --git a/flashproxy-reg-appspot b/flashproxy-reg-appspot
index 134e9ff..373ffb2 100755
--- a/flashproxy-reg-appspot
+++ b/flashproxy-reg-appspot
@@ -1,96 +1,29 @@
#!/usr/bin/env python
"""Register with a facilitator through Google App Engine."""
-import getopt
+import argparse
+import flashproxy
import httplib
-import os
import socket
-import subprocess
import sys
import urlparse
import urllib2
-from flashproxy.keys import PIN_GOOGLE_CA_CERT, PIN_GOOGLE_PUBKEY_SHA1, check_certificate_pin, temp_cert
-from flashproxy.util import parse_addr_spec, format_addr
+from flashproxy.keys import PIN_GOOGLE_CA_CERT, PIN_GOOGLE_PUBKEY_SHA1, check_certificate_pin, ensure_M2Crypto, temp_cert
+from flashproxy.reg import build_reg_b64enc
+from flashproxy.util import parse_addr_spec, safe_str, safe_format_addr
try:
from M2Crypto import SSL
except ImportError:
# Defer the error reporting so that --help works even without M2Crypto.
- SSL = None
-
-DEFAULT_REMOTE_ADDRESS = ""
-DEFAULT_REMOTE_PORT = 9000
-DEFAULT_TRANSPORT = "websocket"
+ pass
# The domain to which requests appear to go.
FRONT_DOMAIN = "www.google.com"
# The value of the Host header within requests.
TARGET_DOMAIN = "fp-reg-a.appspot.com"
-FLASHPROXY_REG_URL = "flashproxy-reg-url"
-
-class options(object):
- address_family = socket.AF_UNSPEC
- use_certificate_pin = True
- facilitator_pubkey_filename = None
- transport = DEFAULT_TRANSPORT
- safe_logging = True
-
-def usage(f = sys.stdout):
- print >> f, """\
-Usage: %(progname)s [REMOTE][:PORT]
-Register with a flash proxy facilitator through a Google App Engine app.
-By default the remote address registered is "%(remote_addr)s" (the
-external IP address is guessed).
-
- -4 name lookups use only IPv4.
- -6 name lookups use only IPv6.
- --disable-pin don't check server public key against a known pin.
- --facilitator-pubkey=FILENAME
- encrypt registrations to the given PEM-formatted
- public key (default built-in).
- -h, --help show this help.
- --transport=TRANSPORT register using the given transport
- (default "%(transport)s").
- --unsafe-logging don't scrub IP addresses from logs.\
-""" % {
- "progname": sys.argv[0],
- "remote_addr": format_addr((DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)),
- "transport": DEFAULT_TRANSPORT,
-}
-
-def safe_str(s):
- """Return "[scrubbed]" if options.safe_logging is true, and s otherwise."""
- if options.safe_logging:
- return "[scrubbed]"
- else:
- return s
-
-def safe_format_addr(addr):
- return safe_str(format_addr(addr))
-
-def generate_url(addr):
- if getattr(sys, "frozen", False):
- script_dir = os.path.dirname(sys.executable)
- else:
- script_dir = sys.path[0]
- if not script_dir:
- # Maybe the script was read from stdin; in any case don't guess at the directory.
- raise ValueError("Can't find executable directory for registration helpers")
- command = [os.path.join(script_dir, FLASHPROXY_REG_URL)]
- command += ["-f", urlparse.urlunparse(("https", FRONT_DOMAIN, "/", "", "", ""))]
- if options.transport is not None:
- command += ["--transport", options.transport]
- if options.facilitator_pubkey_filename is not None:
- command += ["--facilitator-pubkey", options.facilitator_pubkey_filename]
- command.append(format_addr(addr))
- p = subprocess.Popen(command, stdout=subprocess.PIPE)
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- raise ValueError("%s exited with status %d" % (FLASHPROXY_REG_URL, p.returncode))
- return stdout.strip()
-
# Like socket.create_connection in that it tries resolving different address
# families, but doesn't connect the socket.
def create_socket(address, timeout = None):
@@ -129,8 +62,7 @@ class PinHTTPSConnection(httplib.HTTPSConnection):
self.sock = SSL.Connection(ctx, sock)
self.sock.connect((self.host, self.port))
- if options.use_certificate_pin:
- check_certificate_pin(self.sock, PIN_GOOGLE_PUBKEY_SHA1)
+ check_certificate_pin(self.sock, PIN_GOOGLE_PUBKEY_SHA1)
class PinHTTPSHandler(urllib2.HTTPSHandler):
def https_open(self, req):
@@ -149,54 +81,20 @@ def get_external_ip():
finally:
f.close()
-opt, args = getopt.gnu_getopt(sys.argv[1:], "46h", [
- "disable-pin",
- "facilitator-pubkey=",
- "help",
- "transport=",
- "unsafe-logging",
-])
-for o, a in opt:
- if o == "-4":
- options.address_family = socket.AF_INET
- elif o == "-6":
- options.address_family = socket.AF_INET6
- elif o == "--disable-pin":
- options.use_certificate_pin = False
- elif o == "--facilitator-pubkey":
- options.facilitator_pubkey_filename = a
- elif o == "-h" or o == "--help":
- usage()
- sys.exit()
- elif o == "--transport":
- options.transport = a
- elif o == "--unsafe-logging":
- options.safe_logging = False
-
-if len(args) == 0:
- remote_addr = (DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)
-elif len(args) == 1:
- remote_addr = parse_addr_spec(args[0], DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)
-else:
- usage(sys.stderr)
- sys.exit(1)
-
-if SSL is None:
- print >> sys.stderr, """\
-This program requires the M2Crypto library, which is not installed.
-
-You can install it using one of the packages at
-http://chandlerproject.org/Projects/MeTooCrypto#Downloads.
+parser = argparse.ArgumentParser(
+ usage="%(prog)s [OPTIONS] [REMOTE][:PORT]",
+ description="Register with a facilitator through a Google App Engine app. "
+ "If only the external port is given, the remote server guesses our "
+ "external address.")
+flashproxy.util.add_module_opts(parser)
+flashproxy.keys.add_module_opts(parser)
+flashproxy.reg.add_registration_args(parser)
-On Debian-like systems, use the command "apt-get install python-m2crypto".\
-"""
- sys.exit(1)
+options = parser.parse_args(sys.argv[1:])
+flashproxy.util.enforce_address_family(options.address_family)
+remote_addr = options.remote_addr
-if options.address_family != socket.AF_UNSPEC:
- getaddrinfo = socket.getaddrinfo
- def getaddrinfo_replacement(host, port, family, *args, **kwargs):
- return getaddrinfo(host, port, options.address_family, *args, **kwargs)
- socket.getaddrinfo = getaddrinfo_replacement
+ensure_M2Crypto()
if not remote_addr[0]:
try:
@@ -217,9 +115,10 @@ if not remote_addr[0]:
sys.exit(1)
try:
- url = generate_url(remote_addr)
+ reg = build_reg_b64enc(remote_addr, options.transport, urlsafe=True)
+ url = urlparse.urljoin(urlparse.urlunparse(("https", FRONT_DOMAIN, "/", "", "", "")), "reg/" + reg)
except Exception, e:
- print >> sys.stderr, "Error running %s: %s" % (FLASHPROXY_REG_URL, str(e))
+ print >> sys.stderr, "Error generating URL: %s" % str(e)
sys.exit(1)
try:
diff --git a/flashproxy-reg-email b/flashproxy-reg-email
index 6309cec..d5a7b26 100755
--- a/flashproxy-reg-email
+++ b/flashproxy-reg-email
@@ -1,168 +1,60 @@
#!/usr/bin/env python
"""Register with a facilitator using the email method."""
-import getopt
+import argparse
+import flashproxy
import os
import re
import smtplib
-import socket
import sys
-import urllib
-from flashproxy.keys import PIN_GOOGLE_CA_CERT, PIN_GOOGLE_PUBKEY_SHA1, DEFAULT_FACILITATOR_PUBKEY_PEM, check_certificate_pin, temp_cert
-from flashproxy.util import parse_addr_spec, format_addr
+from flashproxy.keys import PIN_GOOGLE_CA_CERT, PIN_GOOGLE_PUBKEY_SHA1, check_certificate_pin, ensure_M2Crypto, temp_cert
+from flashproxy.reg import build_reg_b64enc
+from flashproxy.util import parse_addr_spec, format_addr, safe_format_addr
try:
- from M2Crypto import BIO, RSA, SSL
+ from M2Crypto import SSL
except ImportError:
# Defer the error reporting so that --help works even without M2Crypto.
- BIO = None
- RSA = None
- SSL = None
+ pass
-DEFAULT_REMOTE_ADDRESS = ""
-DEFAULT_REMOTE_PORT = 9000
DEFAULT_EMAIL_ADDRESS = "flashproxyreg.a at gmail.com"
# dig MX gmail.com
-DEFAULT_SMTP_HOST = "gmail-smtp-in.l.google.com"
-DEFAULT_SMTP_PORT = 25
-DEFAULT_TRANSPORT = "websocket"
+DEFAULT_SMTP = ("gmail-smtp-in.l.google.com", 25)
# Use this to prevent Python smtplib from guessing and leaking our hostname.
EHLO_FQDN = "[127.0.0.1]"
FROM_EMAIL_ADDRESS = "nobody at localhost"
-class options(object):
- remote_addr = None
-
- address_family = socket.AF_UNSPEC
- debug = False
- use_certificate_pin = True
- email_addr = None
- facilitator_pubkey_filename = None
- smtp_addr = None
- transport = DEFAULT_TRANSPORT
- safe_logging = True
-
-def usage(f = sys.stdout):
- print >> f, """\
-Usage: %(progname)s [REMOTE][:PORT]
-Register with a flash proxy facilitator through email. Makes a STARTTLS
-connection to an SMTP server and sends mail with a client IP address to a
-designated address. By default the remote address registered is
-"%(remote_addr)s" (the external IP address is guessed).
-
-Using an SMTP server or email address other than the defaults will not work
-unless you have made special arrangements to connect them to a facilitator.
-
-This program requires the M2Crypto library for Python.
-
- -4 name lookups use only IPv4.
- -6 name lookups use only IPv6.
- -d, --debug enable debugging output (Python smtplib messages).
- --disable-pin don't check server public key against a known pin.
- -e, --email=ADDRESS send mail to ADDRESS (default "%(email_addr)s").
- --facilitator-pubkey=FILENAME
- encrypt registrations to the given PEM-formatted
- public key (default built-in).
- -h, --help show this help.
- -s, --smtp=HOST[:PORT] use the given SMTP server
- (default "%(smtp_addr)s").
- --transport=TRANSPORT register using the given transport
- (default "%(transport)s").
- --unsafe-logging don't scrub IP addresses from logs.\
-""" % {
- "progname": sys.argv[0],
- "remote_addr": format_addr((DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)),
- "email_addr": DEFAULT_EMAIL_ADDRESS,
- "smtp_addr": format_addr((DEFAULT_SMTP_HOST, DEFAULT_SMTP_PORT)),
- "transport": DEFAULT_TRANSPORT,
-}
-
-def safe_str(s):
- """Return "[scrubbed]" if options.safe_logging is true, and s otherwise."""
- if options.safe_logging:
- return "[scrubbed]"
- else:
- return s
-
-def safe_format_addr(addr):
- return safe_str(format_addr(addr))
-
-def build_reg(addr, transport):
- return urllib.urlencode((
- ("client", format_addr(addr)),
- ("client-transport", transport),
- ))
-
-def get_facilitator_pubkey():
- if options.facilitator_pubkey_filename is not None:
- return RSA.load_pub_key(options.facilitator_pubkey_filename)
- else:
- return RSA.load_pub_key_bio(BIO.MemoryBuffer(DEFAULT_FACILITATOR_PUBKEY_PEM))
-
-options.email_addr = DEFAULT_EMAIL_ADDRESS
-options.smtp_addr = (DEFAULT_SMTP_HOST, DEFAULT_SMTP_PORT)
-
-opts, args = getopt.gnu_getopt(sys.argv[1:], "46de:hs:", [
- "debug",
- "disable-pin",
- "email=",
- "facilitator-pubkey=",
- "help",
- "smtp=",
- "transport=",
- "unsafe-logging",
-])
-for o, a in opts:
- if o == "-4":
- options.address_family = socket.AF_INET
- elif o == "-6":
- options.address_family = socket.AF_INET6
- elif o == "-d" or o == "--debug":
- options.debug = True
- elif o == "--disable-pin":
- options.use_certificate_pin = False
- elif o == "-e" or o == "--email":
- options.email_addr = a
- elif o == "--facilitator-pubkey":
- options.facilitator_pubkey_filename = a
- elif o == "-h" or o == "--help":
- usage()
- sys.exit()
- elif o == "-s" or o == "--smtp":
- options.smtp_addr = parse_addr_spec(a, DEFAULT_SMTP_HOST, DEFAULT_SMTP_PORT)
- elif o == "--transport":
- options.transport = a
- elif o == "--unsafe-logging":
- options.safe_logging = False
-
-if len(args) == 0:
- options.remote_addr = (DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)
-elif len(args) == 1:
- options.remote_addr = parse_addr_spec(args[0], DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)
-else:
- usage(sys.stderr)
- sys.exit(1)
-
-if SSL is None:
- print >> sys.stderr, """\
-This program requires the M2Crypto library, which is not installed.
-
-You can install it using one of the packages at
-http://chandlerproject.org/Projects/MeTooCrypto#Downloads.
-
-On Debian-like systems, use the command "apt-get install python-m2crypto".\
-"""
- sys.exit(1)
-
-if options.address_family != socket.AF_UNSPEC:
- getaddrinfo = socket.getaddrinfo
- def getaddrinfo_replacement(host, port, family, *args, **kwargs):
- return getaddrinfo(host, port, options.address_family, *args, **kwargs)
- socket.getaddrinfo = getaddrinfo_replacement
-
-smtp = smtplib.SMTP(options.smtp_addr[0], options.smtp_addr[1], EHLO_FQDN)
+parser = argparse.ArgumentParser(
+ usage="%(prog)s [OPTIONS] [REMOTE][:PORT]",
+ description="Register with a flash proxy facilitator through email. Makes "
+ "a STARTTLS connection to an SMTP server and sends mail with a client IP "
+ "address to a designated address. If only the external port is given, the "
+ "external address is guessed from the SMTP EHLO response.",
+ epilog="Using an SMTP server or email address other than the defaults will "
+ "not work unless you have made special arrangements to connect them to a "
+ "facilitator.")
+flashproxy.util.add_module_opts(parser)
+flashproxy.keys.add_module_opts(parser)
+flashproxy.reg.add_registration_args(parser)
+# specific opts
+parser.add_argument("-e", "--email", metavar="ADDRESS",
+ help="send mail to ADDRESS, default %(default)s.",
+ default=DEFAULT_EMAIL_ADDRESS)
+parser.add_argument("-s", "--smtp", metavar="HOST[:PORT]",
+ help="use the given SMTP server, default %s." % format_addr(DEFAULT_SMTP),
+ default="", type=lambda x: parse_addr_spec(x, *DEFAULT_SMTP))
+parser.add_argument("-d", "--debug",
+ help="enable debugging output (Python smtplib messages).",
+ action="store_true")
+
+options = parser.parse_args(sys.argv[1:])
+flashproxy.util.enforce_address_family(options.address_family)
+
+ensure_M2Crypto()
+
+smtp = smtplib.SMTP(options.smtp[0], options.smtp[1], EHLO_FQDN)
if options.debug:
smtp.set_debuglevel(1)
@@ -189,8 +81,7 @@ try:
smtp.sock.connect_ssl()
smtp.file = smtp.sock.makefile()
- if options.use_certificate_pin:
- check_certificate_pin(smtp.sock, PIN_GOOGLE_PUBKEY_SHA1)
+ check_certificate_pin(smtp.sock, PIN_GOOGLE_PUBKEY_SHA1)
smtp.ehlo(EHLO_FQDN)
if not options.remote_addr[0]:
@@ -204,21 +95,18 @@ try:
spec = "[" + spec + "]"
options.remote_addr = parse_addr_spec(spec, *options.remote_addr)
- body_plain = build_reg(options.remote_addr, options.transport)
- rsa = get_facilitator_pubkey()
- body_crypt = rsa.public_encrypt(body_plain, RSA.pkcs1_oaep_padding)
- body = body_crypt.encode("base64")
+ body = build_reg_b64enc(options.remote_addr, options.transport)
# Add a random subject to keep Gmail from threading everything.
rand_string = os.urandom(5).encode("hex")
- smtp.sendmail(options.email_addr, options.email_addr, """\
+ smtp.sendmail(options.email, options.email, """\
To: %(to_addr)s\r
From: %(from_addr)s\r
Subject: client reg %(rand_string)s\r
\r
%(body)s
""" % {
- "to_addr": options.email_addr,
+ "to_addr": options.email,
"from_addr": FROM_EMAIL_ADDRESS,
"rand_string": rand_string,
"body": body,
@@ -228,4 +116,4 @@ except Exception, e:
print >> sys.stderr, "Failed to register: %s" % str(e)
sys.exit(1)
-print "Registered \"%s\" with %s." % (safe_format_addr(options.remote_addr), options.email_addr)
+print "Registered \"%s\" with %s." % (safe_format_addr(options.remote_addr), options.email)
diff --git a/flashproxy-reg-http b/flashproxy-reg-http
index 9f85570..afb3b5c 100755
--- a/flashproxy-reg-http
+++ b/flashproxy-reg-http
@@ -1,105 +1,37 @@
#!/usr/bin/env python
"""Register with a facilitator using the HTTP method."""
-import getopt
-import socket
+import argparse
+import flashproxy
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/"
-DEFAULT_TRANSPORT = "websocket"
-
-class options(object):
- remote_addr = None
-
- address_family = socket.AF_UNSPEC
- facilitator_url = None
- transport = DEFAULT_TRANSPORT
- safe_logging = True
-
-def usage(f = sys.stdout):
- print >> f, """\
-Usage: %(progname)s [REMOTE][:PORT]
-Register with a flash proxy facilitator using an HTTP POST. By default the
-remote address registered is "%(remote_addr)s".
-
- -4 name lookups use only IPv4.
- -6 name lookups use only IPv6.
- -f, --facilitator=URL register with the given facilitator
- (default "%(fac_url)s").
- -h, --help show this help.
- --transport=TRANSPORT register using the given transport
- (default "%(transport)s").
- --unsafe-logging don't scrub IP addresses from logs.\
-""" % {
- "progname": sys.argv[0],
- "fac_url": DEFAULT_FACILITATOR_URL,
- "remote_addr": format_addr((DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)),
- "transport": DEFAULT_TRANSPORT,
-}
-
-def safe_str(s):
- """Return "[scrubbed]" if options.safe_logging is true, and s otherwise."""
- if options.safe_logging:
- return "[scrubbed]"
- else:
- return s
-
-def safe_format_addr(addr):
- return safe_str(format_addr(addr))
-
-def build_reg(addr, transport):
- return urllib.urlencode((
- ("client", format_addr(addr)),
- ("client-transport", transport),
- ))
-
-options.facilitator_url = DEFAULT_FACILITATOR_URL
-options.remote_addr = (DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)
-
-opts, args = getopt.gnu_getopt(sys.argv[1:], "46f:h", [
- "facilitator=",
- "help",
- "transport=",
- "unsafe-logging",
-])
-for o, a in opts:
- if o == "-4":
- options.address_family = socket.AF_INET
- elif o == "-6":
- options.address_family = socket.AF_INET6
- elif o == "-f" or o == "--facilitator":
- options.facilitator_url = a
- elif o == "-h" or o == "--help":
- usage()
- sys.exit()
- elif o == "--transport":
- options.transport = a
- elif o == "--unsafe-logging":
- options.safe_logging = False
-
-if len(args) == 0:
- pass
-elif len(args) == 1:
- options.remote_addr = parse_addr_spec(args[0], DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)
-else:
- usage(sys.stderr)
- sys.exit(1)
-
-if options.address_family != socket.AF_UNSPEC:
- getaddrinfo = socket.getaddrinfo
- def getaddrinfo_replacement(host, port, family, *args, **kwargs):
- return getaddrinfo(host, port, options.address_family, *args, **kwargs)
- socket.getaddrinfo = getaddrinfo_replacement
+from flashproxy.util import format_addr, parse_addr_spec, safe_format_addr
+from flashproxy.reg import DEFAULT_FACILITATOR_URL, DEFAULT_REMOTE, DEFAULT_TRANSPORT, build_reg
+
+parser = argparse.ArgumentParser(
+ usage="%(prog)s [OPTIONS] [REMOTE][:PORT]",
+ description="Register with a flash proxy facilitator using an HTTP POST. "
+ "If only the external port is given, the remote server guesses our "
+ "external address.")
+flashproxy.util.add_module_opts(parser)
+parser.add_argument("--transport", metavar="TRANSPORT",
+ help="register using the given transport, default %(default)s.",
+ default=DEFAULT_TRANSPORT)
+parser.add_argument("remote_addr", metavar="ADDR:PORT",
+ help="external addr+port to register, default %s" %
+ format_addr(DEFAULT_REMOTE), default="", nargs="?",
+ type=lambda x: parse_addr_spec(x, *DEFAULT_REMOTE))
+parser.add_argument("-f", "--facilitator", metavar="URL",
+ help="register with the given facilitator, default %(default)s.",
+ default=DEFAULT_FACILITATOR_URL)
+
+options = parser.parse_args(sys.argv[1:])
+flashproxy.util.enforce_address_family(options.address_family)
body = build_reg(options.remote_addr, options.transport)
try:
- http = urllib2.urlopen(options.facilitator_url, body, 10)
+ http = urllib2.urlopen(options.facilitator, body, 10)
except urllib2.HTTPError, e:
print >> sys.stderr, "Status code was %d, not 200" % e.code
sys.exit(1)
@@ -111,4 +43,4 @@ except Exception, e:
sys.exit(1)
http.close()
-print "Registered \"%s\" with %s." % (safe_format_addr(options.remote_addr), options.facilitator_url)
+print "Registered \"%s\" with %s." % (safe_format_addr(options.remote_addr), options.facilitator)
diff --git a/flashproxy-reg-url b/flashproxy-reg-url
index 4685f28..e73b035 100755
--- a/flashproxy-reg-url
+++ b/flashproxy-reg-url
@@ -1,107 +1,30 @@
#!/usr/bin/env python
"""Register with a facilitator using an indirect URL."""
-import base64
-import getopt
+import argparse
+import flashproxy
import sys
-import urllib
import urlparse
-from flashproxy.keys import DEFAULT_FACILITATOR_PUBKEY_PEM
-from flashproxy.util import parse_addr_spec, format_addr
+from flashproxy.keys import ensure_M2Crypto
+from flashproxy.reg import DEFAULT_FACILITATOR_URL, build_reg_b64enc
-try:
- from M2Crypto import BIO, RSA
-except ImportError:
- # Defer the error reporting so that --help works even without M2Crypto.
- RSA = None
+parser = argparse.ArgumentParser(
+ usage="%(prog)s [OPTIONS] REMOTE[:PORT]",
+ description="Print a URL, which, when retrieved, will cause the input "
+ "client address to be registered with the flash proxy facilitator.")
+flashproxy.reg.add_registration_args(parser)
+parser.add_argument("-f", "--facilitator", metavar="URL",
+ help="register with the given facilitator, default %(default)s.",
+ default=DEFAULT_FACILITATOR_URL)
-DEFAULT_REMOTE_ADDRESS = ""
-DEFAULT_REMOTE_PORT = 9000
-DEFAULT_FACILITATOR_URL = "https://fp-facilitator.org/"
-DEFAULT_TRANSPORT = "websocket"
+options = parser.parse_args(sys.argv[1:])
-class options(object):
- facilitator_url = None
- facilitator_pubkey_filename = None
- transport = DEFAULT_TRANSPORT
+ensure_M2Crypto()
-def usage(f = sys.stdout):
- print >> f, """\
-Usage: %(progname)s REMOTE[:PORT]
-Print a URL, which, when retrieved, will cause the client address
-REMOTE[:PORT] to be registered with the flash proxy facilitator. The
-default PORT is %(port)d.
-
- -f, --facilitator=URL register with the given facilitator
- (default "%(fac_url)s").
- --facilitator-pubkey=FILENAME
- encrypt registrations to the given PEM-formatted
- public key (default built-in).
- -h, --help show this help.
- --transport=TRANSPORT register using the given transport
- (default "%(transport)s").\
-""" % {
- "progname": sys.argv[0],
- "fac_url": DEFAULT_FACILITATOR_URL,
- "port": DEFAULT_REMOTE_PORT,
- "transport": DEFAULT_TRANSPORT,
-}
-
-def build_reg(addr, transport):
- return urllib.urlencode((
- ("client", format_addr(addr)),
- ("client-transport", transport),
- ))
-
-def get_facilitator_pubkey():
- if options.facilitator_pubkey_filename is not None:
- return RSA.load_pub_key(options.facilitator_pubkey_filename)
- else:
- return RSA.load_pub_key_bio(BIO.MemoryBuffer(DEFAULT_FACILITATOR_PUBKEY_PEM))
-
-options.facilitator_url = DEFAULT_FACILITATOR_URL
-
-opt, args = getopt.gnu_getopt(sys.argv[1:], "f:h", [
- "facilitator=",
- "facilitator-pubkey=",
- "help",
- "transport=",
-])
-for o, a in opt:
- if o == "-f" or o == "--facilitator":
- options.facilitator_url = a
- elif o == "--facilitator-pubkey":
- options.facilitator_pubkey_filename = a
- elif o == "-h" or o == "--help":
- usage()
- sys.exit()
- elif o == "--transport":
- options.transport = a
-
-if len(args) != 1:
- usage(sys.stderr)
- sys.exit(1)
-
-remote_addr = parse_addr_spec(args[0], DEFAULT_REMOTE_ADDRESS, DEFAULT_REMOTE_PORT)
-if not remote_addr[0]:
+if not options.remote_addr[0]:
print >> sys.stderr, "An IP address (not just a port) is required."
sys.exit(1)
-if RSA is None:
- print >> sys.stderr, """\
-This program requires the M2Crypto library, which is not installed.
-
-You can install it using one of the packages at
-http://chandlerproject.org/Projects/MeTooCrypto#Downloads.
-
-On Debian-like systems, use the command "apt-get install python-m2crypto".\
-"""
- sys.exit(1)
-
-reg_plain = build_reg(remote_addr, options.transport)
-rsa = get_facilitator_pubkey()
-reg_crypt = rsa.public_encrypt(reg_plain, RSA.pkcs1_oaep_padding)
-reg = base64.urlsafe_b64encode(reg_crypt)
-
-print urlparse.urljoin(options.facilitator_url, "reg/" + reg)
+reg = build_reg_b64enc(options.remote_addr, options.transport, urlsafe=True)
+print urlparse.urljoin(options.facilitator, "reg/" + reg)
diff --git a/flashproxy/keys.py b/flashproxy/keys.py
index 08ffc46..8c60dc0 100644
--- a/flashproxy/keys.py
+++ b/flashproxy/keys.py
@@ -1,9 +1,32 @@
+import base64
import errno
import os
+import sys
import tempfile
from hashlib import sha1
+try:
+ import M2Crypto
+ from M2Crypto import BIO, RSA
+except ImportError:
+ # Defer the error so that the main program gets a chance to print help text
+ M2Crypto = None
+
+class options(object):
+ disable_pin = True
+
+def add_module_opts(parser):
+ parser.add_argument("--disable-pin", help="disable all certificate pinning "
+ "checks", action="store_true",)
+
+ old_parse = parser.parse_args
+ def parse_args(namespace):
+ options.disable_pin = namespace.disable_pin
+ return namespace
+ parser.parse_args = lambda *a, **kw: parse_args(old_parse(*a, **kw))
+
+
# We trust no other CA certificate than this.
#
# To find the certificate to copy here,
@@ -43,23 +66,8 @@ PIN_GOOGLE_PUBKEY_SHA1 = (
"\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-----
-"""
-
def check_certificate_pin(sock, cert_pubkey):
+ if options.disable_pin: return
found = []
for cert in sock.get_peer_cert_chain():
pubkey_der = cert.get_pubkey().as_der()
@@ -98,3 +106,29 @@ class temp_cert(object):
def __exit__(self, type, value, traceback):
os.unlink(self.path)
+
+def get_pubkey(defaultkeybytes, overridefn=None):
+ if overridefn is not None:
+ return RSA.load_pub_key(overridefn)
+ else:
+ return RSA.load_pub_key_bio(BIO.MemoryBuffer(defaultkeybytes))
+
+def pubkey_b64enc(plaintext, pubkey, urlsafe=False):
+ ciphertext = pubkey.public_encrypt(plaintext, RSA.pkcs1_oaep_padding)
+ if urlsafe:
+ return base64.urlsafe_b64encode(ciphertext)
+ else:
+ return ciphertext.encode("base64")
+
+def ensure_M2Crypto():
+ if M2Crypto is None:
+ print >> sys.stderr, """\
+This program requires the M2Crypto library, which is not installed.
+
+You can install it using one of the packages at
+http://chandlerproject.org/Projects/MeTooCrypto#Downloads.
+
+On Debian-like systems, use the command "apt-get install python-m2crypto".\
+"""
+ sys.exit(1)
+
diff --git a/flashproxy/reg.py b/flashproxy/reg.py
index 0551f06..84a1275 100644
--- a/flashproxy/reg.py
+++ b/flashproxy/reg.py
@@ -1,6 +1,62 @@
+import urllib
from collections import namedtuple
-from flashproxy.util import parse_addr_spec
+from flashproxy.keys import get_pubkey, pubkey_b64enc
+from flashproxy.util import parse_addr_spec, format_addr
+
+DEFAULT_REMOTE = ("", 9000)
+DEFAULT_FACILITATOR_URL = "https://fp-facilitator.org/"
+DEFAULT_TRANSPORT = "websocket"
+# Default facilitator pubkey owned by the operator of DEFAULT_FACILITATOR_URL
+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):
+ transport = DEFAULT_TRANSPORT
+ facilitator_pubkey = None
+
+def add_module_opts(parser):
+ parser.add_argument("--transport", metavar="TRANSPORT",
+ help="register using the given transport, default %(default)s.",
+ default=DEFAULT_TRANSPORT)
+ parser.add_argument("--facilitator-pubkey", metavar="FILENAME",
+ help=("encrypt registrations to the given PEM-formatted public "
+ "key file (default built-in)."))
+
+ old_parse = parser.parse_args
+ def parse_args(namespace):
+ options.transport = namespace.transport
+ options.facilitator_pubkey = namespace.facilitator_pubkey
+ return namespace
+ parser.parse_args = lambda *a, **kw: parse_args(old_parse(*a, **kw))
+
+def add_registration_args(parser):
+ add_module_opts(parser)
+ parser.add_argument("remote_addr", metavar="ADDR:PORT",
+ help="external addr+port to register, default %s" %
+ format_addr(DEFAULT_REMOTE), default="", nargs="?",
+ type=lambda x: parse_addr_spec(x, *DEFAULT_REMOTE))
+
+
+def build_reg(addr, transport):
+ return urllib.urlencode((
+ ("client", format_addr(addr)),
+ ("client-transport", transport),
+ ))
+
+def build_reg_b64enc(addr, transport, urlsafe=False):
+ pubkey = get_pubkey(DEFAULT_FACILITATOR_PUBKEY_PEM, options.facilitator_pubkey)
+ return pubkey_b64enc(build_reg(addr, transport), pubkey, urlsafe=urlsafe)
+
class Transport(namedtuple("Transport", "inner outer")):
@classmethod
diff --git a/flashproxy/util.py b/flashproxy/util.py
index 13cb5a4..3d9804b 100644
--- a/flashproxy/util.py
+++ b/flashproxy/util.py
@@ -1,6 +1,47 @@
import re
import socket
+_old_socket_getaddrinfo = socket.getaddrinfo
+
+class options(object):
+ safe_logging = True
+ address_family = socket.AF_UNSPEC
+
+def add_module_opts(parser):
+ parser.add_argument("-4",
+ help="name lookups use only IPv4.",
+ action="store_const", const=socket.AF_INET, dest="address_family")
+ parser.add_argument("-6",
+ help="name lookups use only IPv6.",
+ action="store_const", const=socket.AF_INET6, dest="address_family")
+ parser.add_argument("--unsafe-logging",
+ help="don't scrub IP addresses and other sensitive information from "
+ "logs.", action="store_true")
+
+ old_parse = parser.parse_args
+ def parse_args(namespace):
+ options.safe_logging = not namespace.unsafe_logging
+ options.address_family = namespace.address_family or socket.AF_UNSPEC
+ return namespace
+ parser.parse_args = lambda *a, **kw: parse_args(old_parse(*a, **kw))
+
+def enforce_address_family(address_family):
+ """Force all future name lookups to use the given address family."""
+ if address_family != socket.AF_UNSPEC:
+ def getaddrinfo_replacement(host, port, family, *args, **kwargs):
+ return _old_socket_getaddrinfo(host, port, options.address_family, *args, **kwargs)
+ socket.getaddrinfo = getaddrinfo_replacement
+
+def safe_str(s):
+ """Return "[scrubbed]" if options.safe_logging is true, and s otherwise."""
+ if options.safe_logging:
+ return "[scrubbed]"
+ else:
+ return s
+
+def safe_format_addr(addr):
+ return safe_str(format_addr(addr))
+
def parse_addr_spec(spec, defhost = None, defport = None):
"""Parse a host:port specification and return a 2-tuple ("host", port) as
understood by the Python socket functions.
diff --git a/mkman.sh b/mkman.sh
index cd4ecff..2532194 100755
--- a/mkman.sh
+++ b/mkman.sh
@@ -43,6 +43,7 @@ fi
prog="$1"
ver="$2"
name="${3:-$(get_description "$1")}"
+progname="$(basename "$prog")"
# Prepare a temporary executable file that just dumps its own contents.
trap 'rm -rf .tmp.$$' EXIT INT TERM
@@ -51,11 +52,11 @@ mkdir -p ".tmp.$$"
{
echo "$shebang"
cat
-} > ".tmp.$$/$prog"
-test $(size ".tmp.$$/$prog") -gt $((${#shebang} + 1)) || { echo >&2 "no input received; abort"; exit 1; }
-chmod +x ".tmp.$$/$prog"
+} > ".tmp.$$/$progname"
+test $(size ".tmp.$$/$progname") -gt $((${#shebang} + 1)) || { echo >&2 "no input received; abort"; exit 1; }
+chmod +x ".tmp.$$/$progname"
-help2man ".tmp.$$/$prog" --help-option="-q" \
+help2man ".tmp.$$/$progname" --help-option="-q" \
--name="$name" --version-string="$ver" \
--no-info --include "$(dirname "$0")/mkman.inc" \
| help2man_fixup
diff --git a/proxy/flashproxy-test.js b/proxy/flashproxy-test.js
index e004ee8..fc4fcd2 100755
--- a/proxy/flashproxy-test.js
+++ b/proxy/flashproxy-test.js
@@ -345,6 +345,32 @@ function test_have_websocket_binary_frames() {
window.navigator = _navigator;
}
+function test_is_likely_tor_browser() {
+ var TESTS = [
+ { ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:10.0.2) Gecko/20100101 Firefox/10.0.2", expected: false },
+ { ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:11.0) Gecko/20100101 Firefox/11.0", expected: false },
+ { ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36", expected: false },
+ { ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1", expected: false },
+ { ua: "Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0", expected: true },
+ { ua: "Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/20100101 Firefox/17.0", expected: true },
+ { ua: "Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0", expected: true },
+ { expected: false }, // no userAgent
+ ];
+ var _navigator = window.navigator;
+ window.navigator = { mimeTypes: [] };
+ for (var i = 0; i < TESTS.length; i++) {
+ var test = TESTS[i];
+ window.navigator.userAgent = test.ua;
+ var actual = is_likely_tor_browser();
+
+ if (objects_equal(actual, test.expected))
+ pass(test.ua);
+ else
+ fail(test.ua, test.expected, actual);
+ }
+ window.navigator = _navigator;
+}
+
test_build_url();
test_parse_cookie_string();
test_parse_query_string();
@@ -353,6 +379,7 @@ test_parse_addr_spec();
test_get_param_addr();
test_lang_keys();
test_have_websocket_binary_frames();
+test_is_likely_tor_browser();
if (num_failed == 0)
process.exit(0);
diff --git a/proxy/flashproxy.js b/proxy/flashproxy.js
index 133266a..e5f366d 100644
--- a/proxy/flashproxy.js
+++ b/proxy/flashproxy.js
@@ -20,7 +20,7 @@
*
* max_clients=<NUM>
* How many clients to serve concurrently. The default is
- * DEFAULT_MAX_NUM_PROXY_PAIRS.
+ * DEFAULT_MAX_NUM_CLIENTS.
*
* ratelimit=<FLOAT>(<UNIT>)?|off
* What rate to limit all proxy traffic combined to. The special value "off"
@@ -64,7 +64,11 @@
var DEFAULT_FACILITATOR_URL = DEFAULT_FACILITATOR_URL || "https://fp-facilitator.org/";
-var DEFAULT_MAX_NUM_PROXY_PAIRS = DEFAULT_MAX_NUM_PROXY_PAIRS || 10;
+/* Start two connections because some versions of Tor make two PT connections:
+https://lists.torproject.org/pipermail/tor-dev/2012-December/004221.html
+https://trac.torproject.org/projects/tor/ticket/7733 */
+var CONNECTIONS_PER_CLIENT = 2
+var DEFAULT_MAX_NUM_CLIENTS = DEFAULT_MAX_NUM_CLIENTS || 10;
var DEFAULT_INITIAL_FACILITATOR_POLL_INTERVAL = DEFAULT_INITIAL_FACILITATOR_POLL_INTERVAL || 60.0;
var DEFAULT_FACILITATOR_POLL_INTERVAL = DEFAULT_FACILITATOR_POLL_INTERVAL || 3600.0;
@@ -103,6 +107,8 @@ if (HEADLESS) {
function puts(s) {
if (DEBUG) {
+ s = new Date().toISOString() + " | " + s;
+
/* This shows up in the Web Console in Firefox and F12 developer tools
in Internet Explorer. */
(console.debug || console.log).call(console, s);
@@ -491,8 +497,8 @@ function FlashProxy() {
this.fac_url = get_param_string(query, "facilitator", DEFAULT_FACILITATOR_URL);
- this.max_num_proxy_pairs = get_param_integer(query, "max_clients", DEFAULT_MAX_NUM_PROXY_PAIRS);
- if (this.max_num_proxy_pairs === null || this.max_num_proxy_pairs < 0) {
+ this.max_num_clients = get_param_integer(query, "max_clients", DEFAULT_MAX_NUM_CLIENTS);
+ if (this.max_num_clients === null || this.max_num_clients < 0) {
puts("Error: max_clients must be a nonnegative integer.");
this.die();
return;
@@ -560,7 +566,7 @@ function FlashProxy() {
var base_url, url;
var xhr;
- if (this.proxy_pairs.length >= this.max_num_proxy_pairs) {
+ if (this.proxy_pairs.length >= this.max_num_clients * CONNECTIONS_PER_CLIENT) {
setTimeout(this.proxy_main.bind(this), this.facilitator_poll_interval * 1000);
return;
}
@@ -583,7 +589,6 @@ function FlashProxy() {
like "Component returned failure code: 0x805e0006
[nsIXMLHttpRequest.open]" on Firefox. */
puts("Facilitator: exception while connecting: " + repr(err.message) + ".");
- this.die();
return;
}
xhr.responseType = "text";
@@ -593,7 +598,6 @@ function FlashProxy() {
this.fac_complete(xhr.responseText);
} else {
puts("Facilitator: can't connect: got status " + repr(xhr.status) + " and status text " + repr(xhr.statusText) + ".");
- this.die();
}
}
}.bind(this);
@@ -655,12 +659,9 @@ function FlashProxy() {
};
this.begin_proxy = function(client_addr, relay_addr) {
- /* Start two proxy connections because of some versions of Tor making
- two pt connections:
- https://lists.torproject.org/pipermail/tor-dev/2012-December/004221.html
- https://trac.torproject.org/projects/tor/ticket/7733 */
- this.make_proxy_pair(client_addr, relay_addr);
- this.make_proxy_pair(client_addr, relay_addr);
+ for (var i=0; i<CONNECTIONS_PER_CLIENT; i++) {
+ this.make_proxy_pair(client_addr, relay_addr);
+ }
};
this.make_proxy_pair = function(client_addr, relay_addr) {
@@ -668,8 +669,7 @@ function FlashProxy() {
proxy_pair = new ProxyPair(client_addr, relay_addr, this.rate_limit);
this.proxy_pairs.push(proxy_pair);
- proxy_pair.complete_callback = function(event) {
- puts("Complete.");
+ proxy_pair.cleanup_callback = function(event) {
/* Delete from the list of active proxy pairs. */
this.proxy_pairs.splice(this.proxy_pairs.indexOf(proxy_pair), 1);
if (this.badge)
@@ -679,7 +679,6 @@ function FlashProxy() {
proxy_pair.connect();
} catch (err) {
puts("ProxyPair: exception while connecting: " + safe_repr(err.message) + ".");
- this.die();
return;
}
@@ -688,19 +687,24 @@ function FlashProxy() {
};
/* Cease all network operations and prevent any future ones. */
- this.disable = function() {
- puts("Disabling.");
+ this.cease_operation = function() {
this.start = function() { };
this.proxy_main = function() { };
this.make_proxy_pair = function(client_addr, relay_addr) { };
while (this.proxy_pairs.length > 0)
this.proxy_pairs.pop().close();
+ };
+
+ this.disable = function() {
+ puts("Disabling.");
+ this.cease_operation();
if (this.badge)
this.badge.disable();
};
this.die = function() {
puts("Dying.");
+ this.cease_operation();
if (this.badge)
this.badge.die();
};
@@ -711,6 +715,9 @@ function ProxyPair(client_addr, relay_addr, rate_limit) {
var MAX_BUFFER = 10 * 1024 * 1024;
function log(s) {
+ if (!SAFE_LOGGING) {
+ s = format_addr(client_addr) + '|' + format_addr(relay_addr) + ' : ' + s
+ }
puts(s)
}
@@ -725,7 +732,7 @@ function ProxyPair(client_addr, relay_addr, rate_limit) {
this.flush_timeout_id = null;
/* This callback function can be overridden by external callers. */
- this.complete_callback = function() {
+ this.cleanup_callback = function() {
};
this.connect = function() {
@@ -761,15 +768,23 @@ function ProxyPair(client_addr, relay_addr, rate_limit) {
log(ws.label + ": connected.");
}.bind(this);
+ this.maybe_cleanup = function() {
+ if (this.running && is_closed(this.client_s) && is_closed(this.relay_s)) {
+ this.running = false;
+ this.cleanup_callback();
+ return true;
+ }
+ return false;
+ }
+
this.onclose_callback = function(event) {
var ws = event.target;
log(ws.label + ": closed.");
this.flush();
- if (this.running && is_closed(this.client_s) && is_closed(this.relay_s)) {
- this.running = false;
- this.complete_callback();
+ if (this.maybe_cleanup()) {
+ puts("Complete.");
}
}.bind(this);
@@ -778,6 +793,11 @@ function ProxyPair(client_addr, relay_addr, rate_limit) {
log(ws.label + ": error.");
this.close();
+
+ // we can't rely on onclose_callback to cleanup, since one common error
+ // case is when the client fails to connect and the relay never starts.
+ // in that case close() is a NOP and onclose_callback is never called.
+ this.maybe_cleanup();
}.bind(this);
this.onmessage_client_to_relay = function(event) {
@@ -1031,6 +1051,7 @@ function safe_repr(s) {
var TBB_UAS = [
"Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0",
"Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/20100101 Firefox/17.0",
+ "Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0",
];
function is_likely_tor_browser() {
return TBB_UAS.indexOf(window.navigator.userAgent) > -1
diff --git a/torrc b/torrc
index b8a2439..fa6db3b 100644
--- a/torrc
+++ b/torrc
@@ -3,8 +3,14 @@
## tor -f torrc
UseBridges 1
+
# The address and port are ignored by the client transport plugin.
-Bridge flashproxy 0.0.1.0:1
+Bridge flashproxy 0.0.1.0:1 4D6C0DF6DEC9398A4DEF07084F3CD395A96DD2AD
+Bridge flashproxy 0.0.1.0:2 4D6C0DF6DEC9398A4DEF07084F3CD395A96DD2AD
+Bridge flashproxy 0.0.1.0:3 4D6C0DF6DEC9398A4DEF07084F3CD395A96DD2AD
+Bridge flashproxy 0.0.1.0:4 4D6C0DF6DEC9398A4DEF07084F3CD395A96DD2AD
+Bridge flashproxy 0.0.1.0:5 4D6C0DF6DEC9398A4DEF07084F3CD395A96DD2AD
+
# Change the second number here (9000) to the number of a port that can
# receive connections from the Internet (the port for which you
# configured port forwarding).
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/flashproxy.git
More information about the Pkg-privacy-commits
mailing list