Skip to content

Commit

Permalink
security/openvpn: add tunnelblick openvpn_xorpatch as option; fixes #9
Browse files Browse the repository at this point in the history
  • Loading branch information
fichtner committed May 8, 2015
1 parent 912098e commit ecab736
Show file tree
Hide file tree
Showing 2 changed files with 291 additions and 1 deletion.
6 changes: 5 additions & 1 deletion security/openvpn/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ LDFLAGS+= -L${LOCALBASE}/lib
# set PLUGIN_LIBDIR so that unqualified plugin paths are found:
CPPFLAGS+= -DPLUGIN_LIBDIR=\\\"${PREFIX}/lib/openvpn/plugins\\\"

OPTIONS_DEFINE= PW_SAVE PKCS11 EASYRSA DOCS EXAMPLES X509ALTUSERNAME ENGINEFIX2
OPTIONS_DEFINE= PW_SAVE PKCS11 EASYRSA DOCS EXAMPLES \
X509ALTUSERNAME ENGINEFIX2 TXP
OPTIONS_DEFAULT= EASYRSA OPENSSL
OPTIONS_SINGLE= SSL
OPTIONS_SINGLE_SSL= OPENSSL POLARSSL
PW_SAVE_DESC= Interactive passwords may be read from a file
PKCS11_DESC= Use security/pkcs11-helper
EASYRSA_DESC= Install security/easy-rsa RSA helper package
POLARSSL_DESC= SSL/TLS support via PolarSSL
TXP_DESC= Tunnelblick XOR scramble patch
X509ALTUSERNAME_DESC= Enable --x509-username-field (only with OpenSSL)
ENGINEFIX2_DESC= New EXPERIMENTAL patchset for SSL engine use (OpenSSL)

Expand All @@ -46,6 +48,8 @@ PKCS11_CONFIGURE_ENABLE= pkcs11

PW_SAVE_CONFIGURE_ENABLE= password-save

TXP_EXTRA_PATCHES= ${FILESDIR}/extra-tunnelblick-openvpn_xorpatch

X509ALTUSERNAME_CONFIGURE_ENABLE= x509-alt-username

.include <bsd.port.options.mk>
Expand Down
286 changes: 286 additions & 0 deletions security/openvpn/files/extra-tunnelblick-openvpn_xorpatch
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
diff -u -r src/openvpn/forward.c src/openvpn/forward.c
--- src/openvpn/forward.c 2014-11-29 10:00:35.000000000 -0500
+++ src/openvpn/forward.c 2015-04-07 22:38:20.000000000 -0400
@@ -674,7 +674,10 @@
status = link_socket_read (c->c2.link_socket,
&c->c2.buf,
MAX_RW_SIZE_LINK (&c->c2.frame),
- &c->c2.from);
+ &c->c2.from,
+ c->options.ce.xormethod,
+ c->options.ce.xormask,
+ c->options.ce.xormasklen);

if (socket_connection_reset (c->c2.link_socket, status))
{
@@ -1150,7 +1153,10 @@
/* Send packet */
size = link_socket_write (c->c2.link_socket,
&c->c2.to_link,
- to_addr);
+ to_addr,
+ c->options.ce.xormethod,
+ c->options.ce.xormask,
+ c->options.ce.xormasklen);

#ifdef ENABLE_SOCKS
/* Undo effect of prepend */
diff -u -r src/openvpn/options.c src/openvpn/options.c
--- src/openvpn/options.c 2014-11-29 10:00:35.000000000 -0500
+++ src/openvpn/options.c 2015-04-09 12:56:32.000000000 -0400
@@ -785,6 +785,9 @@
o->max_routes = MAX_ROUTES_DEFAULT;
o->resolve_retry_seconds = RESOLV_RETRY_INFINITE;
o->proto_force = -1;
+ o->ce.xormethod = 0;
+ o->ce.xormask ="\0";
+ o->ce.xormasklen = 1;
#ifdef ENABLE_OCC
o->occ = true;
#endif
@@ -903,6 +906,9 @@
setenv_int_i (es, "local_port", e->local_port, i);
setenv_str_i (es, "remote", e->remote, i);
setenv_int_i (es, "remote_port", e->remote_port, i);
+ setenv_int_i (es, "xormethod", e->xormethod, i);
+ setenv_str_i (es, "xormask", e->xormask, i);
+ setenv_int_i (es, "xormasklen", e->xormasklen, i);

#ifdef ENABLE_HTTP_PROXY
if (e->http_proxy_options)
@@ -1348,6 +1354,9 @@
SHOW_INT (connect_retry_seconds);
SHOW_INT (connect_timeout);
SHOW_INT (connect_retry_max);
+ SHOW_INT (xormethod);
+ SHOW_STR (xormask);
+ SHOW_INT (xormasklen);

#ifdef ENABLE_HTTP_PROXY
if (o->http_proxy_options)
@@ -5049,6 +5058,46 @@
options->proto_force = proto_force;
options->force_connection_list = true;
}
+ else if (streq (p[0], "scramble") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
+ if (streq (p[1], "xormask") && p[2] && (!p[3]))
+ {
+ options->ce.xormethod = 1;
+ options->ce.xormask = p[2];
+ options->ce.xormasklen = strlen(options->ce.xormask);
+ }
+ else if (streq (p[1], "xorptrpos") && (!p[2]))
+ {
+ options->ce.xormethod = 2;
+ options->ce.xormask = NULL;
+ options->ce.xormasklen = 0;
+ }
+ else if (streq (p[1], "reverse") && (!p[2]))
+ {
+ options->ce.xormethod = 3;
+ options->ce.xormask = NULL;
+ options->ce.xormasklen = 0;
+ }
+ else if (streq (p[1], "obfuscate") && p[2] && (!p[3]))
+ {
+ options->ce.xormethod = 4;
+ options->ce.xormask = p[2];
+ options->ce.xormasklen = strlen(options->ce.xormask);
+ }
+ else if (!p[2])
+ {
+ msg (M_WARN, "WARNING: No recognized 'scramble' method specified; using 'scramble xormask \"%s\"'", p[1]);
+ options->ce.xormethod = 1;
+ options->ce.xormask = p[1];
+ options->ce.xormasklen = strlen(options->ce.xormask);
+ }
+ else
+ {
+ msg (msglevel, "No recognized 'scramble' method specified or extra parameters for 'scramble'");
+ goto err;
+ }
+ }
#ifdef ENABLE_HTTP_PROXY
else if (streq (p[0], "http-proxy") && p[1])
{
diff -u -r src/openvpn/options.h src/openvpn/options.h
--- src/openvpn/options.h 2014-11-29 10:00:35.000000000 -0500
+++ src/openvpn/options.h 2015-04-07 22:38:20.000000000 -0400
@@ -100,6 +100,9 @@
int connect_retry_max;
int connect_timeout;
bool connect_timeout_defined;
+ int xormethod;
+ const char *xormask;
+ int xormasklen;
#ifdef ENABLE_HTTP_PROXY
struct http_proxy_options *http_proxy_options;
#endif
diff -u -r src/openvpn/socket.c src/openvpn/socket.c
--- src/openvpn/socket.c 2014-11-29 10:00:35.000000000 -0500
+++ src/openvpn/socket.c 2015-04-09 08:48:01.000000000 -0400
@@ -52,6 +52,51 @@
IPv6_TCP_HEADER_SIZE,
};

+int buffer_mask (struct buffer *buf, const char *mask, int xormasklen) {
+ int i;
+ uint8_t *b;
+ for (i = 0, b = BPTR (buf); i < BLEN(buf); i++, b++) {
+ *b = *b ^ mask[i % xormasklen];
+ }
+ return BLEN (buf);
+}
+
+int buffer_xorptrpos (struct buffer *buf) {
+ int i;
+ uint8_t *b;
+ for (i = 0, b = BPTR (buf); i < BLEN(buf); i++, b++) {
+ *b = *b ^ i+1;
+ }
+ return BLEN (buf);
+}
+
+int buffer_reverse (struct buffer *buf) {
+/* This function has been rewritten for Tunnelblick. The buffer_reverse function at
+ * https://github.com/clayface/openvpn_xorpatch
+ * makes a copy of the buffer and it writes to the byte **after** the
+ * buffer contents, so if the buffer is full then it writes outside of the buffer.
+ * This rewritten version does neither.
+ *
+ * For interoperability, this rewritten version preserves the behavior of the original
+ * function: it does not modify the first character of the buffer. So it does not
+ * actually reverse the contents of the buffer. Instead, it changes 'abcde' to 'aedcb'.
+ * (Of course, the actual buffer contents are bytes, and not necessarily characters.)
+ */
+ int len = BLEN(buf);
+ if ( len > 2 ) { /* Leave '', 'a', and 'ab' alone */
+ int i;
+ uint8_t *b_start = BPTR (buf) + 1; /* point to first byte to swap */
+ uint8_t *b_end = BPTR (buf) + (len - 1); /* point to last byte to swap */
+ uint8_t tmp;
+ for (i = 0; i < (len-1)/2; i++, b_start++, b_end--) {
+ tmp = *b_start;
+ *b_start = *b_end;
+ *b_end = tmp;
+ }
+ }
+ return len;
+}
+
/*
* Convert sockflags/getaddr_flags into getaddr_flags
*/
diff -u -r src/openvpn/socket.h src/openvpn/socket.h
--- src/openvpn/socket.h 2014-11-29 10:00:35.000000000 -0500
+++ src/openvpn/socket.h 2015-04-08 20:12:02.000000000 -0400
@@ -250,6 +250,10 @@
#endif
};

+int buffer_mask (struct buffer *buf, const char *xormask, int xormasklen);
+int buffer_xorptrpos (struct buffer *buf);
+int buffer_reverse (struct buffer *buf);
+
/*
* Some Posix/Win32 differences.
*/
@@ -875,30 +879,56 @@
link_socket_read (struct link_socket *sock,
struct buffer *buf,
int maxsize,
- struct link_socket_actual *from)
+ struct link_socket_actual *from,
+ int xormethod,
+ const char *xormask,
+ int xormasklen)
{
+ int res;
if (proto_is_udp(sock->info.proto)) /* unified UDPv4 and UDPv6 */
{
- int res;

#ifdef WIN32
res = link_socket_read_udp_win32 (sock, buf, from);
#else
res = link_socket_read_udp_posix (sock, buf, maxsize, from);
#endif
- return res;
}
else if (proto_is_tcp(sock->info.proto)) /* unified TCPv4 and TCPv6 */
{
/* from address was returned by accept */
addr_copy_sa(&from->dest, &sock->info.lsa->actual.dest);
- return link_socket_read_tcp (sock, buf);
+ res = link_socket_read_tcp (sock, buf);
}
else
{
ASSERT (0);
return -1; /* NOTREACHED */
}
+ switch(xormethod)
+ {
+ case 0:
+ break;
+ case 1:
+ buffer_mask(buf,xormask,xormasklen);
+ break;
+ case 2:
+ buffer_xorptrpos(buf);
+ break;
+ case 3:
+ buffer_reverse(buf);
+ break;
+ case 4:
+ buffer_mask(buf,xormask,xormasklen);
+ buffer_xorptrpos(buf);
+ buffer_reverse(buf);
+ buffer_xorptrpos(buf);
+ break;
+ default:
+ ASSERT (0);
+ return -1; /* NOTREACHED */
+ }
+ return res;
}

/*
@@ -982,8 +1012,34 @@
static inline int
link_socket_write (struct link_socket *sock,
struct buffer *buf,
- struct link_socket_actual *to)
+ struct link_socket_actual *to,
+ int xormethod,
+ const char *xormask,
+ int xormasklen)
{
+ switch(xormethod)
+ {
+ case 0:
+ break;
+ case 1:
+ buffer_mask(buf,xormask,xormasklen);
+ break;
+ case 2:
+ buffer_xorptrpos(buf);
+ break;
+ case 3:
+ buffer_reverse(buf);
+ break;
+ case 4:
+ buffer_xorptrpos(buf);
+ buffer_reverse(buf);
+ buffer_xorptrpos(buf);
+ buffer_mask(buf,xormask,xormasklen);
+ break;
+ default:
+ ASSERT (0);
+ return -1; /* NOTREACHED */
+ }
if (proto_is_udp(sock->info.proto)) /* unified UDPv4 and UDPv6 */
{
return link_socket_write_udp (sock, buf, to);

0 comments on commit ecab736

Please sign in to comment.