summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-05-01 15:33:00 +0200
committerArne Schwabe <arne@rfc2549.org>2012-05-01 15:33:00 +0200
commit3d54881bc78b893ab286681338dd7b9b69d871b3 (patch)
treea6e8e13bc598a4762c96312800451ddf0a8306e6
parent61deb1b6598f2816125525c8621b08e047172768 (diff)
Support strange certificate + passsword authentication types
-rw-r--r--AndroidManifest.xml4
-rw-r--r--openvpn/Makefile.am1
-rw-r--r--openvpn/README.polarssl4
-rw-r--r--openvpn/config.h6
-rw-r--r--openvpn/configure.ac38
-rw-r--r--openvpn/doc/openvpn.814
-rw-r--r--openvpn/include/openvpn-plugin.h8
-rw-r--r--openvpn/src/compat/Makefile.am1
-rw-r--r--openvpn/src/openvpn/basic.h13
-rw-r--r--openvpn/src/openvpn/crypto_polarssl.c67
-rw-r--r--openvpn/src/openvpn/crypto_polarssl.h21
-rw-r--r--openvpn/src/openvpn/init.c8
-rw-r--r--openvpn/src/openvpn/jniglue.c7
-rw-r--r--openvpn/src/openvpn/manage.c11
-rw-r--r--openvpn/src/openvpn/options.c31
-rw-r--r--openvpn/src/openvpn/options.h3
-rw-r--r--openvpn/src/openvpn/packet_id.c16
-rw-r--r--openvpn/src/openvpn/ssl.c5
-rw-r--r--openvpn/src/openvpn/ssl_backend.h10
-rw-r--r--openvpn/src/openvpn/ssl_polarssl.c38
-rw-r--r--openvpn/src/openvpn/ssl_polarssl.h2
-rw-r--r--openvpn/src/openvpn/syshead.h6
-rw-r--r--openvpn/src/openvpn/tun.c24
-rwxr-xr-xopenvpn/src/openvpnserv/openvpnserv.c6
-rw-r--r--res/values/arrays.xml5
-rw-r--r--res/values/strings.xml1
-rw-r--r--src/de/blinkt/openvpn/LaunchVPN.java8
-rw-r--r--src/de/blinkt/openvpn/Settings_Basic.java8
-rw-r--r--src/de/blinkt/openvpn/Settings_Obscure.java2
-rw-r--r--src/de/blinkt/openvpn/VpnProfile.java85
-rw-r--r--todo.txt1
31 files changed, 312 insertions, 142 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5b4bdef8..fe250a8e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -17,8 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.blinkt.openvpn"
- android:versionCode="14"
- android:versionName="0.4.6" >
+ android:versionCode="15"
+ android:versionName="0.4.7" >
<uses-permission android:name="android.permission.INTERNET" />
diff --git a/openvpn/Makefile.am b/openvpn/Makefile.am
index 68aa0a87..ab3e3d2e 100644
--- a/openvpn/Makefile.am
+++ b/openvpn/Makefile.am
@@ -52,6 +52,7 @@ dist_doc_DATA = \
dist_noinst_DATA = \
.gitignore \
+ .gitattributes \
PORTS \
README.IPv6 TODO.IPv6 \
README.polarssl \
diff --git a/openvpn/README.polarssl b/openvpn/README.polarssl
index 77a95750..ab7c2d78 100644
--- a/openvpn/README.polarssl
+++ b/openvpn/README.polarssl
@@ -3,11 +3,11 @@ instructions:
To Build and Install,
- ./configure --with-ssl-type=polarssl
+ ./configure --with-crypto-library=polarssl
make
make install
-This version depends on at least PolarSSL v0.99.
+This version depends on at least PolarSSL v1.1.
*************************************************************************
diff --git a/openvpn/config.h b/openvpn/config.h
index 3e713081..3dfeffc2 100644
--- a/openvpn/config.h
+++ b/openvpn/config.h
@@ -450,13 +450,13 @@
#define PACKAGE_NAME "OpenVPN"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "OpenVPN 2.1.4"
+#define PACKAGE_STRING "OpenVPN 2.3_alpha1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "openvpn"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.1.4"
+#define PACKAGE_VERSION "2.3_alpha1"
/* Define to the necessary symbol if this constant uses a non-standard name on
your system. */
@@ -490,7 +490,7 @@
#define TAP_WIN32_MIN_MINOR 1
/* A string representing our target */
-#define TARGET_ALIAS "i686-pc-linux-gnu"
+#define TARGET_ALIAS "arm-linux-androideabi"
/* Are we running on Mac OS X? */
/* #undef TARGET_DARWIN */
diff --git a/openvpn/configure.ac b/openvpn/configure.ac
index e962323f..399b4e78 100644
--- a/openvpn/configure.ac
+++ b/openvpn/configure.ac
@@ -168,6 +168,7 @@ AC_ARG_ENABLE(
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@:>@])],
+ ,
[enable_password_save="no"]
)
@@ -354,7 +355,7 @@ AX_EMPTY_ARRAY
AC_CHECK_SIZEOF([unsigned int])
AC_CHECK_SIZEOF([unsigned long])
AC_CHECK_HEADERS([ \
- stdio.h stdarg.h limits.h \
+ stdio.h stdarg.h stdbool.h limits.h \
time.h errno.h fcntl.h io.h direct.h \
ctype.h sys/types.h sys/socket.h \
signal.h unistd.h dlfcn.h \
@@ -363,7 +364,7 @@ AC_CHECK_HEADERS([ \
windows.h winsock2.h ws2tcpip.h \
])
AC_CHECK_HEADERS([ \
- sys/time.h sys/un.h sys/ioctl.h sys/stat.h \
+ sys/time.h sys/ioctl.h sys/stat.h \
sys/mman.h sys/file.h \
unistd.h signal.h libgen.h stropts.h \
syslog.h pwd.h grp.h \
@@ -396,10 +397,13 @@ SOCKET_INCLUDES="
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
"
AC_CHECK_HEADERS(
- [net/if.h netinet/ip.h netinet/if_ether.h resolv.h],
+ [net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h],
,
,
[[${SOCKET_INCLUDES}]]
@@ -412,38 +416,32 @@ AC_CHECK_TYPES(
[[${SOCKET_INCLUDES}]]
)
AC_CHECK_TYPE(
- [struct tun_pi],
- [AC_DEFINE(HAVE_TUN_PI, 1, [struct tun_pi needed for IPv6 support])],
- ,
- [[${SOCKET_INCLUDES}]]
-)
-AC_CHECK_TYPE(
[struct iphdr],
- [AC_DEFINE(HAVE_IPHDR, 1, [struct iphdr needed for IPv6 support])],
+ [AC_DEFINE([HAVE_IPHDR], [1], [struct iphdr needed for IPv6 support])],
,
[[${SOCKET_INCLUDES}]]
)
AC_CHECK_TYPE(
[struct sock_extended_err],
- [AC_DEFINE(HAVE_SOCK_EXTENDED_ERR, 1, [struct sock_extended_err needed for extended socket error support])],
+ [AC_DEFINE([HAVE_SOCK_EXTENDED_ERR], [1], [struct sock_extended_err needed for extended socket error support])],
,
[[${SOCKET_INCLUDES}]]
)
AC_CHECK_TYPE(
[struct msghdr],
- [AC_DEFINE(HAVE_MSGHDR, 1, [struct msghdr needed for extended socket error support])],
+ [AC_DEFINE([HAVE_MSGHDR], [1], [struct msghdr needed for extended socket error support])],
,
[[${SOCKET_INCLUDES}]]
)
AC_CHECK_TYPE(
[struct cmsghdr],
- [AC_DEFINE(HAVE_CMSGHDR, 1, [struct cmsghdr needed for extended socket error support])],
+ [AC_DEFINE([HAVE_CMSGHDR], [1], [struct cmsghdr needed for extended socket error support])],
,
[[${SOCKET_INCLUDES}]]
)
AC_CHECK_TYPE(
[struct in_pktinfo],
- [AC_DEFINE(HAVE_IN_PKTINFO, 1, [struct in_pktinfo needed for IP_PKTINFO support])],
+ [AC_DEFINE([HAVE_IN_PKTINFO], [1], [struct in_pktinfo needed for IP_PKTINFO support])],
,
[[${SOCKET_INCLUDES}]]
)
@@ -595,6 +593,16 @@ AC_CHECK_HEADERS(
],
[have_tap_header="yes"]
)
+AC_CHECK_DECLS(
+ [TUNSETPERSIST],
+ [AC_DEFINE([ENABLE_FEATURE_TUN_PERSIST], [1], [We have persist tun capability])],
+ ,
+ [[
+ #ifdef HAVE_LINUX_IF_TUN_H
+ #include <linux/if_tun.h>
+ #endif
+ ]]
+)
CFLAGS="${old_CFLAGS}"
test "${have_tap_header}" = "yes" || AC_MSG_ERROR([no tap header could be found])
@@ -821,7 +829,7 @@ case "${with_crypto_library}" in
polarssl)
have_crypto_crypto="${have_polarssl_crypto}"
have_crypto_ssl="${have_polarssl_ssl}"
- CRYPTO_CRYPTO_CFLAGS="${POLARSSL_CRYPTO_CFLAGS}"
+ CRYPTO_CRYPTO_CFLAGS="${POLARSSL_CFLAGS}"
CRYPTO_CRYPTO_LIBS="${POLARSSL_LIBS}"
AC_DEFINE([ENABLE_CRYPTO_POLARSSL], [1], [Use PolarSSL library])
;;
diff --git a/openvpn/doc/openvpn.8 b/openvpn/doc/openvpn.8
index 53d6bdb2..ee46de62 100644
--- a/openvpn/doc/openvpn.8
+++ b/openvpn/doc/openvpn.8
@@ -3846,6 +3846,20 @@ space-saving optimization that uses the unique identifier for
datagram replay protection as the IV.
.\"*********************************************************
.TP
+.B \-\-use-prediction-resistance
+Enable prediction resistance on PolarSSL's RNG.
+
+Enabling prediction resistance causes the RNG to reseed in each
+call for random. Reseeding this often can quickly deplete the kernel
+entropy pool.
+
+If you need this option, please consider running a daemon that adds
+entropy to the kernel pool.
+
+Note that this option only works with PolarSSL versions greater
+than 1.1.
+.\"*********************************************************
+.TP
.B \-\-test-crypto
Do a self-test of OpenVPN's crypto options by encrypting and
decrypting test packets using the data channel encryption options
diff --git a/openvpn/include/openvpn-plugin.h b/openvpn/include/openvpn-plugin.h
index f82f61fa..1c80eec3 100644
--- a/openvpn/include/openvpn-plugin.h
+++ b/openvpn/include/openvpn-plugin.h
@@ -43,6 +43,10 @@ typedef X509 openvpn_x509_cert_t;
#endif
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Plug-in types. These types correspond to the set of script callbacks
* supported by OpenVPN.
@@ -724,4 +728,8 @@ OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t OPENVPN_PLUGIN_FUNC(openvpn_plugin_op
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v1)
(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[]);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* OPENVPN_PLUGIN_H_ */
diff --git a/openvpn/src/compat/Makefile.am b/openvpn/src/compat/Makefile.am
index 5ee35f72..7ad44525 100644
--- a/openvpn/src/compat/Makefile.am
+++ b/openvpn/src/compat/Makefile.am
@@ -20,6 +20,7 @@ noinst_LTLIBRARIES = libcompat.la
libcompat_la_SOURCES = \
compat.h \
+ compat-stdbool.h \
compat-dirname.c \
compat-basename.c \
compat-gettimeofday.c \
diff --git a/openvpn/src/openvpn/basic.h b/openvpn/src/openvpn/basic.h
index 7c13e221..298cf103 100644
--- a/openvpn/src/openvpn/basic.h
+++ b/openvpn/src/openvpn/basic.h
@@ -25,19 +25,6 @@
#ifndef BASIC_H
#define BASIC_H
-/* bool definitions */
-#ifndef bool
-#define bool int
-#endif
-
-#ifndef true
-#define true 1
-#endif
-
-#ifndef false
-#define false 0
-#endif
-
#define BOOL_CAST(x) ((x) ? (true) : (false))
/* size of an array */
diff --git a/openvpn/src/openvpn/crypto_polarssl.c b/openvpn/src/openvpn/crypto_polarssl.c
index 0e6728c8..3978a3c6 100644
--- a/openvpn/src/openvpn/crypto_polarssl.c
+++ b/openvpn/src/openvpn/crypto_polarssl.c
@@ -42,12 +42,16 @@
#include "buffer.h"
#include "integer.h"
#include "crypto_backend.h"
+#include "otime.h"
+#include "misc.h"
#include <polarssl/des.h>
#include <polarssl/md5.h>
#include <polarssl/cipher.h>
#include <polarssl/havege.h>
+#include <polarssl/entropy.h>
+
/*
*
* Hardware engine support. Allows loading/unloading of engines.
@@ -149,7 +153,6 @@ show_available_engines ()
"available\n");
}
-
/*
*
* Random number functions, used in cases where we want
@@ -159,29 +162,65 @@ show_available_engines ()
*
*/
-int
-rand_bytes (uint8_t *output, int len)
+/*
+ * Initialise the given ctr_drbg context, using a personalisation string and an
+ * entropy gathering function.
+ */
+ctr_drbg_context * rand_ctx_get()
{
- static havege_state hs = {0};
- static bool hs_initialised = false;
- const int int_size = sizeof(int);
+ static entropy_context ec = {0};
+ static ctr_drbg_context cd_ctx = {0};
+ static bool rand_initialised = false;
- if (!hs_initialised)
+ if (!rand_initialised)
{
- /* Initialise PolarSSL RNG */
- havege_init(&hs);
- hs_initialised = true;
- }
+ struct gc_arena gc = gc_new();
+ struct buffer pers_string = alloc_buf_gc(100, &gc);
+
+ /*
+ * Personalisation string, should be as unique as possible (see NIST
+ * 800-90 section 8.7.1). We have very little information at this stage.
+ * Include Program Name, memory address of the context and PID.
+ */
+ buf_printf(&pers_string, "OpenVPN %0u %p %s", platform_getpid(), &cd_ctx, time_string(0, 0, 0, &gc));
+
+ /* Initialise PolarSSL RNG, and built-in entropy sources */
+ entropy_init(&ec);
+
+ if (0 != ctr_drbg_init(&cd_ctx, entropy_func, &ec, BPTR(&pers_string), BLEN(&pers_string)))
+ msg (M_FATAL, "Failed to initialize random generator");
+
+ gc_free(&gc);
+ rand_initialised = true;
+ }
+
+ return &cd_ctx;
+}
+
+#ifdef ENABLE_PREDICTION_RESISTANCE
+void rand_ctx_enable_prediction_resistance()
+{
+ ctr_drbg_context *cd_ctx = rand_ctx_get();
+
+ ctr_drbg_set_prediction_resistance(cd_ctx, 1);
+}
+#endif /* ENABLE_PREDICTION_RESISTANCE */
+
+int
+rand_bytes (uint8_t *output, int len)
+{
+ ctr_drbg_context *rng_ctx = rand_ctx_get();
while (len > 0)
{
- const int blen = min_int (len, int_size);
- const int rand_int = havege_rand(&hs);
+ const size_t blen = min_int (len, CTR_DRBG_MAX_REQUEST);
+ if (0 != ctr_drbg_random(rng_ctx, output, blen))
+ return 0;
- memcpy (output, &rand_int, blen);
output += blen;
len -= blen;
}
+
return 1;
}
diff --git a/openvpn/src/openvpn/crypto_polarssl.h b/openvpn/src/openvpn/crypto_polarssl.h
index 358483a9..bfabb91b 100644
--- a/openvpn/src/openvpn/crypto_polarssl.h
+++ b/openvpn/src/openvpn/crypto_polarssl.h
@@ -30,8 +30,10 @@
#ifndef CRYPTO_POLARSSL_H_
#define CRYPTO_POLARSSL_H_
+#include <polarssl/version.h>
#include <polarssl/cipher.h>
#include <polarssl/md.h>
+#include <polarssl/ctr_drbg.h>
/** Generic cipher key type %context. */
typedef cipher_info_t cipher_kt_t;
@@ -71,4 +73,23 @@ typedef md_context_t hmac_ctx_t;
#define SHA_DIGEST_LENGTH 20
#define DES_KEY_LENGTH 8
+/**
+ * Returns a singleton instance of the PolarSSL random number generator.
+ *
+ * For PolarSSL 1.1+, this is the CTR_DRBG random number generator. If it
+ * hasn't been initialised yet, the RNG will be initialised using the default
+ * entropy sources. Aside from the default platform entropy sources, an
+ * additional entropy source, the HAVEGE random number generator will also be
+ * added. During initialisation, a personalisation string will be added based
+ * on the time, the PID, and a pointer to the random context.
+ */
+ctr_drbg_context * rand_ctx_get();
+
+#ifdef ENABLE_PREDICTION_RESISTANCE
+/**
+ * Enable prediction resistance on the random number generator.
+ */
+void rand_ctx_enable_prediction_resistance();
+#endif
+
#endif /* CRYPTO_POLARSSL_H_ */
diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c
index 88d621a4..cc94b818 100644
--- a/openvpn/src/openvpn/init.c
+++ b/openvpn/src/openvpn/init.c
@@ -954,7 +954,7 @@ do_genkey (const struct options * options)
bool
do_persist_tuntap (const struct options *options)
{
-#ifdef TUNSETPERSIST
+#ifdef ENABLE_FEATURE_TUN_PERSIST
if (options->persist_config)
{
/* sanity check on options for --mktun or --rmtun */
@@ -2016,6 +2016,12 @@ init_crypto_pre (struct context *c, const unsigned int flags)
if (c->options.mute_replay_warnings)
c->c2.crypto_options.flags |= CO_MUTE_REPLAY_WARNINGS;
+
+#ifdef ENABLE_PREDICTION_RESISTANCE
+ if (c->options.use_prediction_resistance)
+ rand_ctx_enable_prediction_resistance();
+#endif
+
}
/*
diff --git a/openvpn/src/openvpn/jniglue.c b/openvpn/src/openvpn/jniglue.c
index 686092bc..c0fff12b 100644
--- a/openvpn/src/openvpn/jniglue.c
+++ b/openvpn/src/openvpn/jniglue.c
@@ -129,13 +129,6 @@ void android_openvpn_log(int level,const char* prefix,const char* prefix_sep,con
}
-
-unsigned char android_protect_socket(int sockfd) {
- jmethodID aMethodID = (*openvpnjenv)->GetStaticMethodID(openvpnjenv, openvpnclass, "protectSocket",
- "(I)Z");
- return (*openvpnjenv)->CallStaticBooleanMethod(openvpnjenv,openvpnclass,aMethodID,sockfd);
-
-}
int android_open_tun () {
jmethodID aMethodID = (*openvpnjenv)->GetStaticMethodID(openvpnjenv, openvpnclass, "openTunDevice",
"()I");
diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c
index 1a6c0869..1dddd41d 100644
--- a/openvpn/src/openvpn/manage.c
+++ b/openvpn/src/openvpn/manage.c
@@ -1479,14 +1479,13 @@ man_new_connection_post (struct management *man, const char *description)
#if UNIX_SOCK_SUPPORT
if (man->settings.flags & MF_UNIX_SOCK)
{
- msg (D_MANAGEMENT, "MANAGEMENT(unix): %s %s",
- description,
- sockaddr_unix_name (&man->settings.local_unix, "NULL"));
-
+ msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
+ description,
+ sockaddr_unix_name (&man->settings.local_unix, "NULL"));
}
else
#endif
- msg (D_MANAGEMENT, "MANAGEMENT(tcp): %s %s",
+ msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
description,
print_sockaddr (&man->settings.local, &gc));
@@ -2691,7 +2690,6 @@ management_socket_set (struct management *man,
void
management_io (struct management *man)
{
- msg(D_MANAGEMENT,"M I/O State %d in",man->connection.state);
switch (man->connection.state)
{
case MS_LISTEN:
@@ -2708,7 +2706,6 @@ management_io (struct management *man)
default:
ASSERT (0);
}
- msg(D_MANAGEMENT,"M I/O State %d out",man->connection.state);
}
#endif
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index b74e559b..c48d7be9 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -545,6 +545,10 @@ static const char usage_message[] =
" using file.\n"
"--test-crypto : Run a self-test of crypto features enabled.\n"
" For debugging only.\n"
+#ifdef ENABLE_PREDICTION_RESISTANCE
+ "--use-prediction-resistance: Enable prediction resistance on the random\n"
+ " number generator.\n"
+#endif
#ifdef ENABLE_SSL
"\n"
"TLS Key Negotiation Options:\n"
@@ -560,7 +564,6 @@ static const char usage_message[] =
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
" and CRLs).\n"
#else /* OPENSSL_VERSION_NUMBER >= 0x00907000L */
-#error WTF!
").\n"
" WARNING: no support of CRL available with this version.\n"
#endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L */
@@ -726,7 +729,7 @@ static const char usage_message[] =
" for use with the --secret option.\n"
"--secret file : Write key to file.\n"
#endif /* ENABLE_CRYPTO */
-#ifdef TUNSETPERSIST
+#ifdef ENABLE_FEATURE_TUN_PERSIST
"\n"
"Tun/tap config mode (available with linux 2.4+):\n"
"--mktun : Create a persistent tunnel.\n"
@@ -792,7 +795,7 @@ init_options (struct options *o, const bool init_gc)
o->management_echo_buffer_size = 100;
o->management_state_buffer_size = 100;
#endif
-#ifdef TUNSETPERSIST
+#ifdef ENABLE_FEATURE_TUN_PERSIST
o->persist_mode = 1;
#endif
#ifndef WIN32
@@ -838,6 +841,9 @@ init_options (struct options *o, const bool init_gc)
o->replay_time = DEFAULT_TIME_BACKTRACK;
o->use_iv = true;
o->key_direction = KEY_DIRECTION_BIDIRECTIONAL;
+#ifdef ENABLE_PREDICTION_RESISTANCE
+ o->use_prediction_resistance = false;
+#endif
#ifdef ENABLE_SSL
o->key_method = 2;
o->tls_timeout = 2;
@@ -1423,7 +1429,7 @@ show_settings (const struct options *o)
SHOW_INT (mode);
-#ifdef TUNSETPERSIST
+#ifdef ENABLE_FEATURE_TUN_PERSIST
SHOW_BOOL (persist_config);
SHOW_INT (persist_mode);
#endif
@@ -1584,6 +1590,9 @@ show_settings (const struct options *o)
SHOW_STR (packet_id_file);
SHOW_BOOL (use_iv);
SHOW_BOOL (test_crypto);
+#ifdef ENABLE_PREDICTION_RESISTANCE
+ SHOW_BOOL (use_prediction_resistance);
+#endif
#ifdef ENABLE_SSL
SHOW_BOOL (tls_server);
@@ -3021,6 +3030,11 @@ options_string (const struct options *o,
buf_printf (&out, ",no-replay");
if (!o->use_iv)
buf_printf (&out, ",no-iv");
+
+#ifdef ENABLE_PREDICTION_RESISTANCE
+ if (o->use_prediction_resistance)
+ buf_printf (&out, ",use-prediction-resistance");
+#endif
}
#ifdef ENABLE_SSL
@@ -6423,6 +6437,13 @@ add_option (struct options *options,
options->keysize = keysize;
}
#endif
+#ifdef ENABLE_PREDICTION_RESISTANCE
+ else if (streq (p[0], "use-prediction-resistance"))
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->use_prediction_resistance = true;
+ }
+#endif
#ifdef ENABLE_SSL
else if (streq (p[0], "show-tls"))
{
@@ -6795,7 +6816,7 @@ add_option (struct options *options,
options->pkcs11_id_management = true;
}
#endif
-#ifdef TUNSETPERSIST
+#ifdef ENABLE_FEATURE_TUN_PERSIST
else if (streq (p[0], "rmtun"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
diff --git a/openvpn/src/openvpn/options.h b/openvpn/src/openvpn/options.h
index 9e78d00b..1be3dfaf 100644
--- a/openvpn/src/openvpn/options.h
+++ b/openvpn/src/openvpn/options.h
@@ -520,6 +520,9 @@ struct options
const char *packet_id_file;
bool use_iv;
bool test_crypto;
+#ifdef ENABLE_PREDICTION_RESISTANCE
+ bool use_prediction_resistance;
+#endif
#ifdef ENABLE_SSL
/* TLS (control channel) parms */
diff --git a/openvpn/src/openvpn/packet_id.c b/openvpn/src/openvpn/packet_id.c
index 0102129f..baa49664 100644
--- a/openvpn/src/openvpn/packet_id.c
+++ b/openvpn/src/openvpn/packet_id.c
@@ -501,7 +501,7 @@ packet_id_debug_print (int msglevel,
buf_printf (&out, "%s [%d]", message, value);
buf_printf (&out, " [%s-%d] [", p->name, p->unit);
- for (i = 0; i < sl->x_size; ++i)
+ for (i = 0; sl != NULL && i < sl->x_size; ++i)
{
char c;
time_t v;
@@ -538,11 +538,15 @@ packet_id_debug_print (int msglevel,
p->time_backtrack,
p->max_backtrack_stat,
(int)p->initialized);
- buf_printf (&out, " sl=[%d,%d,%d,%d]",
- sl->x_head,
- sl->x_size,
- sl->x_cap,
- sl->x_sizeof);
+ if (sl != NULL)
+ {
+ buf_printf (&out, " sl=[%d,%d,%d,%d]",
+ sl->x_head,
+ sl->x_size,
+ sl->x_cap,
+ sl->x_sizeof);
+ }
+
msg (msglevel, "%s", BSTR(&out));
gc_free (&gc);
diff --git a/openvpn/src/openvpn/ssl.c b/openvpn/src/openvpn/ssl.c
index 537fc12f..9f570b9d 100644
--- a/openvpn/src/openvpn/ssl.c
+++ b/openvpn/src/openvpn/ssl.c
@@ -391,6 +391,11 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
tls_ctx_restrict_ciphers(new_ctx, options->cipher_list);
}
+#ifdef ENABLE_CRYPTO_POLARSSL
+ /* Personalise the random by mixing in the certificate */
+ tls_ctx_personalise_random (new_ctx);
+#endif
+
tls_clear_error ();
return;
diff --git a/openvpn/src/openvpn/ssl_backend.h b/openvpn/src/openvpn/ssl_backend.h
index 5ea6a06b..f3e69dd3 100644
--- a/openvpn/src/openvpn/ssl_backend.h
+++ b/openvpn/src/openvpn/ssl_backend.h
@@ -272,6 +272,16 @@ void tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs
#endif
);
+#ifdef ENABLE_CRYPTO_POLARSSL
+/**
+ * Add a personalisation string to the PolarSSL RNG, based on the certificate
+ * loaded into the given context.
+ *
+ * @param ctx TLS context to use
+ */
+void tls_ctx_personalise_random(struct tls_root_ctx *ctx);
+#endif
+
/* **************************************
*
* Key-state specific functions
diff --git a/openvpn/src/openvpn/ssl_polarssl.c b/openvpn/src/openvpn/ssl_polarssl.c
index d4d85c8e..fc8fa6e9 100644
--- a/openvpn/src/openvpn/ssl_polarssl.c
+++ b/openvpn/src/openvpn/ssl_polarssl.c
@@ -44,6 +44,9 @@
#include "manage.h"
#include "ssl_common.h"
+#include <polarssl/sha2.h>
+#include <polarssl/havege.h>
+
#include "ssl_verify_polarssl.h"
#include <polarssl/pem.h>
@@ -85,9 +88,6 @@ tls_ctx_server_new(struct tls_root_ctx *ctx)
ASSERT(NULL != ctx);
CLEAR(*ctx);
- ALLOC_OBJ_CLEAR(ctx->hs, havege_state);
- havege_init(ctx->hs);
-
ALLOC_OBJ_CLEAR(ctx->dhm_ctx, dhm_context);
ALLOC_OBJ_CLEAR(ctx->priv_key, rsa_context);
@@ -103,12 +103,8 @@ void
tls_ctx_client_new(struct tls_root_ctx *ctx)
{
ASSERT(NULL != ctx);
-
CLEAR(*ctx);
- ALLOC_OBJ_CLEAR(ctx->hs, havege_state);
- havege_init(ctx->hs);
-
ALLOC_OBJ_CLEAR(ctx->dhm_ctx, dhm_context);
ALLOC_OBJ_CLEAR(ctx->priv_key, rsa_context);
@@ -143,8 +139,6 @@ tls_ctx_free(struct tls_root_ctx *ctx)
}
#endif
- free(ctx->hs);
-
if (ctx->allowed_ciphers)
free(ctx->allowed_ciphers);
@@ -504,6 +498,28 @@ static void my_debug( void *ctx, int level, const char *str )
}
}
+/*
+ * Further personalise the RNG using a hash of the public key
+ */
+void tls_ctx_personalise_random(struct tls_root_ctx *ctx)
+{
+ static char old_sha256_hash[32] = {0};
+ char sha256_hash[32] = {0};
+ ctr_drbg_context *cd_ctx = rand_ctx_get();
+
+ if (NULL != ctx->crt_chain)
+ {
+ x509_cert *cert = ctx->crt_chain;
+
+ sha2(cert->tbs.p, cert->tbs.len, sha256_hash, false);
+ if ( 0 != memcmp(old_sha256_hash, sha256_hash, sizeof(sha256_hash)))
+ {
+ ctr_drbg_update(cd_ctx, sha256_hash, 32);
+ memcpy(old_sha256_hash, sha256_hash, sizeof(old_sha256_hash));
+ }
+ }
+}
+
void key_state_ssl_init(struct key_state_ssl *ks_ssl,
const struct tls_root_ctx *ssl_ctx, bool is_server, void *session)
{
@@ -517,7 +533,9 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl,
/* Initialise SSL context */
ssl_set_dbg (ks_ssl->ctx, my_debug, NULL);
ssl_set_endpoint (ks_ssl->ctx, ssl_ctx->endpoint);
- ssl_set_rng (ks_ssl->ctx, havege_rand, ssl_ctx->hs);
+
+ ssl_set_rng (ks_ssl->ctx, ctr_drbg_random, rand_ctx_get());
+
ALLOC_OBJ_CLEAR (ks_ssl->ssn, ssl_session);
ssl_set_session (ks_ssl->ctx, 0, 0, ks_ssl->ssn );
if (ssl_ctx->allowed_ciphers)
diff --git a/openvpn/src/openvpn/ssl_polarssl.h b/openvpn/src/openvpn/ssl_polarssl.h
index e6149b60..2b02a6fd 100644
--- a/openvpn/src/openvpn/ssl_polarssl.h
+++ b/openvpn/src/openvpn/ssl_polarssl.h
@@ -30,7 +30,6 @@
#ifndef SSL_POLARSSL_H_
#define SSL_POLARSSL_H_
-#include <polarssl/havege.h>
#include <polarssl/ssl.h>
#include "config.h"
@@ -63,7 +62,6 @@ struct tls_root_ctx {
int endpoint; /**< Whether or not this is a server or a client */
- havege_state *hs; /**< HAVEGE random number state */
dhm_context *dhm_ctx; /**< Diffie-Helmann-Merkle context */
x509_cert *crt_chain; /**< Local Certificate chain */
x509_cert *ca_chain; /**< CA chain for remote verification */
diff --git a/openvpn/src/openvpn/syshead.h b/openvpn/src/openvpn/syshead.h
index 56a54290..8ce40f7e 100644
--- a/openvpn/src/openvpn/syshead.h
+++ b/openvpn/src/openvpn/syshead.h
@@ -26,6 +26,7 @@
#define SYSHEAD_H
#include "compat.h"
+#include "compat-stdbool.h"
/* branch prediction hints */
#if defined(__GNUC__)
@@ -538,6 +539,11 @@ socket_defined (const socket_descriptor_t sd)
#define MANAGMENT_EXTERNAL_KEY
#endif
+/* Enable PolarSSL RNG prediction resistance support */
+#ifdef ENABLE_CRYPTO_POLARSSL
+#define ENABLE_PREDICTION_RESISTANCE
+#endif /* ENABLE_CRYPTO_POLARSSL */
+
/*
* MANAGEMENT_IN_EXTRA allows the management interface to
* read multi-line inputs from clients.
diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c
index ae372e48..7aa8627d 100644
--- a/openvpn/src/openvpn/tun.c
+++ b/openvpn/src/openvpn/tun.c
@@ -1397,15 +1397,6 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
#error header file linux/sockios.h required
#endif
-
-#if defined(HAVE_TUN_PI) && defined(HAVE_IPHDR) && defined(HAVE_IOVEC) && defined(ETH_P_IPV6) && defined(ETH_P_IP) && defined(HAVE_READV) && defined(HAVE_WRITEV)
-#define LINUX_IPV6 1
-/* #warning IPv6 ON */
-#else
-#define LINUX_IPV6 0
-/* #warning IPv6 OFF */
-#endif
-
#if !PEDANTIC
void
@@ -1413,13 +1404,6 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
{
struct ifreq ifr;
- /* warn if a very old linux version is used & --tun-ipv6 set
- */
-#if LINUX_IPV6 == 0
- if ( tt->ipv6 )
- msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
-#endif
-
/*
* We handle --dev null specially, we do not open /dev/null for this.
*/
@@ -1543,7 +1527,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
#endif /* HAVE_LINUX_IF_TUN_H */
#endif /* TARGET_ANDROID */
-#ifdef TUNSETPERSIST
+#ifdef ENABLE_FEATURE_TUN_PERSIST
/*
* This can be removed in future
@@ -1593,7 +1577,7 @@ tuncfg (const char *dev, const char *dev_type, const char *dev_node, int persist
msg (M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));
}
-#endif /* TUNSETPERSIST */
+#endif /* ENABLE_FEATURE_TUN_PERSIST */
void
close_tun (struct tuntap *tt)
@@ -1649,7 +1633,6 @@ close_tun (struct tuntap *tt)
int
write_tun (struct tuntap* tt, uint8_t *buf, int len)
{
-#if LINUX_IPV6
if (tt->ipv6)
{
struct tun_pi pi;
@@ -1675,14 +1658,12 @@ write_tun (struct tuntap* tt, uint8_t *buf, int len)
return(ret - sizeof(pi));
}
else
-#endif
return write (tt->fd, buf, len);
}
int
read_tun (struct tuntap* tt, uint8_t *buf, int len)
{
-#if LINUX_IPV6
if (tt->ipv6)
{
struct iovec vect[2];
@@ -1698,7 +1679,6 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
return(ret - sizeof(pi));
}
else
-#endif
return read (tt->fd, buf, len);
}
diff --git a/openvpn/src/openvpnserv/openvpnserv.c b/openvpn/src/openvpnserv/openvpnserv.c
index a9a9441e..56f5a025 100755
--- a/openvpn/src/openvpnserv/openvpnserv.c
+++ b/openvpn/src/openvpnserv/openvpnserv.c
@@ -87,9 +87,9 @@ static HANDLE exit_event = NULL;
/*
* Message handling
*/
-#define M_INFO (0) // informational
-#define M_SYSERR (MSG_FLAGS_ERROR|MSG_FLAGS_SYS_CODE) // error + system code
-#define M_ERR (MSG_FLAGS_ERROR) // error
+#define M_INFO (0) /* informational */
+#define M_SYSERR (MSG_FLAGS_ERROR|MSG_FLAGS_SYS_CODE) /* error + system code */
+#define M_ERR (MSG_FLAGS_ERROR) /* error */
/* write error to event log */
#define MSG(flags, ...) \
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 98f244bc..3dd0cbb4 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
-
+ <!-- Keep the order the same as the TYPE_ constants in VPNProfile -->
<string-array name="vpn_types">
<item>Certificates</item>
<item>PKCS12 File</item>
<item>Android Certficate</item>
<item>Username/Password</item>
<item>Static Keys</item>
+ <item>User/PW + Certificates</item>
+ <item>User/PW + PKCS12 </item>
+ <item>User/PW + Android</item>
</string-array>
<string-array name="vpn_entry_types">
<item>certs</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 28863ab9..c8e2b1e1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -117,4 +117,5 @@
<string name="clear_log">clear log</string>
<string name="title_cancel">Cancel Confirmation</string>
<string name="cancel_connection_query">Disconnect the connected VPN/cancel the connection attempt?</string>
+ <string name="remove_vpn">Remove VPN</string>
</resources>
diff --git a/src/de/blinkt/openvpn/LaunchVPN.java b/src/de/blinkt/openvpn/LaunchVPN.java
index 2bd647f9..caeedc09 100644
--- a/src/de/blinkt/openvpn/LaunchVPN.java
+++ b/src/de/blinkt/openvpn/LaunchVPN.java
@@ -203,7 +203,7 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
}
- private void askForPW(String type) {
+ private void askForPW(final String type) {
final EditText entry = new EditText(this);
entry.setSingleLine();
@@ -219,7 +219,11 @@ public class LaunchVPN extends ListActivity implements OnItemClickListener {
@Override
public void onClick(DialogInterface dialog, int which) {
String pw = entry.getText().toString();
- mSelectedProfile.mTransientPW = pw;
+ if(type.equals("Password")) {
+ mSelectedProfile.mTransientPW = pw;
+ } else {
+ mSelectedProfile.mTransientPCKS12PW = pw;
+ }
onActivityResult(START_VPN_PROFILE, Activity.RESULT_OK, null);
}
diff --git a/src/de/blinkt/openvpn/Settings_Basic.java b/src/de/blinkt/openvpn/Settings_Basic.java
index 35e86792..7eb224a8 100644
--- a/src/de/blinkt/openvpn/Settings_Basic.java
+++ b/src/de/blinkt/openvpn/Settings_Basic.java
@@ -173,18 +173,26 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On
mView.findViewById(R.id.statickeys).setVisibility(View.GONE);
mView.findViewById(R.id.keystore).setVisibility(View.GONE);
mView.findViewById(R.id.cacert).setVisibility(View.GONE);
+ mView.findViewById(R.id.userpassword).setVisibility(View.GONE);
+ // Fallthroughs are by desing
switch(type) {
+ case VpnProfile.TYPE_USERPASS_CERTIFICATES:
+ mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);
case VpnProfile.TYPE_CERTIFICATES:
mView.findViewById(R.id.certs).setVisibility(View.VISIBLE);
mView.findViewById(R.id.cacert).setVisibility(View.VISIBLE);
break;
+ case VpnProfile.TYPE_USERPASS_PKCS12:
+ mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);
case VpnProfile.TYPE_PKCS12:
mView.findViewById(R.id.pkcs12).setVisibility(View.VISIBLE);
break;
case VpnProfile.TYPE_STATICKEYS:
mView.findViewById(R.id.statickeys).setVisibility(View.VISIBLE);
break;
+ case VpnProfile.TYPE_USERPASS_KEYSTORE:
+ mView.findViewById(R.id.userpassword).setVisibility(View.VISIBLE);
case VpnProfile.TYPE_KEYSTORE:
mView.findViewById(R.id.keystore).setVisibility(View.VISIBLE);
break;
diff --git a/src/de/blinkt/openvpn/Settings_Obscure.java b/src/de/blinkt/openvpn/Settings_Obscure.java
index 02a433fb..d7bce9ad 100644
--- a/src/de/blinkt/openvpn/Settings_Obscure.java
+++ b/src/de/blinkt/openvpn/Settings_Obscure.java
@@ -67,6 +67,8 @@ public class Settings_Obscure extends PreferenceFragment implements OnPreference
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(preference==mLogverbosity) {
mLogverbosity.setDefaultValue(newValue);
+ // Does not refresh otherwise
+ mLogverbosity.setSummary("%s");
}
return true;
diff --git a/src/de/blinkt/openvpn/VpnProfile.java b/src/de/blinkt/openvpn/VpnProfile.java
index 11f2fffa..04b5927f 100644
--- a/src/de/blinkt/openvpn/VpnProfile.java
+++ b/src/de/blinkt/openvpn/VpnProfile.java
@@ -35,10 +35,20 @@ public class VpnProfile implements Serializable{
static final int TYPE_KEYSTORE=2;
public static final int TYPE_USERPASS = 3;
public static final int TYPE_STATICKEYS = 4;
+ public static final int TYPE_USERPASS_CERTIFICATES = 5;
+ public static final int TYPE_USERPASS_PKCS12 = 6;
+ public static final int TYPE_USERPASS_KEYSTORE = 7;
+
+
+
+
+
private static final String OVPNCONFIGFILE = "android.conf";
protected transient String mTransientPW=null;
+ protected transient String mTransientPCKS12PW=null;
+
private static transient String mTempPKCS12Password;
@@ -141,6 +151,7 @@ public class VpnProfile implements Serializable{
static final String OVPNCONFIGPKCS12 = "android.pkcs12";
+
public VpnProfile(String name) {
mUuid = UUID.randomUUID();
mName = name;
@@ -210,7 +221,11 @@ public class VpnProfile implements Serializable{
+
switch(mAuthenticationType) {
+ case VpnProfile.TYPE_USERPASS_CERTIFICATES:
+ cfg+="auth-user-pass\n";
+ cfg+="management-query-passwords\n";
case VpnProfile.TYPE_CERTIFICATES:
// Ca
cfg+="ca ";
@@ -225,6 +240,8 @@ public class VpnProfile implements Serializable{
cfg+=mClientCertFilename;
cfg+="\n";
break;
+ case VpnProfile.TYPE_USERPASS_PKCS12:
+ cfg+="auth-user-pass\n";
case VpnProfile.TYPE_PKCS12:
cfg+="pkcs12 ";
cfg+=mPKCS12Filename;
@@ -232,6 +249,8 @@ public class VpnProfile implements Serializable{
cfg+="management-query-passwords\n";
break;
+ case VpnProfile.TYPE_USERPASS_KEYSTORE:
+ cfg+="auth-user-pass\n";
case VpnProfile.TYPE_KEYSTORE:
cfg+="pkcs12 ";
cfg+=cacheDir.getAbsolutePath() + "/" + OVPNCONFIGPKCS12;
@@ -239,13 +258,9 @@ public class VpnProfile implements Serializable{
cfg+="management-query-passwords\n";
break;
case VpnProfile.TYPE_USERPASS:
- cfg+="ca " + mCaFilename + "\n";
cfg+="auth-user-pass\n";
cfg+="management-query-passwords\n";
- break;
-
-
-
+ cfg+="ca " + mCaFilename +"\n";
}
if(mUseLzo) {
@@ -298,26 +313,26 @@ public class VpnProfile implements Serializable{
}
if(mExpectTLSCert)
cfg += "remote-cert-tls server\n";
-
-
-
-
+
+
+
+
// Obscure Settings dialog
if(mUseRandomHostname)
cfg += "#my favorite options :)\nremote-random-hostname\n";
-
+
if(mUseFloat)
cfg+= "float\n";
-
+
if(mUseCustomConfig) {
cfg += "# Custom configuration options\n";
cfg += "# You are on your on own here :)\n";
cfg += mCustomConfigOptions;
cfg += "\n";
-
+
}
-
-
+
+
return cfg;
}
@@ -388,7 +403,7 @@ public class VpnProfile implements Serializable{
Intent intent = new Intent(context,OpenVpnService.class);
- if(mAuthenticationType == VpnProfile.TYPE_KEYSTORE) {
+ if(mAuthenticationType == VpnProfile.TYPE_KEYSTORE || mAuthenticationType == VpnProfile.TYPE_USERPASS_KEYSTORE) {
savePKCS12(context);
}
@@ -457,7 +472,7 @@ public class VpnProfile implements Serializable{
}
//! Return an error if somethign is wrong
int checkProfile() {
- if(mAuthenticationType==TYPE_KEYSTORE && mAlias==null)
+ if((mAuthenticationType==TYPE_KEYSTORE || mAuthenticationType==TYPE_USERPASS_KEYSTORE) && mAlias==null)
return R.string.no_keystore_cert_selected;
if(!mUsePull) {
@@ -473,39 +488,55 @@ public class VpnProfile implements Serializable{
}
- //! Openvpn asks for a "Private Key", this can be pkcs12 pw or private key pw
+ //! Openvpn asks for a "Private Key", this should be pkcs12 key
//
public String getPasswordPrivateKey() {
- if(mTransientPW!=null) {
- String pwcopy = mTransientPW;
- mTransientPW=null;
+ if(mTransientPCKS12PW!=null) {
+ String pwcopy = mTransientPCKS12PW;
+ mTransientPCKS12PW=null;
return pwcopy;
}
switch (mAuthenticationType) {
case TYPE_KEYSTORE:
+ case TYPE_USERPASS_KEYSTORE:
return getTemporaryPKCS12Password();
case TYPE_PKCS12:
+ case TYPE_USERPASS_PKCS12:
return mPKCS12Password;
+
case TYPE_USERPASS:
case TYPE_STATICKEYS:
case TYPE_CERTIFICATES:
+ case TYPE_USERPASS_CERTIFICATES:
default:
return null;
}
}
+ private boolean isUserPWAuth() {
+ switch(mAuthenticationType) {
+ case TYPE_USERPASS:
+ case TYPE_USERPASS_CERTIFICATES:
+ case TYPE_USERPASS_KEYSTORE:
+ case TYPE_USERPASS_PKCS12:
+ return true;
+ default:
+ return false;
+
+ }
+ }
public String needUserPWInput() {
- if(mTransientPW!=null)
- return null;
- if(mAuthenticationType == TYPE_PKCS12 &&
+ if((mAuthenticationType == TYPE_PKCS12 || mAuthenticationType == TYPE_USERPASS_PKCS12)&&
(mPKCS12Password.equals("") || mPKCS12Password == null)) {
- return "PKCS12 File Password";
+ if(mTransientPCKS12PW==null)
+ return "PKCS12 File Encryption Key";
}
- if(mAuthenticationType == TYPE_USERPASS &&
- (mPassword.equals("") || mPassword == null)) {
- return "Password";
+ if(isUserPWAuth() && (mPassword.equals("") || mPassword == null)) {
+ if(mTransientPW==null)
+ return "Password";
+
}
return null;
}
diff --git a/todo.txt b/todo.txt
new file mode 100644
index 00000000..a15bf1f5
--- /dev/null
+++ b/todo.txt
@@ -0,0 +1 @@
+- VPN List as ListFragment with Context Menu \ No newline at end of file