summaryrefslogtreecommitdiff
path: root/app/openvpn
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2015-01-19 16:31:59 +0100
committerParménides GV <parmegv@sdf.org>2015-01-19 16:31:59 +0100
commit1e748855652780d225fd113320ffe1bceca5ba8e (patch)
treea0b257591ef9f3b4c662165c20ffad120fcdeba1 /app/openvpn
parentfab7a89f44d59f3c7ea7505ae05a3c8b4c67c0b8 (diff)
parent45cf8b1cc3085a575c5a460eb7d8191ee6033da4 (diff)
Merge branch 'develop'
Diffstat (limited to 'app/openvpn')
-rw-r--r--app/openvpn/config-version.h2
-rw-r--r--app/openvpn/configure.ac6
-rw-r--r--app/openvpn/distro/Makefile.am2
-rw-r--r--app/openvpn/distro/systemd/openvpn-client@.service20
-rw-r--r--app/openvpn/distro/systemd/openvpn-server@.service19
-rw-r--r--app/openvpn/doc/doxygen/doc_data_crypto.h4
-rw-r--r--app/openvpn/doc/doxygen/doc_mainpage.h2
-rw-r--r--app/openvpn/doc/doxygen/doc_protocol_overview.h69
-rw-r--r--app/openvpn/doc/openvpn.827
-rw-r--r--app/openvpn/sample/sample-config-files/client.conf17
-rw-r--r--app/openvpn/sample/sample-config-files/loopback-client2
-rw-r--r--app/openvpn/sample/sample-config-files/loopback-server3
-rw-r--r--app/openvpn/sample/sample-config-files/server.conf6
-rw-r--r--app/openvpn/sample/sample-config-files/tls-office.conf2
-rw-r--r--app/openvpn/sample/sample-keys/README17
-rw-r--r--app/openvpn/sample/sample-keys/ca.crt48
-rw-r--r--app/openvpn/sample/sample-keys/ca.key67
-rw-r--r--app/openvpn/sample/sample-keys/client-ec.crt85
-rw-r--r--app/openvpn/sample/sample-keys/client-ec.key5
-rw-r--r--app/openvpn/sample/sample-keys/client-pass.key30
-rw-r--r--app/openvpn/sample/sample-keys/client.crt126
-rw-r--r--app/openvpn/sample/sample-keys/client.key43
-rw-r--r--app/openvpn/sample/sample-keys/client.p12bin0 -> 4533 bytes
-rw-r--r--app/openvpn/sample/sample-keys/dh2048.pem8
-rwxr-xr-xapp/openvpn/sample/sample-keys/gen-sample-keys.sh75
-rw-r--r--app/openvpn/sample/sample-keys/openssl.cnf139
-rw-r--r--app/openvpn/sample/sample-keys/server-ec.crt96
-rw-r--r--app/openvpn/sample/sample-keys/server-ec.key5
-rw-r--r--app/openvpn/sample/sample-keys/server.crt130
-rw-r--r--app/openvpn/sample/sample-keys/server.key43
-rw-r--r--app/openvpn/src/openvpn/crypto.c131
-rw-r--r--app/openvpn/src/openvpn/crypto.h75
-rw-r--r--app/openvpn/src/openvpn/crypto_backend.h6
-rw-r--r--app/openvpn/src/openvpn/forward.c50
-rw-r--r--app/openvpn/src/openvpn/forward.h30
-rw-r--r--app/openvpn/src/openvpn/helper.c2
-rw-r--r--app/openvpn/src/openvpn/init.c2
-rw-r--r--app/openvpn/src/openvpn/mtu.c5
-rw-r--r--app/openvpn/src/openvpn/mudp.c92
-rw-r--r--app/openvpn/src/openvpn/mudp.h2
-rw-r--r--app/openvpn/src/openvpn/multi.c117
-rw-r--r--app/openvpn/src/openvpn/multi.h27
-rw-r--r--app/openvpn/src/openvpn/options.c35
-rw-r--r--app/openvpn/src/openvpn/options.h4
-rw-r--r--app/openvpn/src/openvpn/push.c3
-rw-r--r--app/openvpn/src/openvpn/route.c60
-rw-r--r--app/openvpn/src/openvpn/route.h1
-rw-r--r--app/openvpn/src/openvpn/socket.c31
-rw-r--r--app/openvpn/src/openvpn/ssl.c46
-rw-r--r--app/openvpn/src/openvpn/ssl.h12
-rw-r--r--app/openvpn/src/openvpn/ssl_backend.h11
-rw-r--r--app/openvpn/src/openvpn/ssl_common.h6
-rw-r--r--app/openvpn/src/openvpn/ssl_openssl.c16
-rw-r--r--app/openvpn/src/openvpn/ssl_polarssl.c82
-rw-r--r--app/openvpn/src/plugins/down-root/down-root.c696
-rwxr-xr-xapp/openvpn/tests/t_lpback.sh3
56 files changed, 1687 insertions, 956 deletions
diff --git a/app/openvpn/config-version.h b/app/openvpn/config-version.h
index 1fca2b7a..f89c974f 100644
--- a/app/openvpn/config-version.h
+++ b/app/openvpn/config-version.h
@@ -1,2 +1,2 @@
-#define CONFIGURE_GIT_REVISION "icsopenvpn_621-b603913ee5d54ab8"
+#define CONFIGURE_GIT_REVISION "icsopenvpn_625-af9eb9424047f9f5"
#define CONFIGURE_GIT_FLAGS ""
diff --git a/app/openvpn/configure.ac b/app/openvpn/configure.ac
index 608ab6d1..ddaa2b2e 100644
--- a/app/openvpn/configure.ac
+++ b/app/openvpn/configure.ac
@@ -73,7 +73,7 @@ AC_ARG_ENABLE(
AC_ARG_ENABLE(
[ofb-cfb],
- [AS_HELP_STRING([--enable-ofb-cfb], [enable support for OFB and CFB cipher modes @<:@default=yes@:>@])],
+ [AS_HELP_STRING([--disable-ofb-cfb], [disable support for OFB and CFB cipher modes @<:@default=yes@:>@])],
,
[enable_crypto_ofb_cfb="yes"]
)
@@ -157,14 +157,14 @@ AC_ARG_ENABLE(
AC_ARG_ENABLE(
[small],
- [AS_HELP_STRING([--enable-small], [enable smaller executable size (disable OCC, usage message, and verb 4 parm list) @<:@default=yes@:>@])],
+ [AS_HELP_STRING([--enable-small], [enable smaller executable size (disable OCC, usage message, and verb 4 parm list) @<:@default=no@:>@])],
,
[enable_small="no"]
)
AC_ARG_ENABLE(
[password-save],
- [AS_HELP_STRING([--enable-password-save], [allow --askpass and --auth-user-pass passwords to be read from a file @<:@default=yes@:>@])],
+ [AS_HELP_STRING([--enable-password-save], [allow --askpass and --auth-user-pass passwords to be read from a file @<:@default=no@:>@])],
,
[enable_password_save="no"]
)
diff --git a/app/openvpn/distro/Makefile.am b/app/openvpn/distro/Makefile.am
index 2dd6a6ee..bd65b79b 100644
--- a/app/openvpn/distro/Makefile.am
+++ b/app/openvpn/distro/Makefile.am
@@ -13,3 +13,5 @@ MAINTAINERCLEANFILES = \
$(srcdir)/Makefile.in
SUBDIRS = rpm
+
+EXTRA_DIST = systemd/openvpn-client@.service systemd/openvpn-server@.service
diff --git a/app/openvpn/distro/systemd/openvpn-client@.service b/app/openvpn/distro/systemd/openvpn-client@.service
new file mode 100644
index 00000000..56d93a93
--- /dev/null
+++ b/app/openvpn/distro/systemd/openvpn-client@.service
@@ -0,0 +1,20 @@
+[Unit]
+Description=OpenVPN tunnel for %I
+After=syslog.target network-online.target
+Wants=network-online.target
+Documentation=man:openvpn(8)
+Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
+Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
+
+[Service]
+PrivateTmp=true
+Type=forking
+PIDFile=/var/run/openvpn/client_%i.pid
+ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/client --config %i.conf --daemon --writepid /var/run/openvpn/client_%i.pid
+CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH
+LimitNPROC=10
+DeviceAllow=/dev/null rw
+DeviceAllow=/dev/net/tun rw
+
+[Install]
+WantedBy=multi-user.target
diff --git a/app/openvpn/distro/systemd/openvpn-server@.service b/app/openvpn/distro/systemd/openvpn-server@.service
new file mode 100644
index 00000000..c4c9a123
--- /dev/null
+++ b/app/openvpn/distro/systemd/openvpn-server@.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=OpenVPN service for %I
+After=syslog.target network.target
+Documentation=man:openvpn(8)
+Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
+Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
+
+[Service]
+PrivateTmp=true
+Type=forking
+PIDFile=/var/run/openvpn/server_%i.pid
+ExecStart=/usr/sbin/openvpn --cd /etc/openvpn/server --status /var/run/openvpn/server_%i-status.log --status-version 2 --config %i.conf --daemon --writepid /var/run/openvpn/server_%i.pid
+CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH
+LimitNPROC=10
+DeviceAllow=/dev/null rw
+DeviceAllow=/dev/net/tun rw
+
+[Install]
+WantedBy=multi-user.target
diff --git a/app/openvpn/doc/doxygen/doc_data_crypto.h b/app/openvpn/doc/doxygen/doc_data_crypto.h
index ee72b8cd..640203f4 100644
--- a/app/openvpn/doc/doxygen/doc_data_crypto.h
+++ b/app/openvpn/doc/doxygen/doc_data_crypto.h
@@ -69,7 +69,5 @@
*
* @par Crypto algorithms
* This module uses the crypto algorithm implementations of the external
- * OpenSSL library. More precisely, it uses the OpenSSL library's \c
- * EVP_Cipher* and \c HMAC_* set of functions to perform cryptographic
- * operations on data channel packets.
+ * crypto library (currently either OpenSSL (default), or PolarSSL).
*/
diff --git a/app/openvpn/doc/doxygen/doc_mainpage.h b/app/openvpn/doc/doxygen/doc_mainpage.h
index 821b2e87..ed8e324e 100644
--- a/app/openvpn/doc/doxygen/doc_mainpage.h
+++ b/app/openvpn/doc/doxygen/doc_mainpage.h
@@ -29,7 +29,7 @@
*/
/**
- * @mainpage OpenVPN v2.1 source code documentation
+ * @mainpage OpenVPN source code documentation
*
* This documentation describes the internal structure of OpenVPN. It was
* automatically generated from specially formatted comment blocks in
diff --git a/app/openvpn/doc/doxygen/doc_protocol_overview.h b/app/openvpn/doc/doxygen/doc_protocol_overview.h
index 26fed331..9edafcfb 100644
--- a/app/openvpn/doc/doxygen/doc_protocol_overview.h
+++ b/app/openvpn/doc/doxygen/doc_protocol_overview.h
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
+ * Copyright (C) 2010-2014 Fox Crypto B.V. <openvpn@fox-it.com>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -61,24 +61,26 @@
* following describes the various opcodes available.
*
* - Control channel messages:
- * - \c P_CONTROL_HARD_RESET_CLIENT_V1 -- %Key method 1, initial %key
+ * - \ref P_CONTROL_HARD_RESET_CLIENT_V1 -- %Key method 1, initial %key
* from client, forget previous state.
- * - \c P_CONTROL_HARD_RESET_SERVER_V1 -- %Key method 1, initial %key
+ * - \ref P_CONTROL_HARD_RESET_SERVER_V1 -- %Key method 1, initial %key
* from server, forget previous state.
- * - \c P_CONTROL_HARD_RESET_CLIENT_V2 -- %Key method 2, initial %key
+ * - \ref P_CONTROL_HARD_RESET_CLIENT_V2 -- %Key method 2, initial %key
* from client, forget previous state.
- * - \c P_CONTROL_HARD_RESET_SERVER_V2 -- %Key method 2, initial %key
+ * - \ref P_CONTROL_HARD_RESET_SERVER_V2 -- %Key method 2, initial %key
* from server, forget previous state.
- * - \c P_CONTROL_SOFT_RESET_V1 -- New %key, with a graceful
+ * - \ref P_CONTROL_SOFT_RESET_V1 -- New %key, with a graceful
* transition from old to new %key in the sense that a transition
* window exists where both the old or new key_id can be used.
- * - \c P_CONTROL_V1 -- Control channel packet (usually TLS
+ * - \ref P_CONTROL_V1 -- Control channel packet (usually TLS
* ciphertext).
- * - \c P_ACK_V1 -- Acknowledgement for control channel packets
+ * - \ref P_ACK_V1 -- Acknowledgement for control channel packets
* received.
* - Data channel messages:
- * - \c P_DATA_V1 -- Data channel packet containing data channel
+ * - \ref P_DATA_V1 -- Data channel packet containing data channel
* ciphertext.
+ * - \ref P_DATA_V2 -- Data channel packet containing peer-id and data
+ * channel ciphertext.
*
* @subsection network_protocol_external_key_id Session IDs and Key IDs
*
@@ -139,10 +141,10 @@
* channel is used to exchange random %key material for bidirectional
* cipher and HMAC keys which will be used to secure data channel packets.
* OpenVPN currently implements two %key methods. %Key method 1 directly
- * derives keys using random bits obtained from the \c RAND_bytes()
- * OpenSSL function. %Key method 2 mixes random %key material from both
- * sides of the connection using the TLS PRF mixing function. %Key method
- * 2 is the preferred method and is the default for OpenVPN 2.0.
+ * derives keys using random bits obtained from the \c rand_bytes() function.
+ * %Key method 2 mixes random %key material from both sides of the connection
+ * using the TLS PRF mixing function. %Key method 2 is the preferred method and
+ * is the default for OpenVPN 2.0+.
*
* The @ref key_generation "Data channel key generation" related page
* describes the %key methods in more detail.
@@ -173,27 +175,22 @@
*
* @section network_protocol_data Structure of data channel messages
*
- * @subsection network_protocol_data_ciphertext Structure of ciphertext data channel messages
- *
- * The P_DATA_* payload represents encrypted, encapsulated tunnel packets
- * which tend to be either IP packets or Ethernet frames. This is
- * essentially the "payload" of the VPN.
- *
- * Data channel packets in ciphertext form consist of the following parts:
- * - HMAC of ciphertext IV + ciphertext (if not disabled by \c --auth
- * none).
- * - Ciphertext IV (size is cipher-dependent, if not disabled by \c
- * --no-iv).
- * - Tunnel packet ciphertext.
- *
- * @subsection network_protocol_data_plaintext Structure of plaintext data channel messages
- *
- * Data channel packets in plaintext form consist of the following parts:
- * - packet-id (4 or 8 bytes, if not disabled by --no-replay).
- * - In TLS mode, 4 bytes are used because the implementation can
- * force a TLS renegotation before \c 2^32 packets are sent.
- * - In pre-shared %key mode, 8 bytes are used (sequence number and \c
- * time_t value) to allow long-term %key usage without packet-id
- * collisions.
- * - User plaintext (n bytes).
+ * The P_DATA_* payload represents encapsulated tunnel packets which tend to be
+ * either IP packets or Ethernet frames. This is essentially the "payload" of
+ * the VPN. Data channel packets consist of a data channel header, and a
+ * payload. There are two possible formats:
+ *
+ * @par P_DATA_V1
+ * P_DATA_V1 packets have a 1-byte header, carrying the \ref P_DATA_V1 \c opcode
+ * and \c key_id, followed by the payload:\n
+ * <tt> [ 5-bit opcode | 3-bit key_id ] [ payload ] </tt>
+ *
+ * @par P_DATA_V2
+ * P_DATA_V2 packets have the same 1-byte opcode/key_id, but carrying the \ref
+ * P_DATA_V2 opcode, followed by a 3-byte peer-id, which uniquely identifies
+ * the peer:\n
+ * <tt> [ 5-bit opcode | 3-bit key_id ] [ 24-bit peer-id ] [ payload ] </tt>
+ *
+ * See @ref data_crypto for details on the data channel payload format.
+ *
*/
diff --git a/app/openvpn/doc/openvpn.8 b/app/openvpn/doc/openvpn.8
index f2911c0e..532eda5c 100644
--- a/app/openvpn/doc/openvpn.8
+++ b/app/openvpn/doc/openvpn.8
@@ -1437,6 +1437,7 @@ Currently defaults to 100.
Limit bandwidth of outgoing tunnel data to
.B n
bytes per second on the TCP/UDP port.
+Note that this will only work if mode is set to p2p.
If you want to limit the bandwidth
in both directions, use this option on both peers.
@@ -4330,6 +4331,11 @@ and version is not recognized, we will only accept the highest TLS
version supported by the local SSL implementation.
.\"*********************************************************
.TP
+.B \-\-tls-version-max version
+Set the maximum TLS version we will use (default is the highest version
+supported). Examples for version include "1.0", "1.1", or "1.2".
+.\"*********************************************************
+.TP
.B \-\-pkcs12 file
Specify a PKCS #12 file containing local private key,
local certificate, and root CA certificate.
@@ -4603,26 +4609,11 @@ bearing an incorrect HMAC signature can be dropped immediately without
response.
.B file
-(required) is a key file which can be in one of two formats:
-
-.B (1)
-An OpenVPN static key file generated by
+(required) is a file in OpenVPN static key format which can be generated by
.B \-\-genkey
-(required if
-.B direction
-parameter is used).
-
-.B (2)
-A freeform passphrase file. In this case the HMAC key will
-be derived by taking a secure hash of this file, similar to
-the
-.BR md5sum (1)
-or
-.BR sha1sum (1)
-commands.
-OpenVPN will first try format (1), and if the file fails to parse as
-a static key file, format (2) will be used.
+Older versions (up to 2.3) supported a freeform passphrase file.
+This is no longer supported in newer versions (2.4+).
See the
.B \-\-secret
diff --git a/app/openvpn/sample/sample-config-files/client.conf b/app/openvpn/sample/sample-config-files/client.conf
index 58b2038b..050ef600 100644
--- a/app/openvpn/sample/sample-config-files/client.conf
+++ b/app/openvpn/sample/sample-config-files/client.conf
@@ -89,18 +89,19 @@ ca ca.crt
cert client.crt
key client.key
-# Verify server certificate by checking
-# that the certicate has the nsCertType
-# field set to "server". This is an
-# important precaution to protect against
+# Verify server certificate by checking that the
+# certicate has the correct key usage set.
+# This is an important precaution to protect against
# a potential attack discussed here:
# http://openvpn.net/howto.html#mitm
#
# To use this feature, you will need to generate
-# your server certificates with the nsCertType
-# field set to "server". The build-key-server
-# script in the easy-rsa folder will do this.
-ns-cert-type server
+# your server certificates with the keyUsage set to
+# digitalSignature, keyEncipherment
+# and the extendedKeyUsage to
+# serverAuth
+# EasyRSA can do this for you.
+remote-cert-tls server
# If a tls-auth key is used on the server
# then every client must also have the key.
diff --git a/app/openvpn/sample/sample-config-files/loopback-client b/app/openvpn/sample/sample-config-files/loopback-client
index d7f59e69..ebbd1cf4 100644
--- a/app/openvpn/sample/sample-config-files/loopback-client
+++ b/app/openvpn/sample/sample-config-files/loopback-client
@@ -17,9 +17,9 @@ dev null
verb 3
reneg-sec 10
tls-client
+remote-cert-tls server
ca sample-keys/ca.crt
key sample-keys/client.key
cert sample-keys/client.crt
-cipher DES-EDE3-CBC
ping 1
inactive 120 10000000
diff --git a/app/openvpn/sample/sample-config-files/loopback-server b/app/openvpn/sample/sample-config-files/loopback-server
index 9d21bcec..8cb97be0 100644
--- a/app/openvpn/sample/sample-config-files/loopback-server
+++ b/app/openvpn/sample/sample-config-files/loopback-server
@@ -17,10 +17,9 @@ dev null
verb 3
reneg-sec 10
tls-server
-dh sample-keys/dh1024.pem
+dh sample-keys/dh2048.pem
ca sample-keys/ca.crt
key sample-keys/server.key
cert sample-keys/server.crt
-cipher DES-EDE3-CBC
ping 1
inactive 120 10000000
diff --git a/app/openvpn/sample/sample-config-files/server.conf b/app/openvpn/sample/sample-config-files/server.conf
index 467d5b8a..701be3cc 100644
--- a/app/openvpn/sample/sample-config-files/server.conf
+++ b/app/openvpn/sample/sample-config-files/server.conf
@@ -81,10 +81,8 @@ key server.key # This file should be kept secret
# Diffie hellman parameters.
# Generate your own with:
-# openssl dhparam -out dh1024.pem 1024
-# Substitute 2048 for 1024 if you are using
-# 2048 bit keys.
-dh dh1024.pem
+# openssl dhparam -out dh2048.pem 2048
+dh dh2048.pem
# Network topology
# Should be subnet (addressing via IP)
diff --git a/app/openvpn/sample/sample-config-files/tls-office.conf b/app/openvpn/sample/sample-config-files/tls-office.conf
index f790f469..d1961444 100644
--- a/app/openvpn/sample/sample-config-files/tls-office.conf
+++ b/app/openvpn/sample/sample-config-files/tls-office.conf
@@ -26,7 +26,7 @@ up ./office.up
tls-server
# Diffie-Hellman Parameters (tls-server only)
-dh dh1024.pem
+dh dh2048.pem
# Certificate Authority file
ca my-ca.crt
diff --git a/app/openvpn/sample/sample-keys/README b/app/openvpn/sample/sample-keys/README
index 9f4f9187..66dd9454 100644
--- a/app/openvpn/sample/sample-keys/README
+++ b/app/openvpn/sample/sample-keys/README
@@ -1,14 +1,19 @@
Sample RSA and EC keys.
+Run ./gen-sample-keys.sh to generate fresh test keys.
+
See the examples section of the man page for usage examples.
NOTE: THESE KEYS ARE FOR TESTING PURPOSES ONLY.
DON'T USE THEM FOR ANY REAL WORK BECAUSE
THEY ARE TOTALLY INSECURE!
-ca.{crt,key} -- sample CA key/cert
-client.{crt,key} -- sample client key/cert
-server.{crt,key} -- sample server key/cert (nsCertType=server)
-pass.{crt,key} -- sample client key/cert with password-encrypted key
- password = "password"
-ec-*.{crt,key} -- sample elliptic curve variants of the above
+ca.{crt,key} -- sample CA key/cert
+server.{crt,key} -- sample server key/cert
+client.{crt,key} -- sample client key/cert
+client-pass.key -- sample client key with password-encrypted key
+ password = "password"
+client.p12 -- sample client pkcs12 bundle
+ password = "password"
+client-ec.{crt,key} -- sample elliptic curve client key/cert
+server-ec.{crt,key} -- sample elliptic curve server key/cert
diff --git a/app/openvpn/sample/sample-keys/ca.crt b/app/openvpn/sample/sample-keys/ca.crt
index e063ccce..a11bafa7 100644
--- a/app/openvpn/sample/sample-keys/ca.crt
+++ b/app/openvpn/sample/sample-keys/ca.crt
@@ -1,19 +1,35 @@
-----BEGIN CERTIFICATE-----
-MIIDBjCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJLRzEL
+MIIGKDCCBBCgAwIBAgIJAKFO3vqQ8q6BMA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNV
+BAYTAktHMQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMM
+T3BlblZQTi1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4w
+HhcNMTQxMDIyMjE1OTUyWhcNMjQxMDE5MjE1OTUyWjBmMQswCQYDVQQGEwJLRzEL
MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t
-VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTA0MTEy
-NTE0NDA1NVoXDTE0MTEyMzE0NDA1NVowZjELMAkGA1UEBhMCS0cxCzAJBgNVBAgT
-Ak5BMRAwDgYDVQQHEwdCSVNIS0VLMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxITAf
-BgkqhkiG9w0BCQEWEm1lQG15aG9zdC5teWRvbWFpbjCBnzANBgkqhkiG9w0BAQEF
-AAOBjQAwgYkCgYEAqPjWJnesPu6bR/iec4FMz3opVaPdBHxg+ORKNmrnVZPh0t8/
-ZT34KXkYoI9B82scurp8UlZVXG8JdUsz+yai8ti9+g7vcuyKUtcCIjn0HLgmdPu5
-gFX25lB0pXw+XIU031dOfPvtROdG5YZN5yCErgCy7TE7zntLnkEDuRmyU6cCAwEA
-AaOBwzCBwDAdBgNVHQ4EFgQUiaZg47rqPq/8ZH9MvYzSSI3gzEYwgZAGA1UdIwSB
-iDCBhYAUiaZg47rqPq/8ZH9MvYzSSI3gzEahaqRoMGYxCzAJBgNVBAYTAktHMQsw
-CQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMMT3BlblZQTi1U
-RVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW6CAQAwDAYDVR0T
-BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBfJoiWYrYdjM0mKPEzUQk0nLYTovBP
-I0es/2rfGrin1zbcFY+4dhVBd1E/StebnG+CP8r7QeEIwu7x8gYDdOLLsZn+2vBL
-e4jNU1ClI6Q0L7jrzhhunQ5mAaZztVyYwFB15odYcdN2iO0tP7jtEsvrRqxICNy3
-8itzViPTf5W4sA==
+VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsJVPCqt3vtoDW2U0DII1QIh2Qs0dqh88
+8nivxAIm2LTq93e9fJhsq3P/UVYAYSeCIrekXypR0EQgSgcNTvGBMe20BoHO5yvb
+GjKPmjfLj6XRotCOGy8EDl/hLgRY9efiA8wsVfuvF2q/FblyJQPR/gPiDtTmUiqF
+qXa7AJmMrqFsnWppOuGd7Qc6aTsae4TF1e/gUTCTraa7NeHowDaKhdyFmEEnCYR5
+CeUsx2JlFWAH8PCrxBpHYbmGyvS0kH3+rQkaSM/Pzc2bS4ayHaOYRK5XsGq8XiNG
+KTTLnSaCdPeHsI+3xMHmEh+u5Og2DFGgvyD22gde6W2ezvEKCUDrzR7bsnYqqyUy
+n7LxnkPXGyvR52T06G8KzLKQRmDlPIXhzKMO07qkHmIonXTdF7YI1azwHpAtN4dS
+rUe1bvjiTSoEsQPfOAyvD0RMK/CBfgEZUzAB50e/IlbZ84c0DJfUMOm4xCyft1HF
+YpYeyCf5dxoIjweCPOoP426+aTXM7kqq0ieIr6YxnKV6OGGLKEY+VNZh1DS7enqV
+HP5i8eimyuUYPoQhbK9xtDGMgghnc6Hn8BldPMcvz98HdTEH4rBfA3yNuCxLSNow
+4jJuLjNXh2QeiUtWtkXja7ec+P7VqKTduJoRaX7cs+8E3ImigiRnvmK+npk7Nt1y
+YE9hBRhSoLsCAwEAAaOB2DCB1TAdBgNVHQ4EFgQUK0DlyX319JY46S/jL9lAZMmO
+BZswgZgGA1UdIwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRoMGYxCzAJ
+BgNVBAYTAktHMQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UE
+ChMMT3BlblZQTi1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21h
+aW6CCQChTt76kPKugTAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG
+9w0BAQsFAAOCAgEABc77f4C4P8fIS+V8qCJmVNSDU44UZBc+D+J6ZTgW8JeOHUIj
+Bh++XDg3gwat7pIWQ8AU5R7h+fpBI9n3dadyIsMHGwSogHY9Gw7di2RVtSFajEth
+rvrq0JbzpwoYedMh84sJ2qI/DGKW9/Is9+O52fR+3z3dY3gNRDPQ5675BQ5CQW9I
+AJgLOqzD8Q0qrXYi7HaEqzNx6p7RDTuhFgvTd+vS5d5+28Z5fm2umnq+GKHF8W5P
+ylp2Js119FTVO7brusAMKPe5emc7tC2ov8OFFemQvfHR41PLryap2VD81IOgmt/J
+kX/j/y5KGux5HZ3lxXqdJbKcAq4NKYQT0mCkRD4l6szaCEJ+k0SiM9DdTcBDefhR
+9q+pCOyMh7d8QjQ1075mF7T+PGkZQUW1DUjEfrZhICnKgq+iEoUmM0Ee5WtRqcnu
+5BTGQ2mSfc6rV+Vr+eYXqcg7Nxb3vFXYSTod1UhefonVqwdmyJ2sC79zp36Tbo2+
+65NW2WJK7KzPUyOJU0U9bcu0utvDOvGWmG+aHbymJgcoFzvZmlXqMXn97pSFn4jV
+y3SLRgJXOw1QLXL2Y5abcuoBVr4gCOxxk2vBeVxOMRXNqSWZOFIF1bu/PxuDA+Sa
+hEi44aHbPXt9opdssz/hdGfd8Wo7vEJrbg7c6zR6C/Akav1Rzy9oohIdgOw=
-----END CERTIFICATE-----
diff --git a/app/openvpn/sample/sample-keys/ca.key b/app/openvpn/sample/sample-keys/ca.key
index b4bf792a..8b11bc22 100644
--- a/app/openvpn/sample/sample-keys/ca.key
+++ b/app/openvpn/sample/sample-keys/ca.key
@@ -1,15 +1,52 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQCo+NYmd6w+7ptH+J5zgUzPeilVo90EfGD45Eo2audVk+HS3z9l
-PfgpeRigj0Hzaxy6unxSVlVcbwl1SzP7JqLy2L36Du9y7IpS1wIiOfQcuCZ0+7mA
-VfbmUHSlfD5chTTfV058++1E50blhk3nIISuALLtMTvOe0ueQQO5GbJTpwIDAQAB
-AoGAQuVREyWp4bhhbZr2UFBOco2ws6EOLWp4kdD/uI+WSoEjlHKiDJj+GJ1CrL5K
-o+4yD5MpCQf4/4FOQ0ukprfjJpDwDinTG6vzuWSLTHNiTgvksW3vy7IsNMJx97hT
-4D2QOOl9HhA50Qqg70teMPYXOgLRMVsdCIV7p7zDNy4nM+ECQQDX8m5ZcQmPtUDA
-38dPTfpL4U7kMB94FItJYH/Lk5kMW1/J33xymNhL+BHaG064ol9n2ubGW4XEO5t2
-qE1IOsVpAkEAyE/x/OBVSI1s75aYGlEwMd87p3qaDdtXT7WzujjRY7r8Y1ynkMU6
-GtMeneBX/lk4BY/6I+5bhAzce+hqhaXejwJBAL5Wg+c4GApf41xdogqHm7doNyYw
-OHyZ9w9NDDc+uGbI30xLPSCxEe0cEXgiG6foDpm2uzRZFTWaqHPU8pFYpAkCQGNX
-cpWM0/7VVK9Fqk1y8knpgfY/UWOJ4jU/0dCLGR0ywLSuYNPlXDmtdkOp3TnhGW14
-x/9F2NEWZ8pzq1B4wHUCQQC5ztD4m/rpiIpinoewUJODoeBJXYBKqx1+mdrALCq6
-ESvK1WRiusMaY3xmsdv4J2TB5iUPryELbn3jU12WGcQc
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCwlU8Kq3e+2gNb
+ZTQMgjVAiHZCzR2qHzzyeK/EAibYtOr3d718mGyrc/9RVgBhJ4Iit6RfKlHQRCBK
+Bw1O8YEx7bQGgc7nK9saMo+aN8uPpdGi0I4bLwQOX+EuBFj15+IDzCxV+68Xar8V
+uXIlA9H+A+IO1OZSKoWpdrsAmYyuoWydamk64Z3tBzppOxp7hMXV7+BRMJOtprs1
+4ejANoqF3IWYQScJhHkJ5SzHYmUVYAfw8KvEGkdhuYbK9LSQff6tCRpIz8/NzZtL
+hrIdo5hErlewarxeI0YpNMudJoJ094ewj7fEweYSH67k6DYMUaC/IPbaB17pbZ7O
+8QoJQOvNHtuydiqrJTKfsvGeQ9cbK9HnZPTobwrMspBGYOU8heHMow7TuqQeYiid
+dN0XtgjVrPAekC03h1KtR7Vu+OJNKgSxA984DK8PREwr8IF+ARlTMAHnR78iVtnz
+hzQMl9Qw6bjELJ+3UcVilh7IJ/l3GgiPB4I86g/jbr5pNczuSqrSJ4ivpjGcpXo4
+YYsoRj5U1mHUNLt6epUc/mLx6KbK5Rg+hCFsr3G0MYyCCGdzoefwGV08xy/P3wd1
+MQfisF8DfI24LEtI2jDiMm4uM1eHZB6JS1a2ReNrt5z4/tWopN24mhFpftyz7wTc
+iaKCJGe+Yr6emTs23XJgT2EFGFKguwIDAQABAoICAQCEYPqnihI0PqZjnwQdGIQp
+g+P8gl7pyY9cS0OhUueicEbyDI8+V9qn0kcmx61zKDY0Jq4QNd6tnlUCijTc6Mot
+DwF2G1xsC4GvKxZiy89MOkhloanXETEeQZzDbbjvaM4UgL0AHLWPfZQRCjxbKXkE
+0A5phgvAr2YSvBLHCVXhGN0fScXnwXouVsvgVdGtpcTWdIUa+KrNdQBGDbz6VCkW
+31I76SQFy40d8PPX6ZjUJHDvnM14LycySO6XOkofRIVnXTqaOUiVBb2VKj5fX+Ro
+ILdWZz4d6J3RiGXYwyTr4SGVKLjgxWfgUGZB7x+NrqgugNzuaLYrkuWKSEN42nWq
+yoP6x6xtbAsmB6Fvdqwm/d8BmLhUweaVc0L7AYzXNsOBuT3kubJHMmu3Jv4xgyWk
+l/MAGJQc7i7QQweGgsYZgR8WlbkWkSFpUcgQBDzDibb6nsD2jnYijQrnrrmiEjEI
+R7MO551V+nFw9utiM8U9WIWwqzY0d98ujWkGjVe7uz9ZBVyg0DEAEj/zRi9T54aG
+1V6CB2Cjyw+HzzsDw7yWroWzo4U9YfjbPKCoBsXlqQFLFwY8oL6mEZ7UOobaV1Zl
+WtuHyYw3UNFxuSGPPyxJkFePIQLLvfKvh2R+V0DrT3UJRoKKlt9RejRSN0tOh0Cm
+2YD6d7T/DXnQHomIQKhKEQKCAQEA3sgsDg0eKDK8pUyVE+9wW5kql12nTzpBtnCM
+eg5J9OJcXKhCD/NIyUTIMXoMvZQpLwGUAYLgu4gE04zKWHDouf7MRSFltD5LJ7F2
+7nuYKHZXk0BhgMhdnQot3FKcOMrKCnZcM+RWX9ZJa8wO6whCaYCw7DtS0SSVODQk
+9EwAgX6/Hq60V7ujPZJCyNd3o0bIdAA/0AQRTZUADP3AHgUzh71aysYJt+UKt1v0
+Xc7l6hn7Dn7Ewzpf+WdZ2pV7d3JUSBVKiTDxLV904nDBNOxjMhz0rW01ojR6bzpn
+XhkFPqnmh+yEYGRgfSAAzkvSsSJEAtBFSicupA/6n83Lo2YvswKCAQEAyumuxP4Z
+a7s8x8DFba7vuQ+KVxpkKgEz1sxnGRNQJm18/ss/Y5JiaLFYT3E72VkQfBQ2ngu+
+GrJL3OhiNhzy1KLGS6mrwULtKiuud5MMQDL0Pvkncr9NTy4rBnWzhp2XyPeETu8n
+JpL2i2OK6lY/lgpBckXuap9gAl0fXk+y+BkZ71OoYaGnKpPjs+Xcq/qgPgZ7O3NW
+1g+Bd2AVPSxQpXjuy5rgtQURCN733vkNBzFedKREx7Z6l8UPlK/Exuc7BMIHfn5V
+dd0R3Th+82fkMNVJz6MKmHJ6CJI53M7co/YdAvIkxOFRIPGbO3arL2R69nRgAZBE
+zLawx1JJTRIG2QKCAQATtZXgMFzopYR3A011FAvWrrhL5+czZS4HG/Hxom38kkIl
+mGUv0BAybjlf1zJlW0RBelxDvfZv4Nq8dIo6RNLyEY601v2OcqxneJXTB3AwtDeP
+OXTm1dMiX5IrGcvkYlx5jHsfxCW4GNcqCEWRmYt2lgIRBDaRdjEVZdeXHVo2GqaB
+6mbeFCWe/t+VsSpOcaauTI9YseNt/66fd5uVjFRAwAnWQqr9b/AAxMvbuMAyc9X4
+NFLoCrQO9ovGgM8JhD3cmrWbaY8MupM2rU8KhZdJCbLD3ROPpCDo0jvu4TvLjXBt
+ugkEFh1LNJedqKudLDDkJtTaeJjxvtAnbyeC7zltAoIBAC9TIyzUqq8io0FfZ2x2
+cXiy9CvuftABKcr+L0l85KOhw5ZVZvpdKNCMFDGrEi9WA28886QWzwbA8Mqb9FP0
+mnoXYLJC50kSx+ee+nju9dt/RtHtIFM15N0DwosmJnHODZmUiOo0AuiPPCs0UzDm
+Xrwqtirlvn5ln2nNuEQxyGbuy8qys0HaBvf6OBA8GySNNpRgxJsQAn+4bBSgdzOm
+Q0TkmKUqASCXBusPvbXmVjCIRiRkL5p4p8z/6+tct0NAqNYqPr80zc/IeKMkyw8P
++vucszNXLmBxyp53JEGoiXNAMnH+ca7tchOB5hePTMun3rneWInk0PcB4OcL/QaZ
+nrkCggEBAN67+SvcWtM1BoLXSz5/apFAE+DicCv94PrvMBOhfvu1oBrElR1rBjiN
+2B83SktkF4WhCXr10GP+RUpjaqPBtT7NW4r3fL5B8EPsHeabL+pg9e6wG1rH8GqG
+toWecmfC9uqK7l1A59h5Oveq5K19bZTRZRjQtv2e4KQknlJR6cwy+TGUU5kAUlMt
+vcivyjzxc0UQwq7zKktJq+xW/TZiSLgd3B32p0sXX378qFUJ4SO2UZ1OCh8R7PY1
+Fx25K/89Q1yGdbYiXb/Dx0a2WB9rP+b6alMl/dxPdqDKj2QXXkdh8+yvhVpQTyZw
+B1RaqQXwzqrCH0F/vw3lRceYhcQvzcQ=
+-----END PRIVATE KEY-----
diff --git a/app/openvpn/sample/sample-keys/client-ec.crt b/app/openvpn/sample/sample-keys/client-ec.crt
new file mode 100644
index 00000000..759dabae
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/client-ec.crt
@@ -0,0 +1,85 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4 (0x4)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain
+ Validity
+ Not Before: Oct 22 21:59:53 2014 GMT
+ Not After : Oct 19 21:59:53 2024 GMT
+ Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Client-EC/emailAddress=me@myhost.mydomain
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:3b:ce:62:5d:6f:87:82:75:24:c2:58:f5:0e:88:
+ 4d:57:0d:06:b2:71:88:87:58:19:bb:de:5f:7f:52:
+ 62:51:a2:48:91:83:48:91:90:3e:87:02:0f:15:51:
+ f9:68:97:12:0a:fd:d2:3c:87:83:4b:65:54:00:44:
+ 8d:28:76:49:05
+ ASN1 OID: secp256k1
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 64:F6:49:88:E7:74:C1:AB:A5:FA:4F:2B:71:3C:25:13:3D:C8:94:C5
+ X509v3 Authority Key Identifier:
+ keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B
+ DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain
+ serial:A1:4E:DE:FA:90:F2:AE:81
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 32:3d:f0:08:67:dd:03:73:76:cc:76:52:0a:f6:97:d1:c6:fa:
+ 5f:d3:e6:28:c9:75:a7:08:a8:34:49:69:cf:eb:ab:da:86:b3:
+ 2e:65:17:ee:7e:b6:b5:6b:15:0b:dc:11:3a:b9:5a:b3:80:b8:
+ bb:f4:6c:cf:88:3a:10:83:7e:10:a0:82:87:6e:06:ec:78:62:
+ d4:d1:44:27:dd:2c:19:d8:1a:a1:ae:f4:a0:00:7f:53:5a:40:
+ 8a:c2:83:77:4b:26:7d:53:b0:d3:0f:2f:7c:28:70:ef:74:58:
+ 5b:de:81:94:4c:63:19:f0:79:cb:6c:b2:ec:32:1b:4b:e4:62:
+ 22:4f:ad:ac:4a:6f:a9:6e:c4:2a:8d:8a:88:19:09:fd:88:93:
+ 3c:27:4d:91:95:ff:57:84:13:fd:4a:68:db:20:df:10:e6:81:
+ 1d:fd:e7:1d:35:fb:19:02:dd:b5:5f:a0:c1:07:ec:74:b4:ef:
+ 8b:f9:33:9a:f2:a6:3b:6e:b6:4a:52:ab:5d:99:76:64:62:c4:
+ d5:3a:c6:81:8d:eb:c8:4b:02:af:e1:ca:60:e9:8d:c7:a9:2b:
+ ea:4f:56:31:d3:9a:11:c2:9c:83:5c:a2:8d:98:fe:cc:a5:ad:
+ 1f:51:c4:6e:cf:ff:a0:51:64:c8:7f:7f:32:05:4c:8d:7f:bf:
+ b8:ed:e5:81:5f:81:bd:1d:9b:3f:8a:83:27:26:b4:69:84:8b:
+ e5:d9:ea:fd:08:a8:aa:e4:3a:dc:29:4d:80:6c:13:f7:45:ce:
+ 92:f2:a9:f3:5f:90:83:d6:23:0f:50:e5:40:09:4c:6b:f2:73:
+ aa:d8:49:a7:a9:81:6e:bb:f2:e4:a5:7f:19:39:1d:65:f3:11:
+ 97:b1:2b:7c:2f:36:77:7f:75:fd:88:44:90:7c:f2:33:8d:cd:
+ 2c:f6:76:60:33:d3:f4:b3:8c:81:d7:85:89:cc:d7:d5:2c:94:
+ a9:31:3f:d3:63:a7:dc:82:3f:0a:d8:c5:71:97:69:3b:c1:69:
+ cb:f0:1b:be:15:c0:be:aa:fd:e8:13:2c:0c:3f:72:7b:7d:9c:
+ 3b:7f:b8:82:36:4b:ad:4d:16:19:b9:1c:b3:2d:d7:5f:8b:f8:
+ 14:ce:d4:13:e5:82:7a:1d:40:28:08:65:4a:19:d7:7a:35:09:
+ db:36:48:4b:96:44:bd:1f:12:b2:39:08:1e:5b:66:25:9b:e0:
+ 16:d3:79:05:e3:f6:90:da:95:95:33:a1:53:a8:3c:a9:f0:b2:
+ f5:d0:aa:80:a0:96:ca:8c:45:62:c2:74:04:91:68:27:fb:e9:
+ 97:be:3a:87:8a:85:28:2d:6e:a9:60:9b:63:ba:65:98:5e:bb:
+ 02:ee:ac:ba:be:f6:42:26
+-----BEGIN CERTIFICATE-----
+MIIESTCCAjGgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL
+MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t
+VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy
+MjIxNTk1M1oXDTI0MTAxOTIxNTk1M1owbTELMAkGA1UEBhMCS0cxCzAJBgNVBAgT
+Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFzAVBgNVBAMTDlRlc3QtQ2xpZW50
+LUVDMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wVjAQBgcqhkjO
+PQIBBgUrgQQACgNCAAQ7zmJdb4eCdSTCWPUOiE1XDQaycYiHWBm73l9/UmJRokiR
+g0iRkD6HAg8VUflolxIK/dI8h4NLZVQARI0odkkFo4HIMIHFMAkGA1UdEwQCMAAw
+HQYDVR0OBBYEFGT2SYjndMGrpfpPK3E8JRM9yJTFMIGYBgNVHSMEgZAwgY2AFCtA
+5cl99fSWOOkv4y/ZQGTJjgWboWqkaDBmMQswCQYDVQQGEwJLRzELMAkGA1UECBMC
+TkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4tVEVTVDEhMB8G
+CSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluggkAoU7e+pDyroEwDQYJKoZI
+hvcNAQELBQADggIBADI98Ahn3QNzdsx2Ugr2l9HG+l/T5ijJdacIqDRJac/rq9qG
+sy5lF+5+trVrFQvcETq5WrOAuLv0bM+IOhCDfhCggoduBux4YtTRRCfdLBnYGqGu
+9KAAf1NaQIrCg3dLJn1TsNMPL3wocO90WFvegZRMYxnwectssuwyG0vkYiJPraxK
+b6luxCqNiogZCf2IkzwnTZGV/1eEE/1KaNsg3xDmgR395x01+xkC3bVfoMEH7HS0
+74v5M5rypjtutkpSq12ZdmRixNU6xoGN68hLAq/hymDpjcepK+pPVjHTmhHCnINc
+oo2Y/sylrR9RxG7P/6BRZMh/fzIFTI1/v7jt5YFfgb0dmz+KgycmtGmEi+XZ6v0I
+qKrkOtwpTYBsE/dFzpLyqfNfkIPWIw9Q5UAJTGvyc6rYSaepgW678uSlfxk5HWXz
+EZexK3wvNnd/df2IRJB88jONzSz2dmAz0/SzjIHXhYnM19UslKkxP9Njp9yCPwrY
+xXGXaTvBacvwG74VwL6q/egTLAw/cnt9nDt/uII2S61NFhm5HLMt11+L+BTO1BPl
+gnodQCgIZUoZ13o1Cds2SEuWRL0fErI5CB5bZiWb4BbTeQXj9pDalZUzoVOoPKnw
+svXQqoCglsqMRWLCdASRaCf76Ze+OoeKhSgtbqlgm2O6ZZheuwLurLq+9kIm
+-----END CERTIFICATE-----
diff --git a/app/openvpn/sample/sample-keys/client-ec.key b/app/openvpn/sample/sample-keys/client-ec.key
new file mode 100644
index 00000000..81313800
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/client-ec.key
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQg2RVk/d0yok086M9bLPIi
+eu4DfcBUwphOnkje1/7VSY+hRANCAAQ7zmJdb4eCdSTCWPUOiE1XDQaycYiHWBm7
+3l9/UmJRokiRg0iRkD6HAg8VUflolxIK/dI8h4NLZVQARI0odkkF
+-----END PRIVATE KEY-----
diff --git a/app/openvpn/sample/sample-keys/client-pass.key b/app/openvpn/sample/sample-keys/client-pass.key
new file mode 100644
index 00000000..2bb8d4e9
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/client-pass.key
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,ECC1F209896FC2621233FFF6F1FFD045
+
+i6t7VKTyNNELTvrBO464e02nFg9rvYwumxd0sfqcPtaKmRK2mrZmEd/Xh0Nv1WyB
+PyuJo78qQixAtxObRbkSNINzTr5C8IDrE6+wQYCJinvO54U0o+ksv0tsyLngz1cb
+is8ZqHXrRgJ3qGFQWmFRtFKFQvSXOTDX3fLkEB53HfeblQCxBCnJ82Sp7ivnVR/j
+Q8qQRy1RMbzIN0trEGf0Zi4tHEvXL1u7Y+olQzSlmWWaQt20hhXUOMLhMtlRsAo7
+AwjlE94JjAfJ1q1dwIcRN4c9Lk8GkiX6w7nDpRACDpk2S8ifCqi69eGe4+g7owhL
+74bgs64PmM9a2sNXy1v6WE3c/t6sSrZiMvrGsqMo4sBlrQ9WXe0Naon7heBkPcdS
+px0YJjnyBXHMIH+ASmALSJ5JXq9vt2xRFf0dOsGapxhP+7bZJ5Pwyk/yUu5uHFbM
+/aBemlrZJzlKeYiiwpwx2whQAtDwN41zMG+r27EzSU/AaDV40NPiwwycpWt/Bp1e
+z1ag0JuS0an+PK4jmREtzT5U5BeAVM91x8YttOPpmUIpahAa1zwdYPRAIkbmPJ4z
+ZH+9YoPH4hoBQKdIhshYktjdI++xNiKXAUGUz5YoX8S68SsLdmKvhnQ7fu5VvOkA
+2pb7taXGy7zfn+a/fWauhuceV9HPlAXMIu3GsssODoNly3vpcFeiMySKppygJ3Eg
+A3o9n8UepD+jXflKG/R/t7U3hT6LqSIvQWqBqYMEVFMCNzSsJ/ce/4veFvx343zT
+qdxuzYqyiXM74cynpfqHdVa9SFICTesNdVDI0FdOXhSQ4bHJc7Xp9FFJdS0lMRw4
+ACwKxvs8lo4Gx1WFyCqH5OxosKtDHQYzdUJfSWVJlhhOFR3GncR9qSe3O5fkhJfs
+TALnC+xTJyCkSB2k0/bxVLIhlkPdCwzsrN/B6X2CDBdg0mQIo0LaPzGF8VneM20d
+XebYn751XSiL3HKyq8G5AEFwj9AO3Q8gKuP2fPoWdngJ2GT+mt1m2fIw9Igu39J0
+ZMegyUN0wSIiA5AkgryK9U+PJEiJmLzOJ/NGr7E5tPF18eZWapK4KZ8TXC4RNiye
+g+apGa+xZJz2VQp/Mrcdj9D4UDJFQjrvKaS0PXJDoYUXFBoMv3rxijzRVxlhhuJY
+yZ0At+UqZD5wpuWW6DRrgJIpy0HNhbaLmgsU0Co0HKviB0x8hvMJbi/uCoPTOdPz
+sPB7CN2i3oXe7xw1HfSTSFWb4leqjlKwNgfV42ox0QUjkkADeeuY+56g/B2+QmdE
+vXrc6sDwfNUwRUzeMn8yfum/aW1y/wrqF/qPTBQqFd85vlzS+NfXIKDg04cAljTu
++2BLzvizh9Bb68iG4PykNXbjbAir1EbQG1tCzq1eKhERjgrxdv6+XqAmvchMCeL5
+L6hvfQFBPCo/4xnMpU5wooFarO/kGdKlGr5rXOydgfL618Td18BIX+FHQFb3zzVU
+y2NR4++DslJAZgAU+512zzpW1m3JtaRoyqyoLE2YFPlW804Xc1PBB3Ix6Wyzcegy
+D4qMk5qxjBkXEsBBSCYfVbWoMBeMhnvxkz0b9wkPtAW/jEJCB2Kkn/5yMC0DkePO
+-----END RSA PRIVATE KEY-----
diff --git a/app/openvpn/sample/sample-keys/client.crt b/app/openvpn/sample/sample-keys/client.crt
index c0474461..1744cb22 100644
--- a/app/openvpn/sample/sample-keys/client.crt
+++ b/app/openvpn/sample/sample-keys/client.crt
@@ -2,64 +2,102 @@ Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2 (0x2)
- Signature Algorithm: md5WithRSAEncryption
+ Signature Algorithm: sha256WithRSAEncryption
Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain
Validity
- Not Before: Nov 25 14:46:49 2004 GMT
- Not After : Nov 23 14:46:49 2014 GMT
+ Not Before: Oct 22 21:59:53 2014 GMT
+ Not After : Oct 19 21:59:53 2024 GMT
Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Client/emailAddress=me@myhost.mydomain
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:d2:12:5c:c6:4d:13:34:ae:cf:fa:ab:fe:cb:de:
- 8c:f1:4b:4a:95:28:60:87:82:2c:b8:c1:e5:8e:c6:
- 5d:11:58:61:a4:a5:f1:42:d7:86:74:6c:9d:9c:7a:
- f0:3a:5c:29:e6:53:3b:5e:6d:d8:f0:45:06:2c:23:
- ee:09:bc:02:8f:0e:b8:d5:33:1f:c3:4a:11:02:48:
- 0b:cc:4b:ad:6e:74:e0:a2:53:b1:d6:cc:89:b9:e2:
- 6f:db:15:b3:19:1e:57:04:79:48:3a:da:76:31:fc:
- bf:d3:34:21:e7:32:d8:9e:06:4e:be:f3:e3:79:b0:
- 54:fd:d1:42:32:aa:3e:7a:c1
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ec:65:8f:e9:12:c2:1a:5b:e6:56:2a:08:a9:82:
+ 3a:2d:44:78:a3:00:3b:b0:9f:e7:27:10:40:93:ef:
+ f1:cc:3e:a0:aa:04:a2:80:1b:13:a9:e6:fe:81:d6:
+ 70:90:a8:d8:d4:de:30:d8:35:00:d2:be:62:f0:48:
+ da:fc:15:8d:c4:c6:6d:0b:99:f1:2b:83:00:0a:d3:
+ 2a:23:0b:e5:cd:f9:35:df:43:61:15:72:ad:95:98:
+ f6:73:21:41:5e:a0:dd:47:27:a0:d5:9a:d4:41:a8:
+ 1c:1d:57:20:71:17:8f:f7:28:9e:3e:07:ce:ec:d5:
+ 0e:42:4f:1e:74:47:8e:47:9d:d2:14:28:27:2c:14:
+ 10:f5:d1:96:b5:93:74:84:ef:f9:04:de:8d:4a:6f:
+ df:77:ab:ea:d1:58:d3:44:fe:5a:04:01:ff:06:7a:
+ 97:f7:fd:e3:57:48:e1:f0:df:40:13:9f:66:23:5a:
+ e3:55:54:3d:54:39:ee:00:f9:12:f1:d2:df:74:2e:
+ ba:d7:f0:8d:c6:dd:18:58:1c:93:22:0b:75:fa:a8:
+ d6:e0:b5:2f:2d:b9:d4:fe:b9:4f:86:e2:75:48:16:
+ 60:fb:3f:c9:b4:30:42:29:fb:3b:b3:2b:b9:59:81:
+ 6a:46:f3:45:83:bf:fd:d5:1a:ff:37:0c:6f:5b:fd:
+ 61:f1
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
- Netscape Comment:
- OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
- 17:B7:3F:C7:62:A0:A9:FD:A4:31:0E:58:D7:D9:94:7B:4B:3F:CB:56
+ D2:B4:36:0F:B1:FC:DD:A5:EA:2A:F7:C7:23:89:FA:E3:FA:7A:44:1D
X509v3 Authority Key Identifier:
- keyid:89:A6:60:E3:BA:EA:3E:AF:FC:64:7F:4C:BD:8C:D2:48:8D:E0:CC:46
+ keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B
DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain
- serial:00
+ serial:A1:4E:DE:FA:90:F2:AE:81
- Signature Algorithm: md5WithRSAEncryption
- 61:c6:d1:fa:24:0f:c7:be:09:3b:d8:04:17:63:31:17:07:f9:
- 56:99:af:4c:67:fa:db:cb:94:cf:55:a5:7b:16:20:8b:42:64:
- 13:23:62:45:28:93:5e:36:f7:db:02:95:a1:e9:fd:e3:0f:8d:
- 73:a1:7b:0e:55:78:4d:a5:c4:b7:22:12:a0:ee:55:e0:b8:0e:
- c9:9b:12:e3:b0:ef:9b:68:93:57:6e:6c:ad:16:68:8e:8d:30:
- 33:fe:2a:1b:c3:03:8f:b6:0a:2d:0c:b1:3c:bb:f9:58:3f:8c:
- 81:59:6b:14:dd:62:b5:c2:93:ed:5d:c6:19:0f:9b:4b:52:b3:
- 7c:78
+ Signature Algorithm: sha256WithRSAEncryption
+ 7f:e0:fe:84:a7:ec:df:62:a5:cd:3c:c1:e6:42:b1:31:12:f0:
+ b9:da:a7:9e:3f:bd:96:52:b6:fc:55:74:64:3e:e4:ff:7e:aa:
+ f7:3e:06:18:5f:73:85:f8:c8:e0:67:1b:4d:97:ca:05:d0:37:
+ 07:33:64:9b:e6:78:77:14:9a:55:bb:2a:ac:c3:7f:c9:15:08:
+ 83:5c:c8:c2:61:d3:71:4c:05:0b:2b:cb:a3:87:6d:a0:32:ed:
+ b0:b3:27:97:4a:55:8d:01:2a:30:56:68:ab:f2:da:5c:10:73:
+ c9:aa:0a:9c:4b:4c:a0:5b:51:6e:0a:7e:6c:53:80:b0:00:e1:
+ 1e:9a:4c:0a:37:9e:20:89:bc:c5:e5:79:58:b7:45:ff:d3:c4:
+ a1:fd:d9:78:3d:45:16:74:df:82:44:1d:1d:81:50:5a:b9:32:
+ 4c:e2:4f:3f:0e:3a:65:5a:64:83:3b:29:31:c4:99:88:bc:c5:
+ 84:39:f2:19:12:e1:66:d0:ea:fb:75:b1:d2:27:be:91:59:a3:
+ 2b:09:d5:5c:bf:46:8e:d6:67:d6:0b:ec:da:ab:f0:80:19:87:
+ 64:07:a9:77:b1:5e:0c:e2:c5:1d:6a:ac:5d:23:f3:30:75:36:
+ 4e:ca:c3:4e:b0:4d:8c:2c:ce:52:61:63:de:d5:f5:ef:ef:0a:
+ 6b:23:25:26:3c:3a:f2:c3:c2:16:19:3f:a9:32:ba:68:f9:c9:
+ 12:3c:3e:c6:1f:ff:9b:4e:f4:90:b0:63:f5:d1:33:00:30:5a:
+ e8:24:fa:35:44:9b:6a:80:f3:a6:cc:7b:3c:73:5f:50:c4:30:
+ 71:d8:74:90:27:0a:01:4e:a5:5e:b1:f8:da:c2:61:81:11:ae:
+ 29:a3:8f:fa:7e:4c:4e:62:b1:00:de:92:e3:8f:6a:2e:da:d9:
+ 38:5d:6b:7c:0d:e4:01:aa:c8:c6:6d:8b:cd:c0:c8:6e:e4:57:
+ 21:8a:f6:46:30:d9:ad:51:a1:87:96:a6:53:c9:1e:c6:bb:c3:
+ eb:55:fe:8c:d6:5c:d5:c6:f3:ca:b0:60:d2:d4:2a:1f:88:94:
+ d3:4c:1a:da:0c:94:fe:c1:5d:0d:2a:db:99:29:5d:f6:dd:16:
+ c4:c8:4d:74:9e:80:d9:d0:aa:ed:7b:e3:30:e4:47:d8:f5:15:
+ c1:71:b8:c6:fd:ee:fc:9e:b2:5f:b5:b7:92:ed:ff:ca:37:f6:
+ c7:82:b4:54:13:9b:83:cd:87:8b:7e:64:f6:2e:54:3a:22:b1:
+ c5:c1:f4:a5:25:53:9a:4d:a8:0f:e7:35:4b:89:df:19:83:66:
+ 64:d9:db:d1:61:2b:24:1b:1d:44:44:fb:49:30:87:b7:49:23:
+ 08:02:8a:e0:25:f3:f4:43
-----BEGIN CERTIFICATE-----
-MIIDNTCCAp6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJLRzEL
+MIIFFDCCAvygAwIBAgIBAjANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL
MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t
-VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTA0MTEy
-NTE0NDY0OVoXDTE0MTEyMzE0NDY0OVowajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT
+VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy
+MjIxNTk1M1oXDTI0MTAxOTIxNTk1M1owajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT
Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFDASBgNVBAMTC1Rlc3QtQ2xpZW50
-MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBANISXMZNEzSuz/qr/svejPFLSpUoYIeCLLjB5Y7GXRFY
-YaSl8ULXhnRsnZx68DpcKeZTO15t2PBFBiwj7gm8Ao8OuNUzH8NKEQJIC8xLrW50
-4KJTsdbMibnib9sVsxkeVwR5SDradjH8v9M0Iecy2J4GTr7z43mwVP3RQjKqPnrB
-AgMBAAGjge4wgeswCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBH
-ZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFBe3P8dioKn9pDEOWNfZlHtL
-P8tWMIGQBgNVHSMEgYgwgYWAFImmYOO66j6v/GR/TL2M0kiN4MxGoWqkaDBmMQsw
-CQYDVQQGEwJLRzELMAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNV
-BAoTDE9wZW5WUE4tVEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9t
-YWluggEAMA0GCSqGSIb3DQEBBAUAA4GBAGHG0fokD8e+CTvYBBdjMRcH+VaZr0xn
-+tvLlM9VpXsWIItCZBMjYkUok14299sClaHp/eMPjXOhew5VeE2lxLciEqDuVeC4
-DsmbEuOw75tok1dubK0WaI6NMDP+KhvDA4+2Ci0MsTy7+Vg/jIFZaxTdYrXCk+1d
-xhkPm0tSs3x4
+MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDsZY/pEsIaW+ZWKgipgjotRHijADuwn+cnEECT
+7/HMPqCqBKKAGxOp5v6B1nCQqNjU3jDYNQDSvmLwSNr8FY3Exm0LmfErgwAK0yoj
+C+XN+TXfQ2EVcq2VmPZzIUFeoN1HJ6DVmtRBqBwdVyBxF4/3KJ4+B87s1Q5CTx50
+R45HndIUKCcsFBD10Za1k3SE7/kE3o1Kb993q+rRWNNE/loEAf8Gepf3/eNXSOHw
+30ATn2YjWuNVVD1UOe4A+RLx0t90LrrX8I3G3RhYHJMiC3X6qNbgtS8tudT+uU+G
+4nVIFmD7P8m0MEIp+zuzK7lZgWpG80WDv/3VGv83DG9b/WHxAgMBAAGjgcgwgcUw
+CQYDVR0TBAIwADAdBgNVHQ4EFgQU0rQ2D7H83aXqKvfHI4n64/p6RB0wgZgGA1Ud
+IwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRoMGYxCzAJBgNVBAYTAktH
+MQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMMT3BlblZQ
+Ti1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW6CCQChTt76
+kPKugTANBgkqhkiG9w0BAQsFAAOCAgEAf+D+hKfs32KlzTzB5kKxMRLwudqnnj+9
+llK2/FV0ZD7k/36q9z4GGF9zhfjI4GcbTZfKBdA3BzNkm+Z4dxSaVbsqrMN/yRUI
+g1zIwmHTcUwFCyvLo4dtoDLtsLMnl0pVjQEqMFZoq/LaXBBzyaoKnEtMoFtRbgp+
+bFOAsADhHppMCjeeIIm8xeV5WLdF/9PEof3ZeD1FFnTfgkQdHYFQWrkyTOJPPw46
+ZVpkgzspMcSZiLzFhDnyGRLhZtDq+3Wx0ie+kVmjKwnVXL9GjtZn1gvs2qvwgBmH
+ZAepd7FeDOLFHWqsXSPzMHU2TsrDTrBNjCzOUmFj3tX17+8KayMlJjw68sPCFhk/
+qTK6aPnJEjw+xh//m070kLBj9dEzADBa6CT6NUSbaoDzpsx7PHNfUMQwcdh0kCcK
+AU6lXrH42sJhgRGuKaOP+n5MTmKxAN6S449qLtrZOF1rfA3kAarIxm2LzcDIbuRX
+IYr2RjDZrVGhh5amU8kexrvD61X+jNZc1cbzyrBg0tQqH4iU00wa2gyU/sFdDSrb
+mSld9t0WxMhNdJ6A2dCq7XvjMORH2PUVwXG4xv3u/J6yX7W3ku3/yjf2x4K0VBOb
+g82Hi35k9i5UOiKxxcH0pSVTmk2oD+c1S4nfGYNmZNnb0WErJBsdRET7STCHt0kj
+CAKK4CXz9EM=
-----END CERTIFICATE-----
diff --git a/app/openvpn/sample/sample-keys/client.key b/app/openvpn/sample/sample-keys/client.key
index 17b95091..6d31489a 100644
--- a/app/openvpn/sample/sample-keys/client.key
+++ b/app/openvpn/sample/sample-keys/client.key
@@ -1,15 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQDSElzGTRM0rs/6q/7L3ozxS0qVKGCHgiy4weWOxl0RWGGkpfFC
-14Z0bJ2cevA6XCnmUztebdjwRQYsI+4JvAKPDrjVMx/DShECSAvMS61udOCiU7HW
-zIm54m/bFbMZHlcEeUg62nYx/L/TNCHnMtieBk6+8+N5sFT90UIyqj56wQIDAQAB
-AoGBAK8RoIGekCfym99DYYfTg9A/t/tQeAnWYaDj7oSrKbqf1lgZ91OGPEZgkoVr
-KzLnxf9uU+bhUs8CJx+4HdO8/L9rAJA+oD9QNuMp0elN4AKuEGE1Eq3a0e3cmgPI
-+VIoXM6WVAGgK9I03Zu/UerYQ/DdXWGOIsKhFe8qyQoG9pKxAkEA9ld6O9MHQt3d
-JAjJkgCNn4psozxjrfLWy2huXd3H3CRqGMjLITDGzdkVSgXjHokBYroi0+TZTu4M
-ulJSJaWwBQJBANpO2DAexH2zRHw5Z6QyeEVxz7B3/FzU4GgJx9BH+FSBh+F0G5Ln
-ir5Vst8vZ/LGcgpYjHQLNAvZVgUjiQ4Y6I0CQGvwMJL+CHR4GmmroAblTyjU0n1D
-/Lk/anZ+L73Za7U+D28ErFzCrpmLwRRKOBYtGfpUbOZDpCQ9kj4hy/TLALECQCcL
-9ysUNbzt9Y/qjJkX1d9F7gn4TBEmmkTBixW76bTjvjQbGlt6Qpyso2O8DPGlgPxM
-vkJ7RoHgC7y7kGYPGnkCQBVxSNGIjLx4NQBgN4HD0y4+fars1PTUGnckBcS4npb9
-onLNyerBlWdBwbARyBS7WPIbyyf5VCrn3yIqWxaARO0=
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDsZY/pEsIaW+ZW
+KgipgjotRHijADuwn+cnEECT7/HMPqCqBKKAGxOp5v6B1nCQqNjU3jDYNQDSvmLw
+SNr8FY3Exm0LmfErgwAK0yojC+XN+TXfQ2EVcq2VmPZzIUFeoN1HJ6DVmtRBqBwd
+VyBxF4/3KJ4+B87s1Q5CTx50R45HndIUKCcsFBD10Za1k3SE7/kE3o1Kb993q+rR
+WNNE/loEAf8Gepf3/eNXSOHw30ATn2YjWuNVVD1UOe4A+RLx0t90LrrX8I3G3RhY
+HJMiC3X6qNbgtS8tudT+uU+G4nVIFmD7P8m0MEIp+zuzK7lZgWpG80WDv/3VGv83
+DG9b/WHxAgMBAAECggEBAIOdaCpUD02trOh8LqZxowJhBOl7z7/ex0uweMPk67LT
+i5AdVHwOlzwZJ8oSIknoOBEMRBWcLQEojt1JMuL2/R95emzjIKshHHzqZKNulFvB
+TIUpdnwChTKtH0mqUkLlPU3Ienty4IpNlpmfUKimfbkWHERdBJBHbtDsTABhdo3X
+9pCF/yRKqJS2Fy/Mkl3gv1y/NB1OL4Jhl7vQbf+kmgfQN2qdOVe2BOKQ8NlPUDmE
+/1XNIDaE3s6uvUaoFfwowzsCCwN2/8QrRMMKkjvV+lEVtNmQdYxj5Xj5IwS0vkK0
+6icsngW87cpZxxc1zsRWcSTloy5ohub4FgKhlolmigECgYEA+cBlxzLvaMzMlBQY
+kCac9KQMvVL+DIFHlZA5i5L/9pRVp4JJwj3GUoehFJoFhsxnKr8HZyLwBKlCmUVm
+VxnshRWiAU18emUmeAtSGawlAS3QXhikVZDdd/L20YusLT+DXV81wlKR97/r9+17
+klQOLkSdPm9wcMDOWMNHX8bUg8kCgYEA8k+hQv6+TR/+Beao2IIctFtw/EauaJiJ
+wW5ql1cpCLPMAOQUvjs0Km3zqctfBF8mUjdkcyJ4uhL9FZtfywY22EtRIXOJ/8VR
+we65mVo6RLR8YVM54sihanuFOnlyF9LIBWB+9pUfh1/Y7DSebh7W73uxhAxQhi3Y
+QwfIQIFd8OkCgYBalH4VXhLYhpaYCiXSej6ot6rrK2N6c5Tb2MAWMA1nh+r84tMP
+gMoh+pDgYPAqMI4mQbxUmqZEeoLuBe6VHpDav7rPECRaW781AJ4ZM4cEQ3Jz/inz
+4qOAMn10CF081/Ez9ykPPlU0bsYNWHNd4eB2xWnmUBKOwk7UgJatVPaUiQKBgQCI
+f18CVGpzG9CHFnaK8FCnMNOm6VIaTcNcGY0mD81nv5Dt943P054BQMsAHTY7SjZW
+HioRyZtkhonXAB2oSqnekh7zzxgv4sG5k3ct8evdBCcE1FNJc2eqikZ0uDETRoOy
+s7cRxNNr+QxDkyikM+80HOPU1PMPgwfOSrX90GJQ8QKBgEBKohGMV/sNa4t14Iau
+qO8aagoqh/68K9GFXljsl3/iCSa964HIEREtW09Qz1w3dotEgp2w8bsDa+OwWrLy
+0SY7T5jRViM3cDWRlUBLrGGiL0FiwsfqiRiji60y19erJgrgyGVIb1kIgIBRkgFM
+2MMweASzTmZcri4PA/5C0HYb
+-----END PRIVATE KEY-----
diff --git a/app/openvpn/sample/sample-keys/client.p12 b/app/openvpn/sample/sample-keys/client.p12
new file mode 100644
index 00000000..8458c797
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/client.p12
Binary files differ
diff --git a/app/openvpn/sample/sample-keys/dh2048.pem b/app/openvpn/sample/sample-keys/dh2048.pem
new file mode 100644
index 00000000..8eda59aa
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/dh2048.pem
@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEArdnA32xujHPlPI+jPffHSoMUZ+b5gRz1H1Lw9//Gugm5TAsRiYrB
+t2BDSsMKvAjyqN+i5SJv4TOk98kRRKB27iPvyXmiL945VaDQl/UehCySjYlGFUjW
+9nuo+JwQxeSbw0TLiSYoYJZQ8X1CxPl9mgJl277O4cW1Gc8I/bWa+ipU/4K5wv3h
+GI8nt+6A0jN3M/KebotMP101G4k0l0qsY4oRMTmP+z3oAP0qU9NZ1jiuMFVzRlNp
+5FdYF7ctrH+tBF+QmyT4SRKSED4wE4oX6gp420NaBhIEQifIj75wlMDtxQlpkN+x
+QkjsEbPlaPKHGQ4uupssChVUi8IM2yq5EwIBAg==
+-----END DH PARAMETERS-----
diff --git a/app/openvpn/sample/sample-keys/gen-sample-keys.sh b/app/openvpn/sample/sample-keys/gen-sample-keys.sh
new file mode 100755
index 00000000..414687eb
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/gen-sample-keys.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# Run this script to set up a test CA, and test key-certificate pair for a
+# server, and various clients.
+#
+# Copyright (C) 2014 Steffan Karger <steffan@karger.me>
+set -eu
+
+command -v openssl >/dev/null 2>&1 || { echo >&2 "Unable to find openssl. Please make sure openssl is installed and in your path."; exit 1; }
+
+if [ ! -f openssl.cnf ]
+then
+ echo "Please run this script from the sample directory"
+ exit 1
+fi
+
+# Create required directories and files
+mkdir -p sample-ca
+rm -f sample-ca/index.txt
+touch sample-ca/index.txt
+echo "01" > sample-ca/serial
+
+# Generate CA key and cert
+openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 \
+ -extensions easyrsa_ca -keyout sample-ca/ca.key -out sample-ca/ca.crt \
+ -subj "/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain" \
+ -config openssl.cnf
+
+# Create server key and cert
+openssl req -new -nodes -config openssl.cnf -extensions server \
+ -keyout sample-ca/server.key -out sample-ca/server.csr \
+ -subj "/C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Server/emailAddress=me@myhost.mydomain"
+openssl ca -batch -config openssl.cnf -extensions server \
+ -out sample-ca/server.crt -in sample-ca/server.csr
+
+# Create client key and cert
+openssl req -new -nodes -config openssl.cnf \
+ -keyout sample-ca/client.key -out sample-ca/client.csr \
+ -subj "/C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Client/emailAddress=me@myhost.mydomain"
+openssl ca -batch -config openssl.cnf \
+ -out sample-ca/client.crt -in sample-ca/client.csr
+
+# Create password protected key file
+openssl rsa -aes256 -passout pass:password \
+ -in sample-ca/client.key -out sample-ca/client-pass.key
+
+# Create pkcs#12 client bundle
+openssl pkcs12 -export -nodes -password pass:password \
+ -out sample-ca/client.p12 -inkey sample-ca/client.key \
+ -in sample-ca/client.crt -certfile sample-ca/ca.crt
+
+
+# Create EC server and client cert (signed by 'regular' RSA CA)
+openssl ecparam -out sample-ca/secp256k1.pem -name secp256k1
+
+openssl req -new -newkey ec:sample-ca/secp256k1.pem -nodes -config openssl.cnf \
+ -extensions server \
+ -keyout sample-ca/server-ec.key -out sample-ca/server-ec.csr \
+ -subj "/C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Server-EC/emailAddress=me@myhost.mydomain"
+openssl ca -batch -config openssl.cnf -extensions server \
+ -out sample-ca/server-ec.crt -in sample-ca/server-ec.csr
+
+openssl req -new -newkey ec:sample-ca/secp256k1.pem -nodes -config openssl.cnf \
+ -keyout sample-ca/client-ec.key -out sample-ca/client-ec.csr \
+ -subj "/C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Client-EC/emailAddress=me@myhost.mydomain"
+openssl ca -batch -config openssl.cnf \
+ -out sample-ca/client-ec.crt -in sample-ca/client-ec.csr
+
+# Generate DH parameters
+openssl dhparam -out dh2048.pem 2048
+
+# Copy keys and certs to working directory
+cp sample-ca/*.key .
+cp sample-ca/*.crt .
+cp sample-ca/*.p12 .
diff --git a/app/openvpn/sample/sample-keys/openssl.cnf b/app/openvpn/sample/sample-keys/openssl.cnf
new file mode 100644
index 00000000..aabfd48f
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/openssl.cnf
@@ -0,0 +1,139 @@
+# Heavily borrowed from EasyRSA 3, for use with OpenSSL 1.0.*
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = sample-ca # Where everything is kept
+certs = $dir # Where the issued certs are kept
+crl_dir = $dir # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+new_certs_dir = $dir # default place for new certs.
+
+certificate = $dir/ca.crt # The CA certificate
+serial = $dir/serial # The current serial number
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/ca.key # The private key
+RANDFILE = $dir/.rand # private random number file
+
+x509_extensions = basic_exts # The extentions to add to the cert
+
+# This allows a V2 CRL. Ancient browsers don't like it, but anything Easy-RSA
+# is designed for will. In return, we get the Issuer attached to CRLs.
+crl_extensions = crl_ext
+
+default_days = 3650 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha256 # use public key default MD
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_anything
+
+# For the 'anything' policy, which defines allowed DN fields
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+name = optional
+emailAddress = optional
+
+####################################################################
+# Easy-RSA request handling
+# We key off $DN_MODE to determine how to format the DN
+[ req ]
+default_bits = 2048
+default_keyfile = privkey.pem
+default_md = sha256
+distinguished_name = cn_only
+x509_extensions = easyrsa_ca # The extentions to add to the self signed cert
+
+# A placeholder to handle the $EXTRA_EXTS feature:
+#%EXTRA_EXTS% # Do NOT remove or change this line as $EXTRA_EXTS support requires it
+
+####################################################################
+# Easy-RSA DN (Subject) handling
+
+# Easy-RSA DN for cn_only support:
+[ cn_only ]
+commonName = Common Name (eg: your user, host, or server name)
+commonName_max = 64
+commonName_default = changeme
+
+# Easy-RSA DN for org support:
+[ org ]
+countryName = Country Name (2 letter code)
+countryName_default = KG
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = NA
+
+localityName = Locality Name (eg, city)
+localityName_default = BISHKEK
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenVPN-TEST
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default =
+
+commonName = Common Name (eg: your user, host, or server name)
+commonName_max = 64
+commonName_default =
+
+emailAddress = Email Address
+emailAddress_default = me@myhost.mydomain
+emailAddress_max = 64
+
+####################################################################
+
+[ basic_exts ]
+basicConstraints = CA:FALSE
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer:always
+
+# The Easy-RSA CA extensions
+[ easyrsa_ca ]
+
+# PKIX recommendations:
+
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer:always
+
+# This could be marked critical, but it's nice to support reading by any
+# broken clients who attempt to do so.
+basicConstraints = CA:true
+
+# Limit key usage to CA tasks. If you really want to use the generated pair as
+# a self-signed cert, comment this out.
+keyUsage = cRLSign, keyCertSign
+
+# CRL extensions.
+[ crl_ext ]
+
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+
+# Server extensions.
+[ server ]
+
+basicConstraints = CA:FALSE
+nsCertType = server
+nsComment = "OpenSSL Generated Server Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer:always
+extendedKeyUsage = serverAuth
+keyUsage = digitalSignature, keyEncipherment
diff --git a/app/openvpn/sample/sample-keys/server-ec.crt b/app/openvpn/sample/sample-keys/server-ec.crt
new file mode 100644
index 00000000..7c7645a5
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/server-ec.crt
@@ -0,0 +1,96 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 3 (0x3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain
+ Validity
+ Not Before: Oct 22 21:59:53 2014 GMT
+ Not After : Oct 19 21:59:53 2024 GMT
+ Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server-EC/emailAddress=me@myhost.mydomain
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:21:09:ac:27:e6:00:3a:57:f4:f6:c7:78:a9:b1:
+ f4:d7:d7:45:59:39:e4:a3:d3:2c:94:f9:61:4a:e6:
+ b9:e9:87:57:c8:0f:88:03:a0:56:ee:34:e7:e4:4e:
+ 20:63:6c:c1:6e:c1:04:ac:b9:2f:a9:76:69:d3:7d:
+ 49:ff:f1:34:cb
+ ASN1 OID: secp256k1
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Cert Type:
+ SSL Server
+ Netscape Comment:
+ OpenSSL Generated Server Certificate
+ X509v3 Subject Key Identifier:
+ 33:1A:42:61:9E:88:08:3F:6F:1F:98:88:3A:DD:2D:C7:07:3D:F6:9B
+ X509v3 Authority Key Identifier:
+ keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B
+ DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain
+ serial:A1:4E:DE:FA:90:F2:AE:81
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 9d:89:f6:7e:0b:43:05:22:63:e5:b3:45:a8:d9:ef:33:3c:b7:
+ 19:37:28:87:27:43:43:86:a3:3f:b9:23:27:0f:96:4f:de:01:
+ 80:38:6b:d9:c8:94:77:1f:06:08:34:65:77:ad:57:0c:23:99:
+ f1:51:12:5f:32:d8:9c:7c:93:f1:f6:72:2a:05:61:ff:62:aa:
+ 33:aa:ef:a3:4d:d6:93:56:40:ff:38:2e:73:1c:69:fb:71:a1:
+ fa:64:19:6a:04:1c:8b:20:a8:ee:a5:18:63:f8:84:f4:ca:84:
+ 8e:b6:05:48:c6:f3:f7:81:90:4d:9e:00:cd:4a:92:83:d4:93:
+ 67:05:dc:16:8b:78:fa:b1:82:48:c6:86:74:44:b1:06:7e:8a:
+ c8:64:0b:82:3a:e2:f5:56:60:ea:50:70:03:da:9f:fc:28:20:
+ 6b:7d:04:e0:eb:8d:e2:f1:be:82:2f:ba:51:50:2b:6c:d2:fc:
+ 11:cd:69:85:3b:9e:14:19:dd:bc:14:cf:61:b0:7a:07:cb:e8:
+ e0:fc:c3:1f:a4:cb:cf:c1:e9:62:0f:d2:53:f8:ce:06:f4:f8:
+ 2f:55:13:aa:67:44:b6:b8:e8:3e:82:af:66:f5:f0:7c:fe:41:
+ e6:9d:c0:9f:78:fd:00:85:02:40:63:37:fa:00:e6:3c:a6:9f:
+ 35:4f:1d:a6:f1:cb:8b:04:e0:67:98:56:d1:87:58:b6:39:f6:
+ d3:fe:a8:40:50:80:7f:e6:4a:36:d0:c0:a5:61:64:1d:3a:87:
+ ad:78:72:c9:3f:98:44:35:f9:cf:32:b2:18:4c:b0:72:fa:5e:
+ 6c:62:1e:d4:31:0c:c8:9b:74:f0:00:9e:70:c3:1e:c7:a4:9d:
+ 03:a4:ac:1a:09:1f:86:23:65:51:34:50:86:68:1e:68:4d:9a:
+ 4b:78:10:1c:bd:51:09:bb:fe:16:a3:c7:19:b4:05:44:a1:e6:
+ c6:23:76:d5:b8:3a:eb:a5:17:1d:2b:2e:fe:85:7c:88:4f:f1:
+ e8:34:32:e0:c5:96:87:c3:e8:c9:5f:89:24:10:0e:1e:07:0b:
+ 2c:f8:d0:49:1b:63:5e:63:44:e9:2a:43:e2:9c:d6:f2:43:99:
+ 47:f8:9b:49:1a:a7:d1:e0:53:67:1d:cb:14:b6:b0:2c:4d:b3:
+ f2:c5:62:c2:a6:09:7a:c0:6c:59:3e:73:83:0c:6c:de:30:77:
+ 4d:1b:ed:b0:7f:77:87:8d:55:1d:d3:ed:f7:66:bd:06:2a:f8:
+ fd:00:e7:c0:31:e2:ff:53:9e:25:97:c6:64:84:9d:8d:61:8e:
+ c9:1f:6c:55:a1:7c:59:aa:eb:e8:2a:b2:2d:c7:09:cd:b5:3d:
+ d8:74:4f:6e:9c:3b:d5:6d
+-----BEGIN CERTIFICATE-----
+MIIEtTCCAp2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL
+MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t
+VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy
+MjIxNTk1M1oXDTI0MTAxOTIxNTk1M1owbTELMAkGA1UEBhMCS0cxCzAJBgNVBAgT
+Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFzAVBgNVBAMTDlRlc3QtU2VydmVy
+LUVDMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wVjAQBgcqhkjO
+PQIBBgUrgQQACgNCAAQhCawn5gA6V/T2x3ipsfTX10VZOeSj0yyU+WFK5rnph1fI
+D4gDoFbuNOfkTiBjbMFuwQSsuS+pdmnTfUn/8TTLo4IBMzCCAS8wCQYDVR0TBAIw
+ADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2Vu
+ZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUMxpCYZ6ICD9vH5iI
+Ot0txwc99pswgZgGA1UdIwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRo
+MGYxCzAJBgNVBAYTAktHMQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEV
+MBMGA1UEChMMT3BlblZQTi1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3Qu
+bXlkb21haW6CCQChTt76kPKugTATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8E
+BAMCBaAwDQYJKoZIhvcNAQELBQADggIBAJ2J9n4LQwUiY+WzRajZ7zM8txk3KIcn
+Q0OGoz+5IycPlk/eAYA4a9nIlHcfBgg0ZXetVwwjmfFREl8y2Jx8k/H2cioFYf9i
+qjOq76NN1pNWQP84LnMcaftxofpkGWoEHIsgqO6lGGP4hPTKhI62BUjG8/eBkE2e
+AM1KkoPUk2cF3BaLePqxgkjGhnREsQZ+ishkC4I64vVWYOpQcAPan/woIGt9BODr
+jeLxvoIvulFQK2zS/BHNaYU7nhQZ3bwUz2GwegfL6OD8wx+ky8/B6WIP0lP4zgb0
++C9VE6pnRLa46D6Cr2b18Hz+QeadwJ94/QCFAkBjN/oA5jymnzVPHabxy4sE4GeY
+VtGHWLY59tP+qEBQgH/mSjbQwKVhZB06h614csk/mEQ1+c8yshhMsHL6XmxiHtQx
+DMibdPAAnnDDHseknQOkrBoJH4YjZVE0UIZoHmhNmkt4EBy9UQm7/hajxxm0BUSh
+5sYjdtW4OuulFx0rLv6FfIhP8eg0MuDFlofD6MlfiSQQDh4HCyz40EkbY15jROkq
+Q+Kc1vJDmUf4m0kap9HgU2cdyxS2sCxNs/LFYsKmCXrAbFk+c4MMbN4wd00b7bB/
+d4eNVR3T7fdmvQYq+P0A58Ax4v9TniWXxmSEnY1hjskfbFWhfFmq6+gqsi3HCc21
+Pdh0T26cO9Vt
+-----END CERTIFICATE-----
diff --git a/app/openvpn/sample/sample-keys/server-ec.key b/app/openvpn/sample/sample-keys/server-ec.key
new file mode 100644
index 00000000..8f2c914e
--- /dev/null
+++ b/app/openvpn/sample/sample-keys/server-ec.key
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgLHGYqSlzoRaogmJfrC+E
+ozTothB9bORaQ1C/3FmeQ6ehRANCAAQhCawn5gA6V/T2x3ipsfTX10VZOeSj0yyU
++WFK5rnph1fID4gDoFbuNOfkTiBjbMFuwQSsuS+pdmnTfUn/8TTL
+-----END PRIVATE KEY-----
diff --git a/app/openvpn/sample/sample-keys/server.crt b/app/openvpn/sample/sample-keys/server.crt
index 28bb4d94..76b40448 100644
--- a/app/openvpn/sample/sample-keys/server.crt
+++ b/app/openvpn/sample/sample-keys/server.crt
@@ -2,25 +2,34 @@ Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
- Signature Algorithm: md5WithRSAEncryption
+ Signature Algorithm: sha256WithRSAEncryption
Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain
Validity
- Not Before: Nov 25 14:42:22 2004 GMT
- Not After : Nov 23 14:42:22 2014 GMT
+ Not Before: Oct 22 21:59:52 2014 GMT
+ Not After : Oct 19 21:59:52 2024 GMT
Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server/emailAddress=me@myhost.mydomain
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:cb:4e:ac:f9:83:57:f6:69:d2:32:29:b4:bc:ad:
- e6:f7:26:21:89:33:30:43:40:a3:35:d9:de:26:01:
- d6:b4:f0:bc:0a:19:55:99:3b:f1:4c:91:60:b6:fd:
- 74:34:8d:5a:c7:62:ec:ce:f2:d6:02:ce:57:32:f4:
- 35:8c:71:a0:6d:65:2a:e7:80:ae:29:59:cf:36:73:
- f8:7c:4a:73:90:fc:30:28:d5:46:7d:35:a4:4e:c9:
- 9f:90:7b:e2:09:21:36:c5:a8:ec:85:82:9a:32:b4:
- 91:3b:c1:d6:4f:9f:d1:f8:6f:68:f4:1d:d2:06:91:
- 32:cc:9a:48:fd:cd:98:7f:2f
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a5:b8:a2:ee:ce:b1:a6:0f:6a:b2:9f:d3:22:17:
+ 79:de:09:98:71:78:fa:a7:ce:36:51:54:57:c7:31:
+ 99:56:d1:8a:d6:c5:fd:52:e6:88:0e:7b:f9:ea:27:
+ 7a:bf:3f:14:ec:aa:d2:ff:8b:56:58:ac:ca:51:77:
+ c5:3c:b6:e4:83:6f:22:06:2d:5b:eb:e7:59:d4:ab:
+ 42:c8:d5:a9:87:73:b3:73:36:51:2f:a5:d0:90:a2:
+ 87:64:54:6c:12:d3:b8:76:47:69:af:ae:8f:00:b3:
+ 70:b9:e7:67:3f:8c:6a:3d:79:5f:81:27:a3:0e:aa:
+ a7:3d:81:48:10:b1:18:6c:38:2e:8f:7a:7b:c5:3d:
+ 21:c8:f9:a0:7f:17:2b:88:4f:ba:f2:ec:6d:24:8e:
+ 6c:f1:0a:5c:d9:5b:b1:b0:fc:49:cb:4a:d2:58:c6:
+ 2a:25:b0:97:84:c3:9e:ff:34:8c:10:46:7f:0f:fb:
+ 3c:59:7a:a6:29:0c:ae:8e:50:3a:f2:53:84:40:2d:
+ d5:91:7b:0a:37:8e:82:77:ce:66:2f:34:77:5c:a5:
+ 45:3b:00:19:a7:07:d1:92:e6:66:b9:3b:4e:e9:63:
+ fc:33:98:1a:ae:7b:08:7d:0a:df:7a:ba:aa:59:6d:
+ 86:82:0a:64:2b:da:59:a7:4c:4e:ef:3d:bd:04:a2:
+ 4b:31
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
@@ -30,38 +39,75 @@ Certificate:
Netscape Comment:
OpenSSL Generated Server Certificate
X509v3 Subject Key Identifier:
- 69:11:FE:E7:9F:89:7B:71:34:69:C0:DC:82:F8:D0:5D:4D:FB:78:DF
+ B3:9D:81:E6:16:92:64:C4:86:87:F5:29:10:1B:5E:2F:74:F7:ED:B1
X509v3 Authority Key Identifier:
- keyid:89:A6:60:E3:BA:EA:3E:AF:FC:64:7F:4C:BD:8C:D2:48:8D:E0:CC:46
+ keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B
DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain
- serial:00
+ serial:A1:4E:DE:FA:90:F2:AE:81
- Signature Algorithm: md5WithRSAEncryption
- 35:5c:75:da:57:ef:b5:79:f2:a2:db:36:e4:75:e8:c7:bc:73:
- 26:cf:30:36:4b:2e:51:46:37:60:2f:4e:2b:f6:71:a2:23:db:
- 8e:d8:5c:d5:af:2e:22:28:dd:30:a8:89:66:3a:cc:5b:3c:0f:
- 96:12:20:de:5e:41:52:74:35:ed:4c:26:40:19:ca:73:df:54:
- b1:30:96:9c:a5:14:d0:38:28:3f:ab:30:07:d7:de:98:d2:7f:
- 7f:90:b2:52:1d:e5:95:88:ed:ba:8a:6a:14:85:66:76:ec:75:
- 30:e8:ae:94:f4:e1:76:fa:4b:0e:f1:53:d7:95:be:fb:69:fa:
- 3d:32
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 4e:25:80:1b:cb:b0:42:ff:bb:3f:e8:0d:58:c1:80:db:cf:d0:
+ 90:df:ca:c1:e6:41:e1:48:7f:a7:1e:c7:35:9f:9c:6d:7c:3e:
+ 82:e8:de:7e:ae:82:16:00:33:0f:02:23:f1:9d:fe:2b:06:16:
+ 05:55:16:89:dc:63:ac:5f:1a:31:13:79:21:a3:6e:60:28:e8:
+ e7:6b:54:00:22:a1:b7:69:5a:17:31:ce:0f:c2:a6:dd:a3:6f:
+ de:ea:19:6c:d2:d2:cb:35:9d:dd:87:51:33:68:cd:c3:9b:90:
+ 55:f1:80:3d:5c:b8:09:b6:e1:3c:13:a4:5d:4a:ce:a5:11:9e:
+ f9:08:ee:be:e3:54:1d:06:4c:bb:1b:72:13:ee:7d:a0:45:cc:
+ fe:d1:3b:02:03:c1:d4:ea:45:2d:a8:c9:97:e7:f3:8a:7a:a0:
+ 2f:dd:48:3a:75:c9:42:28:94:fc:af:44:52:16:68:98:d6:ad:
+ a8:65:b1:cd:ac:60:41:70:e5:44:e8:5a:f2:e7:fc:3b:fe:45:
+ 89:17:1d:6d:85:c6:f0:fc:69:87:d1:1d:07:f3:cb:7b:54:8d:
+ aa:a3:cc:e3:c6:fc:d6:05:76:35:d0:26:63:8e:d1:a8:b7:ff:
+ 61:42:8a:2c:63:1f:d4:ec:14:47:6b:1e:e3:81:61:12:3b:8c:
+ 16:b5:cf:87:6a:2d:42:21:83:9c:0e:3a:90:3a:1e:c1:36:61:
+ 41:f9:fb:4e:5d:ea:f4:df:23:92:33:2b:9b:14:9f:a0:f5:d3:
+ c4:f8:1f:2f:9c:11:36:af:2a:22:61:95:32:0b:c4:1c:2d:b1:
+ c1:0a:2a:97:c0:43:4a:6c:3e:db:00:cd:29:15:9e:7e:41:75:
+ 36:a8:56:86:8c:82:9e:46:20:e5:06:1e:60:d2:03:5f:9f:9e:
+ 69:bb:bf:c2:b4:43:e2:7d:85:17:83:18:41:b0:cb:a9:04:1b:
+ 18:52:9f:89:8b:76:9f:94:59:81:4f:60:5b:33:18:fc:c7:52:
+ d0:d2:69:fc:0b:a2:63:32:75:43:99:e9:d7:f8:6d:c7:55:31:
+ 0c:f3:ef:1a:71:e1:0a:57:e1:9d:13:b2:1e:fe:1d:ef:e4:f1:
+ 51:d9:95:b3:fd:28:28:93:91:4a:29:c5:37:0e:ab:d8:85:6a:
+ fe:a8:83:1f:7b:80:5d:1f:04:79:b7:a9:08:6e:0d:d6:2e:aa:
+ 7c:f6:63:7d:41:de:70:13:32:ce:dd:58:cc:a6:73:d4:72:7e:
+ d7:ac:74:a8:35:ba:c3:1b:2a:64:d7:5a:37:97:56:94:34:2b:
+ 2a:71:60:bc:69:ab:00:85:b9:4f:67:32:17:51:c3:da:57:3a:
+ 37:89:66:c4:7a:51:da:5f
-----BEGIN CERTIFICATE-----
-MIIDUTCCArqgAwIBAgIBATANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJLRzEL
+MIIFgDCCA2igAwIBAgIBATANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL
MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t
-VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTA0MTEy
-NTE0NDIyMloXDTE0MTEyMzE0NDIyMlowajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT
+VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy
+MjIxNTk1MloXDTI0MTAxOTIxNTk1MlowajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT
Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFDASBgNVBAMTC1Rlc3QtU2VydmVy
-MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBAMtOrPmDV/Zp0jIptLyt5vcmIYkzMENAozXZ3iYB1rTw
-vAoZVZk78UyRYLb9dDSNWsdi7M7y1gLOVzL0NYxxoG1lKueArilZzzZz+HxKc5D8
-MCjVRn01pE7Jn5B74gkhNsWo7IWCmjK0kTvB1k+f0fhvaPQd0gaRMsyaSP3NmH8v
-AgMBAAGjggEJMIIBBTAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglg
-hkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRl
-MB0GA1UdDgQWBBRpEf7nn4l7cTRpwNyC+NBdTft43zCBkAYDVR0jBIGIMIGFgBSJ
-pmDjuuo+r/xkf0y9jNJIjeDMRqFqpGgwZjELMAkGA1UEBhMCS0cxCzAJBgNVBAgT
-Ak5BMRAwDgYDVQQHEwdCSVNIS0VLMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxITAf
-BgkqhkiG9w0BCQEWEm1lQG15aG9zdC5teWRvbWFpboIBADANBgkqhkiG9w0BAQQF
-AAOBgQA1XHXaV++1efKi2zbkdejHvHMmzzA2Sy5RRjdgL04r9nGiI9uO2FzVry4i
-KN0wqIlmOsxbPA+WEiDeXkFSdDXtTCZAGcpz31SxMJacpRTQOCg/qzAH196Y0n9/
-kLJSHeWViO26imoUhWZ27HUw6K6U9OF2+ksO8VPXlb77afo9Mg==
+MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCluKLuzrGmD2qyn9MiF3neCZhxePqnzjZRVFfH
+MZlW0YrWxf1S5ogOe/nqJ3q/PxTsqtL/i1ZYrMpRd8U8tuSDbyIGLVvr51nUq0LI
+1amHc7NzNlEvpdCQoodkVGwS07h2R2mvro8As3C552c/jGo9eV+BJ6MOqqc9gUgQ
+sRhsOC6PenvFPSHI+aB/FyuIT7ry7G0kjmzxClzZW7Gw/EnLStJYxiolsJeEw57/
+NIwQRn8P+zxZeqYpDK6OUDryU4RALdWRewo3joJ3zmYvNHdcpUU7ABmnB9GS5ma5
+O07pY/wzmBquewh9Ct96uqpZbYaCCmQr2lmnTE7vPb0EoksxAgMBAAGjggEzMIIB
+LzAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYk
+T3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBSz
+nYHmFpJkxIaH9SkQG14vdPftsTCBmAYDVR0jBIGQMIGNgBQrQOXJffX0ljjpL+Mv
+2UBkyY4Fm6FqpGgwZjELMAkGA1UEBhMCS0cxCzAJBgNVBAgTAk5BMRAwDgYDVQQH
+EwdCSVNIS0VLMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxITAfBgkqhkiG9w0BCQEW
+Em1lQG15aG9zdC5teWRvbWFpboIJAKFO3vqQ8q6BMBMGA1UdJQQMMAoGCCsGAQUF
+BwMBMAsGA1UdDwQEAwIFoDANBgkqhkiG9w0BAQsFAAOCAgEATiWAG8uwQv+7P+gN
+WMGA28/QkN/KweZB4Uh/px7HNZ+cbXw+gujefq6CFgAzDwIj8Z3+KwYWBVUWidxj
+rF8aMRN5IaNuYCjo52tUACKht2laFzHOD8Km3aNv3uoZbNLSyzWd3YdRM2jNw5uQ
+VfGAPVy4CbbhPBOkXUrOpRGe+QjuvuNUHQZMuxtyE+59oEXM/tE7AgPB1OpFLajJ
+l+fzinqgL91IOnXJQiiU/K9EUhZomNatqGWxzaxgQXDlROha8uf8O/5FiRcdbYXG
+8Pxph9EdB/PLe1SNqqPM48b81gV2NdAmY47RqLf/YUKKLGMf1OwUR2se44FhEjuM
+FrXPh2otQiGDnA46kDoewTZhQfn7Tl3q9N8jkjMrmxSfoPXTxPgfL5wRNq8qImGV
+MgvEHC2xwQoql8BDSmw+2wDNKRWefkF1NqhWhoyCnkYg5QYeYNIDX5+eabu/wrRD
+4n2FF4MYQbDLqQQbGFKfiYt2n5RZgU9gWzMY/MdS0NJp/AuiYzJ1Q5np1/htx1Ux
+DPPvGnHhClfhnROyHv4d7+TxUdmVs/0oKJORSinFNw6r2IVq/qiDH3uAXR8Eebep
+CG4N1i6qfPZjfUHecBMyzt1YzKZz1HJ+16x0qDW6wxsqZNdaN5dWlDQrKnFgvGmr
+AIW5T2cyF1HD2lc6N4lmxHpR2l8=
-----END CERTIFICATE-----
diff --git a/app/openvpn/sample/sample-keys/server.key b/app/openvpn/sample/sample-keys/server.key
index 976acabf..011df12e 100644
--- a/app/openvpn/sample/sample-keys/server.key
+++ b/app/openvpn/sample/sample-keys/server.key
@@ -1,15 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXgIBAAKBgQDLTqz5g1f2adIyKbS8reb3JiGJMzBDQKM12d4mAda08LwKGVWZ
-O/FMkWC2/XQ0jVrHYuzO8tYCzlcy9DWMcaBtZSrngK4pWc82c/h8SnOQ/DAo1UZ9
-NaROyZ+Qe+IJITbFqOyFgpoytJE7wdZPn9H4b2j0HdIGkTLMmkj9zZh/LwIDAQAB
-AoGBAKP1ljA/iY/zNY447kZ/5NWKzd7tBk4mcbl7M9no/7O6tZtbZRoIKoi6cYoC
-C1ZabUyBbkNTud5XdCFmq0zRUjOWvoFMZ9VZfd2kRPvl4TGczBtJAq65b+EYMGui
-q6T9p61xPdtzu0vM+Ecj127pAMk5XcJyxu8XQK7lZWmG5UoJAkEA8CxXNZN+A3qD
-bMBPI3VdwKCNSjNVEQEnygMbNgw7VLdxPpspzZziqJEGdzsM4dsnOBwKxIWFLN2h
-lbGBOquAswJBANi0atGWM8VUxDjvqqHCTS9RUXWgnvYhee4/xraJBQPBSivjC9P0
-vKT7PjBHU6djtKSLKGaHn1vHqmyY7PCMjZUCQQCNVSqExqSzG1dXmdt4PErNXi2G
-6qo2dX2arTVIGu6XLdQgSWLSMm5XT/CEHWW5SyPLKwVTHFeATXQXCPvJML9tAkEA
-k0yXax0g1ZoXwufN4SQUmPw6Va03P/BjU/nP1ZVvbiz9gLVU/d7WN4J7tA9XomkY
-idv5OzAmtxkSE70jGSNAvQJAWhCf9+iHkzOHRyKKOYlh1DHUwDfSEp+hlZYg9H03
-P2sraQzUxgWDY/DIY63KvW78ny863baFz7onz21MYGgJXg==
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCluKLuzrGmD2qy
+n9MiF3neCZhxePqnzjZRVFfHMZlW0YrWxf1S5ogOe/nqJ3q/PxTsqtL/i1ZYrMpR
+d8U8tuSDbyIGLVvr51nUq0LI1amHc7NzNlEvpdCQoodkVGwS07h2R2mvro8As3C5
+52c/jGo9eV+BJ6MOqqc9gUgQsRhsOC6PenvFPSHI+aB/FyuIT7ry7G0kjmzxClzZ
+W7Gw/EnLStJYxiolsJeEw57/NIwQRn8P+zxZeqYpDK6OUDryU4RALdWRewo3joJ3
+zmYvNHdcpUU7ABmnB9GS5ma5O07pY/wzmBquewh9Ct96uqpZbYaCCmQr2lmnTE7v
+Pb0EoksxAgMBAAECggEAPMOMin+jR75TYxeTNObiunVOPh0b2zeTVxLT9KfND7ZZ
+cBK8pg79SEJRCnhbW5BnvbeNEkIm8PC6ZlDCM1bkRwUStq0fDUqQ95esLzOYq5/S
+5qW98viblszhU/pYfja/Zi8dI1uf96PT63Zbt0NnGQ9N42+DLDeKhtTGdchZqiQA
+LeSR0bQanY4tUUtCNYvBT8E3pzhoIsUzVwzIK53oovRpcOX3pMXVYZsmNhXdFFRy
+YkjMXpj7fGyaAJK0QsC+PsgrKuhXDzDttsG2lI/mq9+7RXB3d/pzhmBVWynVH2lw
+iQ7ONkSz7akDz/4I4WmxJep+FfQJYgK6rnLAlQqauQKBgQDammSAprnvDvNhSEp8
+W+xt7jQnFqaENbGgP0/D/OZMXc4khgexqlKFmSnBCRDmQ6JvLTWqDXC4+aqAbFQz
+zAIjiKaT+so8xvFRob+rBMJY5JLYKNa+zUUanfORUNYLFJPvFqnrWGaJ9uufdaM7
+0a5bu95PN74NXee3DBbpBv8HLwKBgQDCEk+IjNbjMT+Neq0ywUeM5rFrUKi92abe
+AgsVpjbighRV+6jA2lZFJcize+xYJ9wiOR1/TEI9PZ2OtBkqpwVdvTEHTagRLcvd
+NfGcptREDnNLoNWA22buQpztiEduutACWQsrd+JQmqbUicUdW4zw86/oCMbYCW3V
+QmYOLns7nwKBgHHUX20WZE91S4pmqFKlUzHTDdkk1ESX6Qx2q0R01j8BwawHFs6O
+0DW9EZ7w55nfsh+OPRl1sjK/3ubMgfQO0TZLm+IGf3Sya0qEnVeiPMkpDMX+TgRA
+wzEe+ou6uho+9uFSvdxMxeglaYA5M2ycvNwLsbEyZ4ZyVYxdgTiKahYFAoGAcIfP
+iD0qKQiYcj/tB94cz+3AeJqHjbYT1O1YYhBECOkmQ4kuG80+cs/q5W/45lEOiuWV
+Xgfo7Lu6jVGOujWoneci87oqtvNYH4e09oGh2WiLoBG9Wv9dWtBTUERSLzmxfXsG
+SAk2uEhEbj8IhfJc8iZLHH9iVUh6YEslBBodqL8CgYEAlAhvcqAvw5SzsfBR5Mcu
+4Nql6mXEVhHCvS4hdFCGaNF0z9A6eBORKJpdLWnqhpquDQDsghWE+Ga4QKSNFIi1
+fnAaykmZuY3ToqNOIaVlYM6HpMEz0wHQbTWfDLGcTFcElLZgMAk7VlDyiYVOco+E
+QX9lXOO1PGpLzXhlDxSe63Y=
+-----END PRIVATE KEY-----
diff --git a/app/openvpn/src/openvpn/crypto.c b/app/openvpn/src/openvpn/crypto.c
index 69df29de..eaef9643 100644
--- a/app/openvpn/src/openvpn/crypto.c
+++ b/app/openvpn/src/openvpn/crypto.c
@@ -223,30 +223,6 @@ err:
return;
}
-int verify_hmac(struct buffer *buf, struct key_ctx *ctx, int offset)
-{
- uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */
- int hmac_len = 0;
-
- hmac_ctx_reset(ctx->hmac);
- /* Assume the length of the input HMAC */
- hmac_len = hmac_ctx_size (ctx->hmac);
-
- /* Authentication fails if insufficient data in packet for HMAC */
- if (buf->len - offset < hmac_len)
- return 0;
-
- hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len + offset,
- BLEN (buf) - hmac_len - offset);
- hmac_ctx_final (ctx->hmac, local_hmac);
-
- /* Compare locally computed HMAC with packet HMAC */
- if (memcmp_constant_time (local_hmac, BPTR (buf) + offset, hmac_len) == 0)
- return hmac_len;
-
- return 0;
-}
-
/*
* If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet.
*
@@ -273,9 +249,25 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
/* Verify the HMAC */
if (ctx->hmac)
{
- int hmac_len = verify_hmac(buf, ctx, 0);
- if (hmac_len == 0)
+ int hmac_len;
+ uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */
+
+ hmac_ctx_reset(ctx->hmac);
+
+ /* Assume the length of the input HMAC */
+ hmac_len = hmac_ctx_size (ctx->hmac);
+
+ /* Authentication fails if insufficient data in packet for HMAC */
+ if (buf->len < hmac_len)
+ CRYPT_ERROR ("missing authentication info");
+
+ hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len, BLEN (buf) - hmac_len);
+ hmac_ctx_final (ctx->hmac, local_hmac);
+
+ /* Compare locally computed HMAC with packet HMAC */
+ if (memcmp_constant_time (local_hmac, BPTR (buf), hmac_len))
CRYPT_ERROR ("packet HMAC authentication failed");
+
ASSERT (buf_advance (buf, hmac_len));
}
@@ -400,28 +392,6 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
}
/*
- * This verifies if a packet and its HMAC fit to a crypto context.
- *
- * On success true is returned.
- */
-bool
-crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt)
-{
- if (buf->len > 0 && opt->key_ctx_bi)
- {
- struct key_ctx *ctx = &opt->key_ctx_bi->decrypt;
-
- /* Verify the HMAC */
- if (ctx->hmac)
- {
- /* sizeof(uint32_t) comes from peer_id (3 bytes) and opcode (1 byte) */
- return verify_hmac(buf, ctx, sizeof(uint32_t)) != 0;
- }
- }
- return false;
-}
-
-/*
* How many bytes will we add to frame buffer for a given
* set of crypto options?
*/
@@ -800,22 +770,13 @@ get_tls_handshake_key (const struct key_type *key_type,
}
else
{
- int hash_size;
-
CLEAR (key2);
- /* failed, now try to get hash from a freeform file */
- hash_size = read_passphrase_hash (passphrase_file,
- kt.digest,
- key2.keys[0].hmac,
- MAX_HMAC_KEY_LENGTH);
- ASSERT (hash_size == kt.hmac_length);
-
- /* suceeded */
- key2.n = 1;
+ /* failed, now bail out */
- msg (M_INFO,
- "Control Channel Authentication: using '%s' as a free-form passphrase file",
+ msg (M_ERR,
+ "Control Channel Authentication: File '%s' does not have OpenVPN Static Key format. "
+ "Using free-form passphrase file is not supported anymore",
passphrase_file);
}
}
@@ -1042,54 +1003,6 @@ read_key_file (struct key2 *key2, const char *file, const unsigned int flags)
gc_free (&gc);
}
-int
-read_passphrase_hash (const char *passphrase_file,
- const md_kt_t *digest,
- uint8_t *output,
- int len)
-{
- md_ctx_t md;
-
- ASSERT (len >= md_kt_size(digest));
- memset (output, 0, len);
-
- md_ctx_init(&md, digest);
-
- /* read passphrase file */
- {
- const int min_passphrase_size = 8;
- uint8_t buf[64];
- int total_size = 0;
- int fd = platform_open (passphrase_file, O_RDONLY, 0);
-
- if (fd == -1)
- msg (M_ERR, "Cannot open passphrase file: '%s'", passphrase_file);
-
- for (;;)
- {
- int size = read (fd, buf, sizeof (buf));
- if (size == 0)
- break;
- if (size == -1)
- msg (M_ERR, "Read error on passphrase file: '%s'",
- passphrase_file);
- md_ctx_update(&md, buf, size);
- total_size += size;
- }
- close (fd);
-
- warn_if_group_others_accessible (passphrase_file);
-
- if (total_size < min_passphrase_size)
- msg (M_FATAL,
- "Passphrase file '%s' is too small (must have at least %d characters)",
- passphrase_file, min_passphrase_size);
- }
- md_ctx_final(&md, output);
- md_ctx_cleanup(&md);
- return md_kt_size(digest);
-}
-
/*
* Write key to file, return number of random bits
* written.
diff --git a/app/openvpn/src/openvpn/crypto.h b/app/openvpn/src/openvpn/crypto.h
index 3c4e59d7..e4898278 100644
--- a/app/openvpn/src/openvpn/crypto.h
+++ b/app/openvpn/src/openvpn/crypto.h
@@ -6,7 +6,7 @@
* packet compression.
*
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
- * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
+ * Copyright (C) 2010-2014 Fox Crypto B.V. <openvpn@fox-it.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -25,6 +25,76 @@
/**
* @file Data Channel Cryptography Module
+ *
+ * @addtogroup data_crypto Data Channel Crypto module
+ *
+ * @par Crypto packet formats
+ * The Data Channel Crypto module supports a number of crypto modes and
+ * configurable options. The actual packet format depends on these options. A
+ * Data Channel packet can consist of:
+ * - \b Opcode, one byte specifying the packet type (see @ref network_protocol
+ * "Network protocol").
+ * - \b Peer-id, if using the v2 data channel packet format (see @ref
+ * network_protocol "Network protocol").
+ * - \b HMAC, covering the ciphertext IV + ciphertext. The HMAC size depends
+ * on the \c \-\-auth option. If \c \-\-auth \c none is specified, there is no
+ * HMAC at all.
+ * - \b Ciphertext \b IV, if not disabled by \c \-\-no-iv. The IV size depends on
+ * the \c \-\-cipher option.
+ * - \b Packet \b ID, a 32-bit incrementing packet counter that provides replay
+ * protection (if not disabled by \c \-\-no-replay).
+ * - \b Timestamp, a 32-bit timestamp of the current time.
+ * - \b Payload, the plain text network packet to be encrypted (unless
+ * encryption is disabled by using \c \-\-cipher \c none). The payload might
+ * already be compressed (see @ref compression "Compression module").
+ *
+ * @par
+ * This section does not discuss the opcode and peer-id, since those do not
+ * depend on the data channel crypto. See @ref network_protocol
+ * "Network protocol" for more information on those.
+ *
+ * @par
+ * \e Legenda \n
+ * <tt>[ xxx ]</tt> = unprotected \n
+ * <tt>[ - xxx - ]</tt> = authenticated \n
+ * <tt>[ * xxx * ]</tt> = encrypted and authenticated
+ *
+ * @par
+ * <b>CBC data channel cypto format</b> \n
+ * In CBC mode, both TLS-mode and static key mode are supported. The IV
+ * consists of random bits to provide unpredictable IVs. \n
+ * <i>CBC IV format:</i> \n
+ * <tt> [ - random - ] </tt> \n
+ * <i>CBC data channel crypto format in TLS-mode:</i> \n
+ * <tt> [ HMAC ] [ - IV - ] [ * packet ID * ] [ * packet payload * ] </tt> \n
+ * <i>CBC data channel crypto format in static key mode:</i> \n
+ * <tt> [ HMAC ] [ - IV - ] [ * packet ID * ] [ * timestamp * ]
+ * [ * packet payload * ] </tt>
+ *
+ * @par
+ * <b>CFB/OFB data channel crypto format</b> \n
+ * CFB and OFB modes are only supported in TLS mode. In these modes, the IV
+ * consists of the packet counter and a timestamp. If the IV is more than 8
+ * bytes long, the remaining space is filled with zeroes. The packet counter may
+ * not roll over within a single TLS sessions. This results in a unique IV for
+ * each packet, as required by the CFB and OFB cipher modes.
+ *
+ * @par
+ * <i>CFB/OFB IV format:</i> \n
+ * <tt> [ - packet ID - ] [ - timestamp - ] [ - opt: zero-padding - ] </tt>\n
+ * <i>CFB/OFB data channel crypto format:</i> \n
+ * <tt> [ HMAC ] [ - IV - ] [ * packet payload * ] </tt>
+ *
+ * @par
+ * <b>No-crypto data channel format</b> \n
+ * In no-crypto mode (\c \-\-cipher \c none is specified), both TLS-mode and
+ * static key mode are supported. No encryption will be performed on the packet,
+ * but packets can still be authenticated. This mode does not require an IV.\n
+ * <i>No-crypto data channel crypto format in TLS-mode:</i> \n
+ * <tt> [ HMAC ] [ - packet ID - ] [ - packet payload - ] </tt> \n
+ * <i>No-crypto data channel crypto format in static key mode:</i> \n
+ * <tt> [ HMAC ] [ - packet ID - ] [ - timestamp - ] [ - packet payload - ] </tt>
+ *
*/
#ifndef CRYPTO_H
@@ -275,9 +345,6 @@ bool openvpn_decrypt (struct buffer *buf, struct buffer work,
const struct crypto_options *opt,
const struct frame* frame);
-
-bool crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt);
-
/** @} name Functions for performing security operations on data channel packets */
void crypto_adjust_frame_parameters(struct frame *frame,
diff --git a/app/openvpn/src/openvpn/crypto_backend.h b/app/openvpn/src/openvpn/crypto_backend.h
index 87498785..4e45df00 100644
--- a/app/openvpn/src/openvpn/crypto_backend.h
+++ b/app/openvpn/src/openvpn/crypto_backend.h
@@ -237,8 +237,7 @@ int cipher_kt_mode (const cipher_kt_t *cipher_kt);
*
* @return true iff the cipher is a CBC mode cipher.
*/
-bool cipher_kt_mode_cbc(const cipher_kt_t *cipher)
- __attribute__((nonnull));
+bool cipher_kt_mode_cbc(const cipher_kt_t *cipher);
/**
* Check if the supplied cipher is a supported OFB or CFB mode cipher.
@@ -247,8 +246,7 @@ bool cipher_kt_mode_cbc(const cipher_kt_t *cipher)
*
* @return true iff the cipher is a OFB or CFB mode cipher.
*/
-bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)
- __attribute__((nonnull));
+bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher);
/**
diff --git a/app/openvpn/src/openvpn/forward.c b/app/openvpn/src/openvpn/forward.c
index 0bbdedb0..5709ee51 100644
--- a/app/openvpn/src/openvpn/forward.c
+++ b/app/openvpn/src/openvpn/forward.c
@@ -722,20 +722,11 @@ read_incoming_link (struct context *c)
perf_pop ();
}
-/*
- * Input: c->c2.buf
- * Output: c->c2.to_tun
- */
-
-void
-process_incoming_link (struct context *c)
+bool
+process_incoming_link_part1 (struct context *c, struct link_socket_info *lsi, bool floated)
{
struct gc_arena gc = gc_new ();
- bool decrypt_status;
- struct link_socket_info *lsi = get_link_socket_info (c);
- const uint8_t *orig_buf = c->c2.buf.data;
-
- perf_push (PERF_PROC_IN_LINK);
+ bool decrypt_status = false;
if (c->c2.buf.len > 0)
{
@@ -805,7 +796,7 @@ process_incoming_link (struct context *c)
* will load crypto_options with the correct encryption key
* and return false.
*/
- if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &c->c2.crypto_options))
+ if (tls_pre_decrypt (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &c->c2.crypto_options, floated))
{
interval_action (&c->c2.tmp_int);
@@ -832,11 +823,25 @@ process_incoming_link (struct context *c)
/* decryption errors are fatal in TCP mode */
register_signal (c, SIGUSR1, "decryption-error"); /* SOFT-SIGUSR1 -- decryption error in TCP mode */
msg (D_STREAM_ERRORS, "Fatal decryption error (process_incoming_link), restarting");
- goto done;
}
-
+#else /* ENABLE_CRYPTO */
+ decrypt_status = true;
#endif /* ENABLE_CRYPTO */
+ }
+ else
+ {
+ buf_reset (&c->c2.to_tun);
+ }
+ gc_free (&gc);
+ return decrypt_status;
+}
+
+void
+process_incoming_link_part2 (struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf)
+{
+ if (c->c2.buf.len > 0)
+ {
#ifdef ENABLE_FRAGMENT
if (c->c2.fragment)
fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment);
@@ -903,9 +908,20 @@ process_incoming_link (struct context *c)
{
buf_reset (&c->c2.to_tun);
}
- done:
+}
+
+void
+process_incoming_link (struct context *c)
+{
+ perf_push (PERF_PROC_IN_LINK);
+
+ struct link_socket_info *lsi = get_link_socket_info (c);
+ const uint8_t *orig_buf = c->c2.buf.data;
+
+ process_incoming_link_part1(c, lsi, false);
+ process_incoming_link_part2(c, lsi, orig_buf);
+
perf_pop ();
- gc_free (&gc);
}
/*
diff --git a/app/openvpn/src/openvpn/forward.h b/app/openvpn/src/openvpn/forward.h
index 1830a00b..af3b0a67 100644
--- a/app/openvpn/src/openvpn/forward.h
+++ b/app/openvpn/src/openvpn/forward.h
@@ -127,12 +127,11 @@ void encrypt_sign (struct context *c, bool comp_frag);
*/
void read_incoming_link (struct context *c);
-
/**
- * Process a packet read from the external network interface.
+ * Starts processing a packet read from the external network interface.
* @ingroup external_multiplexer
*
- * This function controls the processing of a data channel packet which
+ * This function starts the processing of a data channel packet which
* has come out of a VPN tunnel. It's high-level structure is as follows:
* - Verify that a nonzero length packet has been received from a valid
* source address for the given context \a c.
@@ -146,6 +145,25 @@ void read_incoming_link (struct context *c);
* - Call \c openvpn_decrypt() of the \link data_crypto Data Channel
* Crypto module\endlink to authenticate and decrypt the packet using
* the security parameters loaded by \c tls_pre_decrypt() above.
+ *
+ * @param c - The context structure of the VPN tunnel associated with the
+ * packet.
+ * @param lsi - link_socket_info obtained from context before processing.
+ * @param floated - Flag indicates that peer has floated.
+ *
+ * @return true if packet is authenticated, false otherwise.
+ */
+bool process_incoming_link_part1 (struct context *c, struct link_socket_info *lsi, bool floated);
+
+/**
+ * Continues processing a packet read from the external network interface.
+ * @ingroup external_multiplexer
+ *
+ * This function continues the processing of a data channel packet which
+ * has come out of a VPN tunnel. It must be called after
+ * \c process_incoming_link_part1() function.
+ *
+ * It's high-level structure is as follows:
* - Call \c fragment_incoming() of the \link fragmentation Data Channel
* Fragmentation module\endlink to reassemble the packet if it's
* fragmented.
@@ -158,9 +176,11 @@ void read_incoming_link (struct context *c);
*
* @param c - The context structure of the VPN tunnel associated with the
* packet.
+ * @param lsi - link_socket_info obtained from context before processing.
+ * @param orig_buf - Pointer to a buffer data.
+ *
*/
-void process_incoming_link (struct context *c);
-
+void process_incoming_link_part2 (struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf);
/**
* Write a packet to the external network interface.
diff --git a/app/openvpn/src/openvpn/helper.c b/app/openvpn/src/openvpn/helper.c
index 0ed0b2ba..339e2aea 100644
--- a/app/openvpn/src/openvpn/helper.c
+++ b/app/openvpn/src/openvpn/helper.c
@@ -534,7 +534,7 @@ helper_tcp_nodelay (struct options *o)
}
else
{
- ASSERT (0);
+ o->sockflags |= SF_TCP_NODELAY;
}
}
#endif
diff --git a/app/openvpn/src/openvpn/init.c b/app/openvpn/src/openvpn/init.c
index 7cec8d9b..b5c81f87 100644
--- a/app/openvpn/src/openvpn/init.c
+++ b/app/openvpn/src/openvpn/init.c
@@ -1797,12 +1797,14 @@ do_deferred_options (struct context *c, const unsigned int found)
if (found & OPT_P_SETENV)
msg (D_PUSH, "OPTIONS IMPORT: environment modified");
+#ifdef ENABLE_SSL
if (found & OPT_P_PEER_ID)
{
msg (D_PUSH, "OPTIONS IMPORT: peer-id set");
c->c2.tls_multi->use_peer_id = true;
c->c2.tls_multi->peer_id = c->options.peer_id;
}
+#endif
}
/*
diff --git a/app/openvpn/src/openvpn/mtu.c b/app/openvpn/src/openvpn/mtu.c
index 13f3f6c6..3665a34d 100644
--- a/app/openvpn/src/openvpn/mtu.c
+++ b/app/openvpn/src/openvpn/mtu.c
@@ -158,8 +158,7 @@ set_mtu_discover_type (int sd, int mtu_type)
if (mtu_type >= 0)
{
#if defined(HAVE_SETSOCKOPT) && defined(SOL_IP) && defined(IP_MTU_DISCOVER)
- if (setsockopt
- (sd, SOL_IP, IP_MTU_DISCOVER, &mtu_type, sizeof (mtu_type)))
+ if (setsockopt (sd, SOL_IP, IP_MTU_DISCOVER, (void *) &mtu_type, sizeof (mtu_type)))
msg (M_ERR, "Error setting IP_MTU_DISCOVER type=%d on TCP/UDP socket",
mtu_type);
#else
@@ -288,7 +287,7 @@ void
set_sock_extended_error_passing (int sd)
{
int on = 1;
- if (setsockopt (sd, SOL_IP, IP_RECVERR, &on, sizeof (on)))
+ if (setsockopt (sd, SOL_IP, IP_RECVERR, (void *) &on, sizeof (on)))
msg (M_WARN | M_ERRNO,
"Note: enable extended error passing on TCP/UDP socket failed (IP_RECVERR)");
}
diff --git a/app/openvpn/src/openvpn/mudp.c b/app/openvpn/src/openvpn/mudp.c
index 51227a90..3e3f7508 100644
--- a/app/openvpn/src/openvpn/mudp.c
+++ b/app/openvpn/src/openvpn/mudp.c
@@ -33,67 +33,19 @@
#if P2MP_SERVER
#include "multi.h"
+#include <inttypes.h>
#include "forward-inline.h"
#include "memdbg.h"
/*
- * Update instance with new peer address
- */
-void
-update_floated(struct multi_context *m, struct multi_instance *mi,
- struct mroute_addr real, uint32_t hv)
-{
- struct mroute_addr real_old;
-
- real_old = mi->real;
- generate_prefix (mi);
-
- /* remove before modifying mi->real, since it also modifies key in hash */
- hash_remove(m->hash, &real_old);
- hash_remove(m->iter, &real_old);
-
- /* update address */
- memcpy(&mi->real, &real, sizeof(real));
-
- mi->context.c2.from = m->top.c2.from;
- mi->context.c2.to_link_addr = &mi->context.c2.from;
-
- /* switch to new log prefix */
- generate_prefix (mi);
- /* inherit buffers */
- mi->context.c2.buffers = m->top.c2.buffers;
-
- /* inherit parent link_socket and link_socket_info */
- mi->context.c2.link_socket = m->top.c2.link_socket;
- mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from;
-
- /* fix remote_addr in tls structure */
- tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from);
- mi->did_open_context = true;
-
- hash_add(m->hash, &mi->real, mi, false);
- hash_add(m->iter, &mi->real, mi, false);
-
- mi->did_real_hash = true;
-#ifdef MANAGEMENT_DEF_AUTH
- hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid);
- hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false);
-#endif
-
-#ifdef MANAGEMENT_DEF_AUTH
- mi->did_cid_hash = true;
-#endif
-}
-
-/*
* Get a client instance based on real address. If
* the instance doesn't exist, create it while
* maintaining real address hash table atomicity.
*/
struct multi_instance *
-multi_get_create_instance_udp (struct multi_context *m)
+multi_get_create_instance_udp (struct multi_context *m, bool *floated)
{
struct gc_arena gc = gc_new ();
struct mroute_addr real;
@@ -108,32 +60,25 @@ multi_get_create_instance_udp (struct multi_context *m)
uint8_t* ptr = BPTR(&m->top.c2.buf);
uint8_t op = ptr[0] >> P_OPCODE_SHIFT;
uint32_t peer_id;
- bool hmac_mismatch = false;
+ int i;
- if (op == P_DATA_V2)
+ /* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */
+ if (op == P_DATA_V2 && m->top.c2.buf.len >= (1 + 3))
{
- peer_id = ntohl((*(uint32_t*)ptr)) & 0xFFFFFF;
+ peer_id = ntohl(*(uint32_t*)ptr) & 0xFFFFFF;
if ((peer_id < m->max_clients) && (m->instances[peer_id]))
{
mi = m->instances[peer_id];
- if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from))
- {
- msg(D_MULTI_MEDIUM, "float from %s to %s",
- print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc));
+ *floated = !link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from);
- /* peer-id is not trusted, so check hmac */
- hmac_mismatch = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options));
- if (hmac_mismatch)
- {
- mi = NULL;
- msg (D_MULTI_MEDIUM, "HMAC mismatch for peer-id %d", peer_id);
- }
- else
- {
- update_floated(m, mi, real, hv);
- }
- }
+ if (*floated)
+ {
+ /* reset prefix, since here we are not sure peer is the one it claims to be */
+ ungenerate_prefix(mi);
+ msg (D_MULTI_ERRORS, "Untrusted peer %" PRIu32 " wants to float to %s", peer_id,
+ mroute_addr_print (&real, &gc));
+ }
}
}
else
@@ -144,7 +89,7 @@ multi_get_create_instance_udp (struct multi_context *m)
mi = (struct multi_instance *) he->value;
}
}
- if (!mi && !hmac_mismatch)
+ if (!mi)
{
if (!m->top.c2.tls_auth_standalone
|| tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf))
@@ -157,8 +102,7 @@ multi_get_create_instance_udp (struct multi_context *m)
hash_add_fast (hash, bucket, &mi->real, hv, mi);
mi->did_real_hash = true;
- int i;
- for (i = 0; i < m->max_clients; ++ i)
+ for (i = 0; i < m->max_clients; ++i)
{
if (!m->instances[i])
{
@@ -167,6 +111,10 @@ multi_get_create_instance_udp (struct multi_context *m)
break;
}
}
+
+ /* should not really end up here, since multi_create_instance returns null
+ * if amount of clients exceeds max_clients */
+ ASSERT(i < m->max_clients);
}
}
else
diff --git a/app/openvpn/src/openvpn/mudp.h b/app/openvpn/src/openvpn/mudp.h
index 97f961b3..1f15d9d2 100644
--- a/app/openvpn/src/openvpn/mudp.h
+++ b/app/openvpn/src/openvpn/mudp.h
@@ -65,7 +65,7 @@ void tunnel_server_udp (struct context *top);
* packet's source address or if one was a newly created successfully.
* NULL if one did not yet exist and a new one was not created.
*/
-struct multi_instance *multi_get_create_instance_udp (struct multi_context *m);
+struct multi_instance *multi_get_create_instance_udp (struct multi_context *m, bool *floated);
#endif
#endif
diff --git a/app/openvpn/src/openvpn/multi.c b/app/openvpn/src/openvpn/multi.c
index bd5948c8..90b3d2dc 100644
--- a/app/openvpn/src/openvpn/multi.c
+++ b/app/openvpn/src/openvpn/multi.c
@@ -39,6 +39,7 @@
#include "gremlin.h"
#include "mstats.h"
#include "ssl_verify.h"
+#include <inttypes.h>
#include "memdbg.h"
@@ -402,7 +403,7 @@ multi_instance_string (const struct multi_instance *mi, bool null, struct gc_are
{
if (mi)
{
- struct buffer out = alloc_buf_gc (256, gc);
+ struct buffer out = alloc_buf_gc (MULTI_PREFIX_MAX_LENGTH, gc);
const char *cn = tls_common_name (mi->context.c2.tls_multi, true);
if (cn)
@@ -419,21 +420,27 @@ multi_instance_string (const struct multi_instance *mi, bool null, struct gc_are
void
generate_prefix (struct multi_instance *mi)
{
- mi->msg_prefix = multi_instance_string (mi, true, &mi->gc);
+ struct gc_arena gc = gc_new();
+ const char *prefix = multi_instance_string (mi, true, &gc);
+ if (prefix)
+ strncpynt(mi->msg_prefix, prefix, sizeof(mi->msg_prefix));
+ else
+ mi->msg_prefix[0] = '\0';
set_prefix (mi);
+ gc_free(&gc);
}
void
ungenerate_prefix (struct multi_instance *mi)
{
- mi->msg_prefix = NULL;
+ mi->msg_prefix[0] = '\0';
set_prefix (mi);
}
static const char *
mi_prefix (const struct multi_instance *mi)
{
- if (mi && mi->msg_prefix)
+ if (mi && mi->msg_prefix[0])
return mi->msg_prefix;
else
return "UNDEF_I";
@@ -814,8 +821,8 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int
*/
status_printf (so, "TITLE%c%s", sep, title_string);
status_printf (so, "TIME%c%s%c%u", sep, time_string (now, 0, false, &gc_top), sep, (unsigned int)now);
- status_printf (so, "HEADER%cCLIENT_LIST%cCommon Name%cReal Address%cVirtual Address%cVirtual IPv6 Address%cBytes Received%cBytes Sent%cConnected Since%cConnected Since (time_t)%cUsername%cClient ID",
- sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep);
+ status_printf (so, "HEADER%cCLIENT_LIST%cCommon Name%cReal Address%cVirtual Address%cVirtual IPv6 Address%cBytes Received%cBytes Sent%cConnected Since%cConnected Since (time_t)%cUsername%cClient ID%cPeer ID",
+ sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep, sep);
hash_iterator_init (m->hash, &hi);
while ((he = hash_iterator_next (&hi)))
{
@@ -826,10 +833,11 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int
{
status_printf (so, "CLIENT_LIST%c%s%c%s%c%s%c%s%c" counter_format "%c" counter_format "%c%s%c%u%c%s%c"
#ifdef MANAGEMENT_DEF_AUTH
- "%lu",
+ "%lu"
#else
- "",
+ ""
#endif
+ "%c%"PRIu32,
sep, tls_common_name (mi->context.c2.tls_multi, false),
sep, mroute_addr_print (&mi->real, &gc),
sep, print_in_addr_t (mi->reporting_addr, IA_EMPTY_IF_UNDEF, &gc),
@@ -840,10 +848,11 @@ multi_print_status (struct multi_context *m, struct status_output *so, const int
sep, (unsigned int)mi->created,
sep, tls_username (mi->context.c2.tls_multi, false),
#ifdef MANAGEMENT_DEF_AUTH
- sep, mi->context.c2.mda_context.cid);
+ sep, mi->context.c2.mda_context.cid,
#else
- sep);
+ sep,
#endif
+ sep, mi->context.c2.tls_multi ? mi->context.c2.tls_multi->peer_id : UINT32_MAX);
}
gc_free (&gc);
}
@@ -2104,6 +2113,70 @@ multi_process_post (struct multi_context *m, struct multi_instance *mi, const un
return ret;
}
+void multi_process_float (struct multi_context* m, struct multi_instance* mi)
+{
+ struct mroute_addr real;
+ struct hash *hash = m->hash;
+ struct gc_arena gc = gc_new ();
+
+ if (!mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true))
+ goto done;
+
+ const uint32_t hv = hash_value (hash, &real);
+ struct hash_bucket *bucket = hash_bucket (hash, hv);
+
+ struct hash_element *he = hash_lookup_fast (hash, bucket, &real, hv);
+ if (he)
+ {
+ struct multi_instance *ex_mi = (struct multi_instance *) he->value;
+
+ const char *cn = tls_common_name (mi->context.c2.tls_multi, true);
+ const char *ex_cn = tls_common_name (ex_mi->context.c2.tls_multi, true);
+ if (cn && ex_cn && strcmp (cn, ex_cn))
+ {
+ msg (D_MULTI_MEDIUM, "prevent float to %s",
+ multi_instance_string (ex_mi, false, &gc));
+
+ mi->context.c2.buf.len = 0;
+
+ goto done;
+ }
+
+ msg (D_MULTI_MEDIUM, "closing instance %s", multi_instance_string (ex_mi, false, &gc));
+ multi_close_instance(m, ex_mi, false);
+ }
+
+ msg (D_MULTI_MEDIUM, "peer %" PRIu32 " floated from %s to %s", mi->context.c2.tls_multi->peer_id,
+ mroute_addr_print (&mi->real, &gc), print_link_socket_actual (&m->top.c2.from, &gc));
+
+ ASSERT (hash_remove(m->hash, &mi->real));
+ ASSERT (hash_remove(m->iter, &mi->real));
+
+ /* change external network address of the remote peer */
+ mi->real = real;
+ generate_prefix (mi);
+
+ mi->context.c2.from = m->top.c2.from;
+ mi->context.c2.to_link_addr = &mi->context.c2.from;
+
+ /* inherit parent link_socket and link_socket_info */
+ mi->context.c2.link_socket = m->top.c2.link_socket;
+ mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from;
+
+ tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from);
+
+ ASSERT (hash_add (m->hash, &mi->real, mi, false));
+ ASSERT (hash_add (m->iter, &mi->real, mi, false));
+
+#ifdef MANAGEMENT_DEF_AUTH
+ hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid);
+ hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false);
+#endif
+
+done:
+ gc_free (&gc);
+}
+
/*
* Process packets in the TCP/UDP socket -> TUN/TAP interface direction,
* i.e. client -> server direction.
@@ -2118,6 +2191,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
unsigned int mroute_flags;
struct multi_instance *mi;
bool ret = true;
+ bool floated = false;
if (m->pending)
return true;
@@ -2127,7 +2201,7 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
#ifdef MULTI_DEBUG_EVENT_LOOP
printf ("TCP/UDP -> TUN [%d]\n", BLEN (&m->top.c2.buf));
#endif
- multi_set_pending (m, multi_get_create_instance_udp (m));
+ multi_set_pending (m, multi_get_create_instance_udp (m, &floated));
}
else
multi_set_pending (m, instance);
@@ -2145,13 +2219,30 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins
c->c2.buf = m->top.c2.buf;
/* transfer from-addr from top-level context buffer to instance */
- c->c2.from = m->top.c2.from;
+ if (!floated)
+ c->c2.from = m->top.c2.from;
}
if (BLEN (&c->c2.buf) > 0)
{
+ struct link_socket_info *lsi;
+ const uint8_t *orig_buf;
+
/* decrypt in instance context */
- process_incoming_link (c);
+
+ perf_push (PERF_PROC_IN_LINK);
+ lsi = get_link_socket_info (c);
+ orig_buf = c->c2.buf.data;
+ if (process_incoming_link_part1(c, lsi, floated))
+ {
+ if (floated)
+ {
+ multi_process_float (m, m->pending);
+ }
+
+ process_incoming_link_part2(c, lsi, orig_buf);
+ }
+ perf_pop ();
if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TUN)
{
diff --git a/app/openvpn/src/openvpn/multi.h b/app/openvpn/src/openvpn/multi.h
index 0446fbfc..32b89d25 100644
--- a/app/openvpn/src/openvpn/multi.h
+++ b/app/openvpn/src/openvpn/multi.h
@@ -42,6 +42,8 @@
#include "mtcp.h"
#include "perf.h"
+#define MULTI_PREFIX_MAX_LENGTH 256
+
/*
* Walk (don't run) through the routing table,
* deleting old entries, and possibly multi_instance
@@ -80,7 +82,7 @@ struct multi_instance {
struct mroute_addr real; /**< External network address of the
* remote peer. */
ifconfig_pool_handle vaddr_handle;
- const char *msg_prefix;
+ char msg_prefix[MULTI_PREFIX_MAX_LENGTH];
/* queued outgoing data in Server/TCP mode */
unsigned int tcp_rwflags;
@@ -125,7 +127,8 @@ struct multi_context {
# define MC_WORK_THREAD (MC_MULTI_THREADED_WORKER|MC_MULTI_THREADED_SCHEDULER)
int thread_mode;
- struct multi_instance** instances;
+ struct multi_instance** instances; /**< Array of multi_instances. An instance can be
+ * accessed using peer-id as an index. */
struct hash *hash; /**< VPN tunnel instances indexed by real
* address of the remote peer. */
@@ -220,6 +223,16 @@ void multi_close_instance (struct multi_context *m, struct multi_instance *mi, b
bool multi_process_timeout (struct multi_context *m, const unsigned int mpp_flags);
+/**
+ * Handles peer floating.
+ *
+ * If peer is floated to a taken address, either drops packet
+ * (if peer that owns address has different CN) or disconnects
+ * existing peer. Updates multi_instance with new address,
+ * updates hashtables in multi_context.
+ */
+void multi_process_float (struct multi_context* m, struct multi_instance* mi);
+
#define MPP_PRE_SELECT (1<<0)
#define MPP_CONDITIONAL_PRE_SELECT (1<<1)
#define MPP_CLOSE_ON_SIGNAL (1<<2)
@@ -421,6 +434,12 @@ multi_route_defined (const struct multi_context *m,
}
/*
+ * Takes prefix away from multi_instance.
+ */
+void
+ungenerate_prefix (struct multi_instance *mi);
+
+/*
* Set a msg() function prefix with our current client instance ID.
*/
@@ -428,10 +447,10 @@ static inline void
set_prefix (struct multi_instance *mi)
{
#ifdef MULTI_DEBUG_EVENT_LOOP
- if (mi->msg_prefix)
+ if (mi->msg_prefix[0])
printf ("[%s]\n", mi->msg_prefix);
#endif
- msg_set_prefix (mi->msg_prefix);
+ msg_set_prefix (mi->msg_prefix[0] ? mi->msg_prefix : NULL);
}
static inline void
diff --git a/app/openvpn/src/openvpn/options.c b/app/openvpn/src/openvpn/options.c
index 1ca4ad57..763e2cbc 100644
--- a/app/openvpn/src/openvpn/options.c
+++ b/app/openvpn/src/openvpn/options.c
@@ -570,6 +570,7 @@ static const char usage_message[] =
"--tls-version-min <version> ['or-highest'] : sets the minimum TLS version we\n"
" will accept from the peer. If version is unrecognized and 'or-highest'\n"
" is specified, require max TLS version supported by SSL implementation.\n"
+ "--tls-version-max <version> : sets the maximum TLS version we will use.\n"
#ifndef ENABLE_CRYPTO_POLARSSL
"--pkcs12 file : PKCS#12 file containing local private key, local certificate\n"
" and optionally the root CA certificate.\n"
@@ -1976,9 +1977,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
if (ce->proto == PROTO_TCP_SERVER && (options->connection_list->len > 1))
msg (M_USAGE, "TCP server mode allows at most one --remote address");
- if (options->routes && ((options->routes->flags & RG_BLOCK_LOCAL) && (options->routes->flags & RG_UNBLOCK_LOCAL)))
- msg (M_USAGE, "unblock-local and block-local options of redirect-gateway/redirect-private are mutatlly exclusive");
-
#if P2MP_SERVER
/*
@@ -2038,7 +2036,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
#endif
if (options->routes && (options->routes->flags & RG_ENABLE))
msg (M_USAGE, "--redirect-gateway cannot be used with --mode server (however --push \"redirect-gateway\" is fine)");
-
if (options->route_delay_defined)
msg (M_USAGE, "--route-delay cannot be used with --mode server");
if (options->up_delay)
@@ -2106,7 +2103,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
if (options->ssl_flags & SSLF_OPT_VERIFY)
msg (M_USAGE, "--opt-verify requires --mode server");
if (options->server_flags & SF_TCP_NODELAY_HELPER)
- msg (M_USAGE, "--tcp-nodelay requires --mode server");
+ msg (M_WARN, "WARNING: setting tcp-nodelay on the client side will not "
+ "affect the server. To have TCP_NODELAY in both direction use "
+ "tcp-nodelay in the server configuration instead.");
if (options->auth_user_pass_verify_script)
msg (M_USAGE, "--auth-user-pass-verify requires --mode server");
#if PORT_SHARE
@@ -3898,8 +3897,7 @@ apply_push_options (struct options *options,
struct buffer *buf,
unsigned int permission_mask,
unsigned int *option_types_found,
- struct env_set *es,
- struct tls_multi *tls_multi)
+ struct env_set *es)
{
char line[OPTION_PARM_SIZE];
int line_num = 0;
@@ -5325,8 +5323,6 @@ add_option (struct options *options,
options->routes->flags |= RG_BYPASS_DNS;
else if (streq (p[j], "block-local"))
options->routes->flags |= RG_BLOCK_LOCAL;
- else if (streq (p[j], "unblock-local"))
- options->routes->flags |= RG_UNBLOCK_LOCAL;
else
{
msg (msglevel, "unknown --%s flag: %s", p[0], p[j]);
@@ -6568,14 +6564,29 @@ add_option (struct options *options,
{
int ver;
VERIFY_PERMISSION (OPT_P_GENERAL);
- ver = tls_version_min_parse(p[1], p[2]);
+ ver = tls_version_parse(p[1], p[2]);
if (ver == TLS_VER_BAD)
{
msg (msglevel, "unknown tls-version-min parameter: %s", p[1]);
goto err;
}
- options->ssl_flags &= ~(SSLF_TLS_VERSION_MASK << SSLF_TLS_VERSION_SHIFT);
- options->ssl_flags |= (ver << SSLF_TLS_VERSION_SHIFT);
+ options->ssl_flags &=
+ ~(SSLF_TLS_VERSION_MIN_MASK << SSLF_TLS_VERSION_MIN_SHIFT);
+ options->ssl_flags |= (ver << SSLF_TLS_VERSION_MIN_SHIFT);
+ }
+ else if (streq (p[0], "tls-version-max") && p[1])
+ {
+ int ver;
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ ver = tls_version_parse(p[1], NULL);
+ if (ver == TLS_VER_BAD)
+ {
+ msg (msglevel, "unknown tls-version-max parameter: %s", p[1]);
+ goto err;
+ }
+ options->ssl_flags &=
+ ~(SSLF_TLS_VERSION_MAX_MASK << SSLF_TLS_VERSION_MAX_SHIFT);
+ options->ssl_flags |= (ver << SSLF_TLS_VERSION_MAX_SHIFT);
}
#ifndef ENABLE_CRYPTO_POLARSSL
else if (streq (p[0], "pkcs12") && p[1])
diff --git a/app/openvpn/src/openvpn/options.h b/app/openvpn/src/openvpn/options.h
index d5f7e95d..a51b8ab5 100644
--- a/app/openvpn/src/openvpn/options.h
+++ b/app/openvpn/src/openvpn/options.h
@@ -716,13 +716,11 @@ void options_postprocess (struct options *options);
void pre_pull_save (struct options *o);
void pre_pull_restore (struct options *o, struct gc_arena *gc);
-struct tls_multi;
bool apply_push_options (struct options *options,
struct buffer *buf,
unsigned int permission_mask,
unsigned int *option_types_found,
- struct env_set *es,
- struct tls_multi* tls_multi);
+ struct env_set *es);
void options_detach (struct options *o);
diff --git a/app/openvpn/src/openvpn/push.c b/app/openvpn/src/openvpn/push.c
index c7844499..385be1d5 100644
--- a/app/openvpn/src/openvpn/push.c
+++ b/app/openvpn/src/openvpn/push.c
@@ -475,8 +475,7 @@ process_incoming_push_msg (struct context *c,
&buf,
permission_mask,
option_types_found,
- c->c2.es,
- c->c2.tls_multi))
+ c->c2.es))
switch (c->options.push_continuation)
{
case 0:
diff --git a/app/openvpn/src/openvpn/route.c b/app/openvpn/src/openvpn/route.c
index c330169a..1cb98c03 100644
--- a/app/openvpn/src/openvpn/route.c
+++ b/app/openvpn/src/openvpn/route.c
@@ -277,7 +277,7 @@ init_route (struct route_ipv4 *r,
/* get_special_addr replaces specialaddr with a special ip addr
like gw. getaddrinfo is called to convert a a addrinfo struct */
- if(get_special_addr (rl, ro->network, &special.s_addr, &status))
+ if(get_special_addr (rl, ro->network, (in_addr_t *) &special.s_addr, &status))
{
special.s_addr = htonl(special.s_addr);
ret = openvpn_getaddrinfo(0, inet_ntoa(special), NULL, 0, NULL,
@@ -520,51 +520,6 @@ add_block_local_item (struct route_list *rl,
}
static void
-add_unblock_local (struct route_list *rl)
-{
- const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
-
- if (rl->flags & RG_UNBLOCK_LOCAL
- && (rl->rgi.flags & rgi_needed) == rgi_needed)
- {
- /* unblock access to local subnet */
- struct route_ipv4 *r;
-
- ALLOC_OBJ_GC (r, struct route_ipv4, &rl->gc);
- int i;
-
- CLEAR(*r);
- r->flags = RT_DEFINED;
- r->network = rl->rgi.gateway.addr & rl->rgi.gateway.netmask;
- r->netmask = rl->rgi.gateway.netmask;
- r->gateway = rl->rgi.gateway.addr;
- r->next = rl->routes;
- rl->routes = r;
-
- /* Additional local networks */
- for (i = 0; i < rl->rgi.n_addrs; ++i)
- {
- const struct route_gateway_address *gwa = &rl->rgi.addrs[i];
-
- /* omit the add/subnet in &rl->rgi which we processed above */
- if (!((rl->rgi.gateway.addr & rl->rgi.gateway.netmask) == (gwa->addr & gwa->netmask)
- && rl->rgi.gateway.netmask == gwa->netmask))
- {
- ALLOC_OBJ_GC (r, struct route_ipv4, &rl->gc);
- CLEAR(*r);
- r->flags = RT_DEFINED;
- r->network = gwa->addr & gwa->netmask;
- r->netmask = gwa->netmask;
- r->gateway = gwa->addr;
- r->next = rl->routes;
- rl->routes=r;
- }
- }
- }
-}
-
-
-static void
add_block_local (struct route_list *rl)
{
const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
@@ -595,8 +550,6 @@ add_block_local (struct route_list *rl)
}
}
-
-
bool
init_route_list (struct route_list *rl,
const struct route_option_list *opt,
@@ -665,8 +618,6 @@ init_route_list (struct route_list *rl,
}
}
-
- add_unblock_local (rl);
if (rl->flags & RG_ENABLE)
{
add_block_local (rl);
@@ -863,12 +814,10 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
{
msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
}
-#ifndef TARGET_ANDROID
else if (!(rl->rgi.flags & RGI_ADDR_DEFINED))
{
msg (M_WARN, "%s Cannot read current default gateway from system", err);
}
-#endif
else if (!(rl->spec.flags & RTSA_REMOTE_HOST))
{
msg (M_WARN, "%s Cannot obtain current remote host address", err);
@@ -2538,6 +2487,7 @@ get_default_gateway (struct route_gateway_info *rgi)
CLEAR(*rgi);
+#ifndef TARGET_ANDROID
/* get default gateway IP addr */
{
FILE *fp = fopen ("/proc/net/route", "r");
@@ -2594,6 +2544,12 @@ get_default_gateway (struct route_gateway_info *rgi)
}
}
}
+#else
+ /* Android, set some pseudo GW, addr is in host byte order */
+ rgi->gateway.addr = 127 << 24 | 'd' << 16 | 'g' << 8 | 'w';
+ rgi->flags |= RGI_ADDR_DEFINED;
+ strcpy(best_name, "android-gw");
+#endif
/* scan adapter list */
if (rgi->flags & RGI_ADDR_DEFINED)
diff --git a/app/openvpn/src/openvpn/route.h b/app/openvpn/src/openvpn/route.h
index 2b1ae3e8..f3c01501 100644
--- a/app/openvpn/src/openvpn/route.h
+++ b/app/openvpn/src/openvpn/route.h
@@ -88,7 +88,6 @@ struct route_option {
#define RG_REROUTE_GW (1<<5)
#define RG_AUTO_LOCAL (1<<6)
#define RG_BLOCK_LOCAL (1<<7)
-#define RG_UNBLOCK_LOCAL (1<<8)
struct route_option_list {
unsigned int flags; /* RG_x flags */
diff --git a/app/openvpn/src/openvpn/socket.c b/app/openvpn/src/openvpn/socket.c
index c649d627..331a9d9f 100644
--- a/app/openvpn/src/openvpn/socket.c
+++ b/app/openvpn/src/openvpn/socket.c
@@ -729,7 +729,7 @@ static inline void
socket_set_mark (int sd, int mark)
{
#if defined(TARGET_LINUX) && HAVE_DECL_SO_MARK
- if (mark && setsockopt (sd, SOL_SOCKET, SO_MARK, &mark, sizeof (mark)) != 0)
+ if (mark && setsockopt (sd, SOL_SOCKET, SO_MARK, (void *) &mark, sizeof (mark)) != 0)
msg (M_WARN, "NOTE: setsockopt SO_MARK=%d failed", mark);
#endif
}
@@ -1081,6 +1081,14 @@ socket_listen_accept (socket_descriptor_t sd,
return new_sd;
}
+/* older mingw versions and WinXP do not have this define,
+ * but Vista and up support the functionality - just define it here
+ */
+#ifdef WIN32
+# ifndef IPV6_V6ONLY
+# define IPV6_V6ONLY 27
+# endif
+#endif
void
socket_bind (socket_descriptor_t sd,
struct addrinfo *local,
@@ -1117,7 +1125,7 @@ socket_bind (socket_descriptor_t sd,
int v6only = ipv6only ? 1: 0; /* setsockopt must have an "int" */
msg (M_INFO, "setsockopt(IPV6_V6ONLY=%d)", v6only);
- if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)))
+ if (setsockopt (sd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &v6only, sizeof(v6only)))
{
msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only);
}
@@ -1211,7 +1219,7 @@ openvpn_connect (socket_descriptor_t sd,
}
}
#else
- status = connect (sd, &remote->addr.sa, af_addr_size(remote->addr.sa.sa_family));
+ status = connect (sd, remote, af_addr_size(remote->sa_family));
if (status)
status = openvpn_errno ();
#endif
@@ -2658,7 +2666,7 @@ proto_is_tcp(int proto)
{
if (proto < 0 || proto >= PROTO_N)
ASSERT(0);
- return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER || proto == PROTO_TCP_CLIENT;
+ return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER;
}
int
@@ -2916,6 +2924,7 @@ link_socket_read_udp_posix (struct link_socket *sock,
#endif
buf->len = recvfrom (sock->sd, BPTR (buf), maxsize, 0,
&from->dest.addr.sa, &fromlen);
+ /* FIXME: won't do anything when sock->info.af == AF_UNSPEC */
if (buf->len >= 0 && expectedlen && fromlen != expectedlen)
bad_address_length (fromlen, expectedlen);
return buf->len;
@@ -3060,10 +3069,7 @@ socket_recv_queue (struct link_socket *sock, int maxsize)
if (proto_is_udp(sock->info.proto))
{
sock->reads.addr_defined = true;
- if (sock->info.af == AF_INET)
- sock->reads.addrlen = sizeof (sock->reads.addr);
- else
- sock->reads.addrlen = sizeof (sock->reads.addr6);
+ sock->reads.addrlen = sizeof (sock->reads.addr6);
status = WSARecvFrom(
sock->sd,
wsabuf,
@@ -3095,9 +3101,10 @@ socket_recv_queue (struct link_socket *sock, int maxsize)
if (!status) /* operation completed immediately? */
{
- int addrlen = af_addr_size(sock->info.lsa->local.addr.sa.sa_family);
- if (sock->reads.addr_defined && sock->reads.addrlen != addrlen)
- bad_address_length (sock->reads.addrlen, addrlen);
+ /* FIXME: won't do anything when sock->info.af == AF_UNSPEC */
+ int af_len = af_addr_size (sock->info.af);
+ if (sock->reads.addr_defined && af_len && sock->reads.addrlen != af_len)
+ bad_address_length (sock->reads.addrlen, af_len);
sock->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
/* since we got an immediate return, we must signal the event object ourselves */
@@ -3159,7 +3166,7 @@ socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct li
{
/* set destination address for UDP writes */
sock->writes.addr_defined = true;
- if (sock->info.af == AF_INET6)
+ if (to->dest.addr.sa.sa_family == AF_INET6)
{
sock->writes.addr6 = to->dest.addr.in6;
sock->writes.addrlen = sizeof (sock->writes.addr6);
diff --git a/app/openvpn/src/openvpn/ssl.c b/app/openvpn/src/openvpn/ssl.c
index f79f42d9..cdc8eb19 100644
--- a/app/openvpn/src/openvpn/ssl.c
+++ b/app/openvpn/src/openvpn/ssl.c
@@ -454,7 +454,7 @@ ssl_put_auth_challenge (const char *cr_str)
* return tls_version_max().
*/
int
-tls_version_min_parse(const char *vstr, const char *extra)
+tls_version_parse(const char *vstr, const char *extra)
{
const int max_version = tls_version_max();
if (!strcmp(vstr, "1.0") && TLS_VER_1_0 <= max_version)
@@ -2036,7 +2036,11 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
ASSERT (session->opt->key_method == 2);
/* discard leading uint32 */
- ASSERT (buf_advance (buf, 4));
+ if (!buf_advance (buf, 4)) {
+ msg (D_TLS_ERRORS, "TLS ERROR: Plaintext buffer too short (%d bytes).",
+ buf->len);
+ goto error;
+ }
/* get key method */
key_method_flags = buf_read_u8 (buf);
@@ -2773,7 +2777,8 @@ bool
tls_pre_decrypt (struct tls_multi *multi,
const struct link_socket_actual *from,
struct buffer *buf,
- struct crypto_options *opt)
+ struct crypto_options *opt,
+ bool floated)
{
struct gc_arena gc = gc_new ();
bool ret = false;
@@ -2817,7 +2822,7 @@ tls_pre_decrypt (struct tls_multi *multi,
#ifdef ENABLE_DEF_AUTH
&& !ks->auth_deferred
#endif
- && link_socket_actual_match (from, &ks->remote_addr))
+ && (floated || link_socket_actual_match (from, &ks->remote_addr)))
{
/* return appropriate data channel decrypt key in opt */
opt->key_ctx_bi = &ks->key;
@@ -3492,27 +3497,30 @@ tls_rec_payload (struct tls_multi *multi,
return ret;
}
-/* Update the remote_addr, needed if a client floats. */
void
-tls_update_remote_addr (struct tls_multi *multi,
-const struct link_socket_actual *from)
+tls_update_remote_addr (struct tls_multi *multi, const struct link_socket_actual *addr)
{
struct gc_arena gc = gc_new ();
- int i;
+ int i, j;
- for (i = 0; i < KEY_SCAN_SIZE; ++i)
+ for (i = 0; i < TM_SIZE; ++i)
{
- struct key_state *ks = multi->key_scan[i];
- if (DECRYPT_KEY_ENABLED (multi, ks) && ks->authenticated && link_socket_actual_defined(&ks->remote_addr))
- {
- if (link_socket_actual_match (from, &ks->remote_addr))
- continue;
- dmsg (D_TLS_KEYSELECT,
- "TLS: tls_update_remote_addr from IP=%s to IP=%s",
+ struct tls_session *session = &multi->session[i];
+
+ for (j = 0; j < KS_SIZE; ++j)
+ {
+ struct key_state *ks = &session->key[j];
+
+ if (!link_socket_actual_defined(&ks->remote_addr) ||
+ link_socket_actual_match (addr, &ks->remote_addr))
+ continue;
+
+ dmsg (D_TLS_KEYSELECT, "TLS: tls_update_remote_addr from IP=%s to IP=%s",
print_link_socket_actual (&ks->remote_addr, &gc),
- print_link_socket_actual (from, &gc));
- memcpy(&ks->remote_addr, from, sizeof(*from));
- }
+ print_link_socket_actual (addr, &gc));
+
+ ks->remote_addr = *addr;
+ }
}
gc_free (&gc);
}
diff --git a/app/openvpn/src/openvpn/ssl.h b/app/openvpn/src/openvpn/ssl.h
index a338745e..7e5a203e 100644
--- a/app/openvpn/src/openvpn/ssl.h
+++ b/app/openvpn/src/openvpn/ssl.h
@@ -306,7 +306,8 @@ int tls_multi_process (struct tls_multi *multi,
bool tls_pre_decrypt (struct tls_multi *multi,
const struct link_socket_actual *from,
struct buffer *buf,
- struct crypto_options *opt);
+ struct crypto_options *opt,
+ bool floated);
/**************************************************************************/
@@ -431,11 +432,14 @@ bool tls_send_payload (struct tls_multi *multi,
bool tls_rec_payload (struct tls_multi *multi,
struct buffer *buf);
-/*
- * Update remote address of a tls_multi structure
+/**
+ * Updates remote address in TLS sessions.
+ *
+ * @param multi - Tunnel to update
+ * @param addr - new address
*/
void tls_update_remote_addr (struct tls_multi *multi,
- const struct link_socket_actual *from);
+ const struct link_socket_actual *addr);
#ifdef MANAGEMENT_DEF_AUTH
static inline char *
diff --git a/app/openvpn/src/openvpn/ssl_backend.h b/app/openvpn/src/openvpn/ssl_backend.h
index bfd15496..b0777bf5 100644
--- a/app/openvpn/src/openvpn/ssl_backend.h
+++ b/app/openvpn/src/openvpn/ssl_backend.h
@@ -109,11 +109,12 @@ void tls_clear_error();
* @return One of the TLS_VER_x constants or TLS_VER_BAD
* if a parse error should be flagged.
*/
-#define TLS_VER_BAD -1
-#define TLS_VER_1_0 0 /* default */
-#define TLS_VER_1_1 1
-#define TLS_VER_1_2 2
-int tls_version_min_parse(const char *vstr, const char *extra);
+#define TLS_VER_BAD -1
+#define TLS_VER_UNSPEC 0 /* default */
+#define TLS_VER_1_0 1
+#define TLS_VER_1_1 2
+#define TLS_VER_1_2 3
+int tls_version_parse(const char *vstr, const char *extra);
/**
* Return the maximum TLS version (as a TLS_VER_x constant)
diff --git a/app/openvpn/src/openvpn/ssl_common.h b/app/openvpn/src/openvpn/ssl_common.h
index cb0ba628..6222bd67 100644
--- a/app/openvpn/src/openvpn/ssl_common.h
+++ b/app/openvpn/src/openvpn/ssl_common.h
@@ -296,8 +296,10 @@ struct tls_options
# define SSLF_AUTH_USER_PASS_OPTIONAL (1<<2)
# define SSLF_OPT_VERIFY (1<<4)
# define SSLF_CRL_VERIFY_DIR (1<<5)
-# define SSLF_TLS_VERSION_SHIFT 6
-# define SSLF_TLS_VERSION_MASK 0xF /* (uses bit positions 6 to 9) */
+# define SSLF_TLS_VERSION_MIN_SHIFT 6
+# define SSLF_TLS_VERSION_MIN_MASK 0xF /* (uses bit positions 6 to 9) */
+# define SSLF_TLS_VERSION_MAX_SHIFT 10
+# define SSLF_TLS_VERSION_MAX_MASK 0xF /* (uses bit positions 10 to 13) */
unsigned int ssl_flags;
#ifdef MANAGEMENT_DEF_AUTH
diff --git a/app/openvpn/src/openvpn/ssl_openssl.c b/app/openvpn/src/openvpn/ssl_openssl.c
index adf3ae6f..6782a953 100644
--- a/app/openvpn/src/openvpn/ssl_openssl.c
+++ b/app/openvpn/src/openvpn/ssl_openssl.c
@@ -184,15 +184,23 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags)
/* process SSL options including minimum TLS version we will accept from peer */
{
long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
- const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
- if (tls_version_min > TLS_VER_1_0)
+ int tls_ver_max = TLS_VER_UNSPEC;
+ const int tls_ver_min =
+ (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK;
+
+ tls_ver_max =
+ (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK;
+ if (tls_ver_max <= TLS_VER_UNSPEC)
+ tls_ver_max = tls_version_max();
+
+ if (tls_ver_min > TLS_VER_1_0 || tls_ver_max < TLS_VER_1_0)
sslopt |= SSL_OP_NO_TLSv1;
#ifdef SSL_OP_NO_TLSv1_1
- if (tls_version_min > TLS_VER_1_1)
+ if (tls_ver_min > TLS_VER_1_1 || tls_ver_max < TLS_VER_1_1)
sslopt |= SSL_OP_NO_TLSv1_1;
#endif
#ifdef SSL_OP_NO_TLSv1_2
- if (tls_version_min > TLS_VER_1_2)
+ if (tls_ver_min > TLS_VER_1_2 || tls_ver_max < TLS_VER_1_2)
sslopt |= SSL_OP_NO_TLSv1_2;
#endif
SSL_CTX_set_options (ctx->ctx, sslopt);
diff --git a/app/openvpn/src/openvpn/ssl_polarssl.c b/app/openvpn/src/openvpn/ssl_polarssl.c
index 387e6369..20368857 100644
--- a/app/openvpn/src/openvpn/ssl_polarssl.c
+++ b/app/openvpn/src/openvpn/ssl_polarssl.c
@@ -685,6 +685,40 @@ tls_version_max(void)
#endif
}
+/**
+ * Convert an OpenVPN tls-version variable to PolarSSl format (i.e. a major and
+ * minor ssl version number).
+ *
+ * @param tls_ver The tls-version variable to convert.
+ * @param major Returns the TLS major version in polarssl format.
+ * Must be a valid pointer.
+ * @param minor Returns the TLS minor version in polarssl format.
+ * Must be a valid pointer.
+ */
+static void tls_version_to_major_minor(int tls_ver, int *major, int *minor) {
+ ASSERT(major);
+ ASSERT(minor);
+
+ switch (tls_ver)
+ {
+ case TLS_VER_1_0:
+ *major = SSL_MAJOR_VERSION_3;
+ *minor = SSL_MINOR_VERSION_1;
+ break;
+ case TLS_VER_1_1:
+ *major = SSL_MAJOR_VERSION_3;
+ *minor = SSL_MINOR_VERSION_2;
+ break;
+ case TLS_VER_1_2:
+ *major = SSL_MAJOR_VERSION_3;
+ *minor = SSL_MINOR_VERSION_3;
+ break;
+ default:
+ msg(M_FATAL, "%s: invalid TLS version %d", __func__, tls_ver);
+ break;
+ }
+}
+
void key_state_ssl_init(struct key_state_ssl *ks_ssl,
const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session)
{
@@ -743,30 +777,32 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl,
/* Initialize minimum TLS version */
{
- const int tls_version_min = (session->opt->ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK;
- int polar_major;
- int polar_minor;
- switch (tls_version_min)
+ const int tls_version_min =
+ (session->opt->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) &
+ SSLF_TLS_VERSION_MIN_MASK;
+
+ /* default to TLS 1.0 */
+ int major = SSL_MAJOR_VERSION_3;
+ int minor = SSL_MINOR_VERSION_1;
+
+ if (tls_version_min > TLS_VER_UNSPEC)
+ tls_version_to_major_minor(tls_version_min, &major, &minor);
+
+ ssl_set_min_version(ks_ssl->ctx, major, minor);
+ }
+
+ /* Initialize maximum TLS version */
+ {
+ const int tls_version_max =
+ (session->opt->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) &
+ SSLF_TLS_VERSION_MAX_MASK;
+
+ if (tls_version_max > TLS_VER_UNSPEC)
{
- case TLS_VER_1_0:
- default:
- polar_major = SSL_MAJOR_VERSION_3;
- polar_minor = SSL_MINOR_VERSION_1;
- break;
-#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2)
- case TLS_VER_1_1:
- polar_major = SSL_MAJOR_VERSION_3;
- polar_minor = SSL_MINOR_VERSION_2;
- break;
-#endif
-#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3)
- case TLS_VER_1_2:
- polar_major = SSL_MAJOR_VERSION_3;
- polar_minor = SSL_MINOR_VERSION_3;
- break;
-#endif
+ int major, minor;
+ tls_version_to_major_minor(tls_version_max, &major, &minor);
+ ssl_set_max_version(ks_ssl->ctx, major, minor);
}
- ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor);
}
/* Initialise BIOs */
@@ -810,8 +846,8 @@ key_state_write_plaintext (struct key_state_ssl *ks, struct buffer *buf)
if (0 == buf->len)
{
- return 0;
perf_pop ();
+ return 0;
}
retval = ssl_write(ks->ctx, BPTR(buf), buf->len);
diff --git a/app/openvpn/src/plugins/down-root/down-root.c b/app/openvpn/src/plugins/down-root/down-root.c
index d51d0e55..6931becf 100644
--- a/app/openvpn/src/plugins/down-root/down-root.c
+++ b/app/openvpn/src/plugins/down-root/down-root.c
@@ -5,7 +5,8 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2013 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2013 David Sommerseth <davids@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -40,14 +41,16 @@
#include <fcntl.h>
#include <signal.h>
#include <syslog.h>
+#include <errno.h>
+#include <err.h>
#include <openvpn-plugin.h>
#define DEBUG(verb) ((verb) >= 7)
/* Command codes for foreground -> background communication */
-#define COMMAND_RUN_SCRIPT 0
-#define COMMAND_EXIT 1
+#define COMMAND_RUN_SCRIPT 1
+#define COMMAND_EXIT 2
/* Response codes for background -> foreground communication */
#define RESPONSE_INIT_SUCCEEDED 10
@@ -56,24 +59,24 @@
#define RESPONSE_SCRIPT_FAILED 13
/* Background process function */
-static void down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb);
+static void down_root_server (const int fd, char * const * argv, char * const *envp, const int verb);
/*
* Plugin state, used by foreground
*/
struct down_root_context
{
- /* Foreground's socket to background process */
- int foreground_fd;
+ /* Foreground's socket to background process */
+ int foreground_fd;
- /* Process ID of background process */
- pid_t background_pid;
+ /* Process ID of background process */
+ pid_t background_pid;
- /* Verbosity level of OpenVPN */
- int verb;
+ /* Verbosity level of OpenVPN */
+ int verb;
- /* down command */
- char *command;
+ /* down command */
+ char **command;
};
/*
@@ -84,21 +87,21 @@ struct down_root_context
static const char *
get_env (const char *name, const char *envp[])
{
- if (envp)
+ if (envp)
{
- int i;
- const int namelen = strlen (name);
- for (i = 0; envp[i]; ++i)
- {
- if (!strncmp (envp[i], name, namelen))
- {
- const char *cp = envp[i] + namelen;
- if (*cp == '=')
- return cp + 1;
- }
- }
+ int i;
+ const int namelen = strlen (name);
+ for (i = 0; envp[i]; ++i)
+ {
+ if (!strncmp (envp[i], name, namelen))
+ {
+ const char *cp = envp[i] + namelen;
+ if (*cp == '=')
+ return cp + 1;
+ }
+ }
}
- return NULL;
+ return NULL;
}
/*
@@ -107,13 +110,13 @@ get_env (const char *name, const char *envp[])
static int
string_array_len (const char *array[])
{
- int i = 0;
- if (array)
+ int i = 0;
+ if (array)
{
- while (array[i])
- ++i;
+ while (array[i])
+ ++i;
}
- return i;
+ return i;
}
/*
@@ -123,23 +126,23 @@ string_array_len (const char *array[])
static int
recv_control (int fd)
{
- unsigned char c;
- const ssize_t size = read (fd, &c, sizeof (c));
- if (size == sizeof (c))
- return c;
- else
- return -1;
+ unsigned char c;
+ const ssize_t size = read (fd, &c, sizeof (c));
+ if (size == sizeof (c))
+ return c;
+ else
+ return -1;
}
static int
send_control (int fd, int code)
{
- unsigned char c = (unsigned char) code;
- const ssize_t size = write (fd, &c, sizeof (c));
- if (size == sizeof (c))
- return (int) size;
- else
- return -1;
+ unsigned char c = (unsigned char) code;
+ const ssize_t size = write (fd, &c, sizeof (c));
+ if (size == sizeof (c))
+ return (int) size;
+ else
+ return -1;
}
/*
@@ -150,22 +153,22 @@ send_control (int fd, int code)
static void
daemonize (const char *envp[])
{
- const char *daemon_string = get_env ("daemon", envp);
- if (daemon_string && daemon_string[0] == '1')
+ const char *daemon_string = get_env ("daemon", envp);
+ if (daemon_string && daemon_string[0] == '1')
{
- const char *log_redirect = get_env ("daemon_log_redirect", envp);
- int fd = -1;
- if (log_redirect && log_redirect[0] == '1')
- fd = dup (2);
- if (daemon (0, 0) < 0)
- {
- fprintf (stderr, "DOWN-ROOT: daemonization failed\n");
- }
- else if (fd >= 3)
- {
- dup2 (fd, 2);
- close (fd);
- }
+ const char *log_redirect = get_env ("daemon_log_redirect", envp);
+ int fd = -1;
+ if (log_redirect && log_redirect[0] == '1')
+ fd = dup (2);
+ if (daemon (0, 0) < 0)
+ {
+ warn ("DOWN-ROOT: daemonization failed");
+ }
+ else if (fd >= 3)
+ {
+ dup2 (fd, 2);
+ close (fd);
+ }
}
}
@@ -182,12 +185,12 @@ daemonize (const char *envp[])
static void
close_fds_except (int keep)
{
- int i;
- closelog ();
- for (i = 3; i <= 100; ++i)
+ int i;
+ closelog ();
+ for (i = 3; i <= 100; ++i)
{
- if (i != keep)
- close (i);
+ if (i != keep)
+ close (i);
}
}
@@ -198,254 +201,261 @@ close_fds_except (int keep)
static void
set_signals (void)
{
- signal (SIGTERM, SIG_DFL);
+ signal (SIGTERM, SIG_DFL);
- signal (SIGINT, SIG_IGN);
- signal (SIGHUP, SIG_IGN);
- signal (SIGUSR1, SIG_IGN);
- signal (SIGUSR2, SIG_IGN);
- signal (SIGPIPE, SIG_IGN);
+ signal (SIGINT, SIG_IGN);
+ signal (SIGHUP, SIG_IGN);
+ signal (SIGUSR1, SIG_IGN);
+ signal (SIGUSR2, SIG_IGN);
+ signal (SIGPIPE, SIG_IGN);
}
-/*
- * convert system() return into a success/failure value
- */
-int
-system_ok (int stat)
+
+static void
+free_context (struct down_root_context *context)
{
-#ifdef WIN32
- return stat == 0;
-#else
- return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0;
-#endif
+ if (context)
+ {
+ if (context->command)
+ {
+ free (context->command);
+ }
+ free (context);
+ }
}
-static char *
-build_command_line (const char *argv[])
+/* Run the script using execve(). As execve() replaces the
+ * current process with the new one, do a fork first before
+ * calling execve()
+ */
+static int
+run_script(char * const *argv, char * const *envp)
{
- int size = 0;
- int n = 0;
- int i;
- char *string;
+ pid_t pid;
+ int ret = 0;
- /* precompute size */
- if (argv)
+ pid = fork();
+ if (pid == (pid_t)0) /* child side */
{
- for (i = 0; argv[i]; ++i)
- {
- size += (strlen (argv[i]) + 1); /* string length plus trailing space */
- ++n;
- }
+ execve(argv[0], argv, envp);
+ /* If execve() fails to run, exit child with exit code 127 */
+ err(127, "DOWN-ROOT: Failed execute: %s", argv[0]);
}
- ++size; /* for null terminator */
-
- /* allocate memory */
- string = (char *) malloc (size);
- if (!string)
+ else if (pid < (pid_t)0 )
{
- fprintf (stderr, "DOWN-ROOT: out of memory\n");
- exit (1);
+ warn ("DOWN-ROOT: Failed to fork child to run %s", argv[0]);
+ return -1;
}
- string[0] = '\0';
-
- /* build string */
- for (i = 0; i < n; ++i)
+ else /* parent side */
{
- strcat (string, argv[i]);
- if (i + 1 < n)
- strcat (string, " ");
+ if( waitpid (pid, &ret, 0) != pid )
+ {
+ /* waitpid does not return error information via errno */
+ fprintf(stderr, "DOWN-ROOT: waitpid() failed, don't know exit code of child (%s)\n", argv[0]);
+ return -1;
+ }
}
- return string;
+ return ret;
}
-static void
-free_context (struct down_root_context *context)
+OPENVPN_EXPORT openvpn_plugin_handle_t
+openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
{
- if (context)
+ struct down_root_context *context;
+ int i = 0;
+
+ /*
+ * Allocate our context
+ */
+ context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context));
+ if (!context)
{
- if (context->command)
- free (context->command);
- free (context);
+ warn ("DOWN-ROOT: Could not allocate memory for plug-in context");
+ goto error;
+ }
+ context->foreground_fd = -1;
+
+ /*
+ * Intercept the --up and --down callbacks
+ */
+ *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN);
+
+ /*
+ * Make sure we have two string arguments: the first is the .so name,
+ * the second is the script command.
+ */
+ if (string_array_len (argv) < 2)
+ {
+ fprintf (stderr, "DOWN-ROOT: need down script command\n");
+ goto error;
}
-}
-OPENVPN_EXPORT openvpn_plugin_handle_t
-openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
-{
- struct down_root_context *context;
-
- /*
- * Allocate our context
- */
- context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context));
- if (!context)
- goto error;
- context->foreground_fd = -1;
-
- /*
- * Intercept the --up and --down callbacks
- */
- *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN);
-
- /*
- * Make sure we have two string arguments: the first is the .so name,
- * the second is the script command.
- */
- if (string_array_len (argv) < 2)
+ /*
+ * Save the arguments in our context
+ */
+ context->command = calloc(string_array_len(argv), sizeof(char *));
+ if (!context->command)
+ {
+ warn ("DOWN-ROOT: Could not allocate memory for command array");
+ goto error;
+ }
+
+ /* Ignore argv[0], as it contains just the plug-in file name */
+ for (i = 1; i < string_array_len(argv); i++)
+ {
+ context->command[i-1] = (char *) argv[i];
+ }
+
+ /*
+ * Get verbosity level from environment
+ */
{
- fprintf (stderr, "DOWN-ROOT: need down script command\n");
- goto error;
+ const char *verb_string = get_env ("verb", envp);
+ if (verb_string)
+ context->verb = atoi (verb_string);
}
- /*
- * Save our argument in context
- */
- context->command = build_command_line (&argv[1]);
-
- /*
- * Get verbosity level from environment
- */
- {
- const char *verb_string = get_env ("verb", envp);
- if (verb_string)
- context->verb = atoi (verb_string);
- }
-
- return (openvpn_plugin_handle_t) context;
-
- error:
- free_context (context);
- return NULL;
+ return (openvpn_plugin_handle_t) context;
+
+error:
+ free_context (context);
+ return NULL;
}
OPENVPN_EXPORT int
openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
{
- struct down_root_context *context = (struct down_root_context *) handle;
+ struct down_root_context *context = (struct down_root_context *) handle;
- if (type == OPENVPN_PLUGIN_UP && context->foreground_fd == -1) /* fork off a process to hold onto root */
+ if (type == OPENVPN_PLUGIN_UP && context->foreground_fd == -1) /* fork off a process to hold onto root */
{
- pid_t pid;
- int fd[2];
-
- /*
- * Make a socket for foreground and background processes
- * to communicate.
- */
- if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
- {
- fprintf (stderr, "DOWN-ROOT: socketpair call failed\n");
- return OPENVPN_PLUGIN_FUNC_ERROR;
- }
-
- /*
- * Fork off the privileged process. It will remain privileged
- * even after the foreground process drops its privileges.
- */
- pid = fork ();
-
- if (pid)
- {
- int status;
-
- /*
- * Foreground Process
- */
-
- context->background_pid = pid;
-
- /* close our copy of child's socket */
- close (fd[1]);
-
- /* don't let future subprocesses inherit child socket */
- if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0)
- fprintf (stderr, "DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed\n");
-
- /* wait for background child process to initialize */
- status = recv_control (fd[0]);
- if (status == RESPONSE_INIT_SUCCEEDED)
- {
- context->foreground_fd = fd[0];
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- }
- }
- else
- {
- /*
- * Background Process
- */
-
- /* close all parent fds except our socket back to parent */
- close_fds_except (fd[1]);
-
- /* Ignore most signals (the parent will receive them) */
- set_signals ();
-
- /* Daemonize if --daemon option is set. */
- daemonize (envp);
-
- /* execute the event loop */
- down_root_server (fd[1], context->command, argv, envp, context->verb);
-
- close (fd[1]);
- exit (0);
- return 0; /* NOTREACHED */
- }
+ pid_t pid;
+ int fd[2];
+
+ /*
+ * Make a socket for foreground and background processes
+ * to communicate.
+ */
+ if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
+ {
+ warn ("DOWN-ROOT: socketpair call failed");
+ return OPENVPN_PLUGIN_FUNC_ERROR;
+ }
+
+ /*
+ * Fork off the privileged process. It will remain privileged
+ * even after the foreground process drops its privileges.
+ */
+ pid = fork ();
+
+ if (pid)
+ {
+ int status;
+
+ /*
+ * Foreground Process
+ */
+
+ context->background_pid = pid;
+
+ /* close our copy of child's socket */
+ close (fd[1]);
+
+ /* don't let future subprocesses inherit child socket */
+ if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0)
+ {
+ warn ("DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed");
+ }
+
+ /* wait for background child process to initialize */
+ status = recv_control (fd[0]);
+ if (status == RESPONSE_INIT_SUCCEEDED)
+ {
+ context->foreground_fd = fd[0];
+ return OPENVPN_PLUGIN_FUNC_SUCCESS;
+ }
+ }
+ else
+ {
+ /*
+ * Background Process
+ */
+
+ /* close all parent fds except our socket back to parent */
+ close_fds_except (fd[1]);
+
+ /* Ignore most signals (the parent will receive them) */
+ set_signals ();
+
+ /* Daemonize if --daemon option is set. */
+ daemonize (envp);
+
+ /* execute the event loop */
+ down_root_server (fd[1], context->command, (char * const *) envp, context->verb);
+
+ close (fd[1]);
+ exit (0);
+ return 0; /* NOTREACHED */
+ }
}
- else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0)
+ else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0)
{
- if (send_control (context->foreground_fd, COMMAND_RUN_SCRIPT) == -1)
- {
- fprintf (stderr, "DOWN-ROOT: Error sending script execution signal to background process\n");
- }
- else
- {
- const int status = recv_control (context->foreground_fd);
- if (status == RESPONSE_SCRIPT_SUCCEEDED)
- return OPENVPN_PLUGIN_FUNC_SUCCESS;
- if (status == -1)
- fprintf (stderr, "DOWN-ROOT: Error receiving script execution confirmation from background process\n");
- }
+ if (send_control (context->foreground_fd, COMMAND_RUN_SCRIPT) == -1)
+ {
+ warn ("DOWN-ROOT: Error sending script execution signal to background process");
+ }
+ else
+ {
+ const int status = recv_control (context->foreground_fd);
+ if (status == RESPONSE_SCRIPT_SUCCEEDED)
+ return OPENVPN_PLUGIN_FUNC_SUCCESS;
+ if (status == -1)
+ {
+ warn ("DOWN-ROOT: Error receiving script execution confirmation from background process");
+ }
+ }
}
- return OPENVPN_PLUGIN_FUNC_ERROR;
+ return OPENVPN_PLUGIN_FUNC_ERROR;
}
OPENVPN_EXPORT void
openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
{
- struct down_root_context *context = (struct down_root_context *) handle;
+ struct down_root_context *context = (struct down_root_context *) handle;
- if (DEBUG (context->verb))
- fprintf (stderr, "DOWN-ROOT: close\n");
+ if (DEBUG (context->verb))
+ fprintf (stderr, "DOWN-ROOT: close\n");
- if (context->foreground_fd >= 0)
+ if (context->foreground_fd >= 0)
{
- /* tell background process to exit */
- if (send_control (context->foreground_fd, COMMAND_EXIT) == -1)
- fprintf (stderr, "DOWN-ROOT: Error signaling background process to exit\n");
-
- /* wait for background process to exit */
- if (context->background_pid > 0)
- waitpid (context->background_pid, NULL, 0);
-
- close (context->foreground_fd);
- context->foreground_fd = -1;
+ /* tell background process to exit */
+ if (send_control (context->foreground_fd, COMMAND_EXIT) == -1)
+ {
+ warn ("DOWN-ROOT: Error signalling background process to exit");
+ }
+
+ /* wait for background process to exit */
+ if (context->background_pid > 0)
+ waitpid (context->background_pid, NULL, 0);
+
+ close (context->foreground_fd);
+ context->foreground_fd = -1;
}
- free_context (context);
+ free_context (context);
}
OPENVPN_EXPORT void
openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle)
{
- struct down_root_context *context = (struct down_root_context *) handle;
+ struct down_root_context *context = (struct down_root_context *) handle;
- if (context && context->foreground_fd >= 0)
+ if (context && context->foreground_fd >= 0)
{
- /* tell background process to exit */
- send_control (context->foreground_fd, COMMAND_EXIT);
- close (context->foreground_fd);
- context->foreground_fd = -1;
+ /* tell background process to exit */
+ send_control (context->foreground_fd, COMMAND_EXIT);
+ close (context->foreground_fd);
+ context->foreground_fd = -1;
}
}
@@ -453,105 +463,85 @@ openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle)
* Background process -- runs with privilege.
*/
static void
-down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb)
+down_root_server (const int fd, char * const *argv, char * const *envp, const int verb)
{
- const char *p[3];
- char *command_line = NULL;
- char *argv_cat = NULL;
- int i;
-
- /*
- * Do initialization
- */
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", command);
-
- /*
- * Tell foreground that we initialized successfully
- */
- if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1)
+ /*
+ * Do initialization
+ */
+ if (DEBUG (verb))
+ fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", argv[0]);
+
+ /*
+ * Tell foreground that we initialized successfully
+ */
+ if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1)
{
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [1]\n");
- goto done;
+ warn ("DOWN-ROOT: BACKGROUND: write error on response socket [1]");
+ goto done;
}
- /*
- * Build command line
- */
- if (string_array_len (argv) >= 2)
- argv_cat = build_command_line (&argv[1]);
- else
- argv_cat = build_command_line (NULL);
- p[0] = command;
- p[1] = argv_cat;
- p[2] = NULL;
- command_line = build_command_line (p);
-
- /*
- * Save envp in environment
- */
- for (i = 0; envp[i]; ++i)
+ /*
+ * Event loop
+ */
+ while (1)
{
- putenv ((char *)envp[i]);
+ int command_code;
+ int exit_code = -1;
+
+ /* get a command from foreground process */
+ command_code = recv_control (fd);
+
+ if (DEBUG (verb))
+ fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code);
+
+ switch (command_code)
+ {
+ case COMMAND_RUN_SCRIPT:
+ if ( (exit_code = run_script(argv, envp)) == 0 ) /* Succeeded */
+ {
+ if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1)
+ {
+ warn ("DOWN-ROOT: BACKGROUND: write error on response socket [2]");
+ goto done;
+ }
+ }
+ else /* Failed */
+ {
+ fprintf(stderr, "DOWN-ROOT: BACKGROUND: %s exited with exit code %i\n", argv[0], exit_code);
+ if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1)
+ {
+ warn ("DOWN-ROOT: BACKGROUND: write error on response socket [3]");
+ goto done;
+ }
+ }
+ break;
+
+ case COMMAND_EXIT:
+ goto done;
+
+ case -1:
+ warn ("DOWN-ROOT: BACKGROUND: read error on command channel");
+ goto done;
+
+ default:
+ fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n",
+ command_code);
+ goto done;
+ }
}
- /*
- * Event loop
- */
- while (1)
- {
- int command_code;
- int status;
-
- /* get a command from foreground process */
- command_code = recv_control (fd);
-
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code);
-
- switch (command_code)
- {
- case COMMAND_RUN_SCRIPT:
- status = system (command_line);
- if (system_ok (status)) /* Succeeded */
- {
- if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1)
- {
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [2]\n");
- goto done;
- }
- }
- else /* Failed */
- {
- if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1)
- {
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [3]\n");
- goto done;
- }
- }
- break;
-
- case COMMAND_EXIT:
- goto done;
-
- case -1:
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: read error on command channel\n");
- goto done;
-
- default:
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n",
- command_code);
- goto done;
- }
- }
+done:
+ if (DEBUG (verb))
+ fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n");
- done:
- if (argv_cat)
- free (argv_cat);
- if (command_line)
- free (command_line);
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n");
-
- return;
+ return;
}
+
+
+/*
+Local variables:
+c-file-style: "bsd"
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/app/openvpn/tests/t_lpback.sh b/app/openvpn/tests/t_lpback.sh
index 8f88ad92..d7792cd3 100755
--- a/app/openvpn/tests/t_lpback.sh
+++ b/app/openvpn/tests/t_lpback.sh
@@ -35,6 +35,9 @@ CIPHERS=$(${top_builddir}/src/openvpn/openvpn --show-ciphers | \
# GD, 2014-07-06 do not test RC5-* either (fails on NetBSD w/o libcrypto_rc5)
CIPHERS=$(echo "$CIPHERS" | egrep -v '^(DES-EDE3-CFB1|DES-CFB1|RC5-)' )
+# Also test cipher 'none'
+CIPHERS=${CIPHERS}$(printf "\nnone")
+
"${top_builddir}/src/openvpn/openvpn" --genkey --secret key.$$
set +e