[Openvpn-devel] Pushing multiple certificates from server

2016-03-03 Thread ValdikSS
Hello everyone,

I'm trying to leisurely move from an old existing 1024 bit CA to a new 4096 bit 
one without a hassle for a clients.
From a X.509 perspective it shouldn't be a problem, and I already have new CA 
self-signed and cross-signed with old CA, it should work just fine.

While there's no problem authenticating clients from both old and new CA using 
single instance (multiple certificates in --ca are supported, this information 
is
documented), I need to send two certificates from OpenVPN server: server 
certificate, which is signed by new CA, and cross-signed new CA with old CA. 
This way
it should work for clients either with old or new CA in configuration files.

I can't manage server to send more than one certificate to the client. It seems 
that multiple certificates in --cert directive are supported only on client
side. Am I missing something, is there a way to push multiple certificates from 
server? If there isn't a way currently, are there any protocol limitations which
allows only one certificate to be sent?




signature.asc
Description: OpenPGP digital signature


Re: [Openvpn-devel] Handling bitness (32/64) for OpenVPN Windowsinstallers

2016-03-03 Thread ValdikSS
On 02/17/2016 06:16 PM, Samuli Seppänen wrote:
> I don't think there are many (any?) 32-bit Windows operating systems 
> being bundled with new computers. The reason why Microsoft backpedaled 
> on dropping 32-bit support in Windows 10 seemed to be their free upgrade 
> program: they wanted the 32-bit operating systems to be upgradeable too.

There are a lot of tablets on Intel Atom with 32 bit Windows 10.




signature.asc
Description: OpenPGP digital signature


Re: [Openvpn-devel] manpage oddity

2016-03-03 Thread Gert Doering
Hi,

On Thu, Mar 03, 2016 at 05:13:01PM +0100, Jan Just Keijser wrote:
> and a few others. However, the actual name of these env vars is local_N, 
> local_port_N  etc. I've checked the code and that has been the case 
> since v2.1
> 
> Two questions:
> - why are we adding the number? per connection there will be only one 
> local IP and only one local port

If it was there at v2.1 - "you tell us, you're the only one that has been
around back then" :-)

(Most likely it's just using the same function for "stick a number to it
and build an environment string containing an IP address" that is used
for route_1, route_2, ...)

> - should we update the man page to reflect this?

Actually, I'd go for "update the manpage, and keep the number" - Heiko
is working on multi-listen, so we could end up with multiple local
IPs and ports one day, and then it makes sense to have them numbered
local_1, local_2, etc.

gert

-- 
USENET is *not* the non-clickable part of WWW!
   //www.muc.de/~gert/
Gert Doering - Munich, Germany g...@greenie.muc.de
fax: +49-89-35655025g...@net.informatik.tu-muenchen.de


signature.asc
Description: PGP signature


[Openvpn-devel] manpage oddity

2016-03-03 Thread Jan Just Keijser

hi,

the openvpn man page section on environment variables lists


   local  The --local parameter.  Set on program initiation and 
reset on SIGHUP.


   local_port
  The local port number, specified by --port or --lport.  
Set on program initiation and reset on SIGHUP.



and a few others. However, the actual name of these env vars is local_N, 
local_port_N  etc. I've checked the code and that has been the case 
since v2.1


Two questions:
- why are we adding the number? per connection there will be only one 
local IP and only one local port

- should we update the man page to reflect this?

TIA,

JJK



[Openvpn-devel] [PATCH] hardening: add safe FD_SET() wrapper openvpn_fd_set()

2016-03-03 Thread steffan.karger
From: Steffan Karger 

On many platforms (not Windows, for once), FD_SET() can write outside the
given fd_set if an fd >= FD_SETSIZE is given.  To make sure we don't do
that, add an ASSERT() to error out with a clear error message when this
does happen.

This patch was inspired by remarks about FD_SET() from Sebastian Krahmer
of the SuSE Security Team.

Signed-off-by: Steffan Karger 
---
 src/openvpn/event.c  |  8 
 src/openvpn/fdmisc.h | 16 
 src/openvpn/proxy.c  |  2 +-
 src/openvpn/socket.c |  4 ++--
 src/openvpn/socks.c  |  6 +++---
 5 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/src/openvpn/event.c b/src/openvpn/event.c
index 34a3c45..c642691 100644
--- a/src/openvpn/event.c
+++ b/src/openvpn/event.c
@@ -873,18 +873,18 @@ se_ctl (struct event_set *es, event_t event, unsigned int 
rwflags, void *arg)
   if (ses->fast)
{
  if (rwflags & EVENT_READ)
-   FD_SET (event, >readfds);
+   openvpn_fd_set (event, >readfds);
  if (rwflags & EVENT_WRITE)
-   FD_SET (event, >writefds);
+   openvpn_fd_set (event, >writefds);
}
   else
{
  if (rwflags & EVENT_READ)
-   FD_SET (event, >readfds);
+   openvpn_fd_set (event, >readfds);
  else
FD_CLR (event, >readfds);
  if (rwflags & EVENT_WRITE)
-   FD_SET (event, >writefds);
+   openvpn_fd_set (event, >writefds);
  else
FD_CLR (event, >writefds);
}
diff --git a/src/openvpn/fdmisc.h b/src/openvpn/fdmisc.h
index 4b6b6d0..13d6552 100644
--- a/src/openvpn/fdmisc.h
+++ b/src/openvpn/fdmisc.h
@@ -22,10 +22,26 @@
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */

+#ifndef FD_MISC_H
+#define FD_MISC_H
+
 #include "basic.h"
+#include "error.h"
+#include "syshead.h"

 bool set_nonblock_action (int fd);
 bool set_cloexec_action (int fd);

 void set_nonblock (int fd);
 void set_cloexec (int fd);
+
+static inline void openvpn_fd_set(int fd, fd_set *setp)
+{
+#ifndef WIN32 /* The Windows FD_SET() implementation does not overflow */
+  ASSERT (fd >= 0 && fd < FD_SETSIZE);
+#endif
+  FD_SET (fd, setp);
+}
+#undef FD_SET /* prevent direct use of FD_SET() */
+
+#endif /* FD_MISC_H */
diff --git a/src/openvpn/proxy.c b/src/openvpn/proxy.c
index 2568e19..8ff6458 100644
--- a/src/openvpn/proxy.c
+++ b/src/openvpn/proxy.c
@@ -92,7 +92,7 @@ recv_line (socket_descriptor_t sd,
}

   FD_ZERO ();
-  FD_SET (sd, );
+  openvpn_fd_set (sd, );
   tv.tv_sec = timeout_sec;
   tv.tv_usec = 0;

diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 714a847..9bcf4d4 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -1003,7 +1003,7 @@ socket_listen_accept (socket_descriptor_t sd,
   struct timeval tv;

   FD_ZERO ();
-  FD_SET (sd, );
+  openvpn_fd_set (sd, );
   tv.tv_sec = 0;
   tv.tv_usec = 0;

@@ -1153,7 +1153,7 @@ openvpn_connect (socket_descriptor_t sd,
  struct timeval tv;

  FD_ZERO ();
- FD_SET (sd, );
+ openvpn_fd_set (sd, );
  tv.tv_sec = 0;
  tv.tv_usec = 0;

diff --git a/src/openvpn/socks.c b/src/openvpn/socks.c
index cef7a35..a9d04ae 100644
--- a/src/openvpn/socks.c
+++ b/src/openvpn/socks.c
@@ -134,7 +134,7 @@ socks_username_password_auth (struct socks_proxy_info *p,
   char c;

   FD_ZERO ();
-  FD_SET (sd, );
+  openvpn_fd_set (sd, );
   tv.tv_sec = timeout_sec;
   tv.tv_usec = 0;

@@ -213,7 +213,7 @@ socks_handshake (struct socks_proxy_info *p,
   char c;

   FD_ZERO ();
-  FD_SET (sd, );
+  openvpn_fd_set (sd, );
   tv.tv_sec = timeout_sec;
   tv.tv_usec = 0;

@@ -319,7 +319,7 @@ recv_socks_reply (socket_descriptor_t sd,
   char c;

   FD_ZERO ();
-  FD_SET (sd, );
+  openvpn_fd_set (sd, );
   tv.tv_sec = timeout_sec;
   tv.tv_usec = 0;

-- 
2.5.0




[Openvpn-devel] [PATCH 10/10] Bind to local socket before dropping privileges

2016-03-03 Thread James Yonan
Bind the local TCP/UDP socket before UID/GID downgrade,
otherwise we cannot bind to ports < 1024.

Signed-off-by: James Yonan 
---
 src/openvpn/init.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index cb73a3d..9658895 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -3630,16 +3630,16 @@ init_instance (struct context *c, const struct env_set 
*env, const unsigned int
 open_plugins (c, false, OPENVPN_PLUGIN_INIT_POST_DAEMON);
 #endif

+  /* finalize the TCP/UDP socket */
+  if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP)
+do_init_socket_2 (c);
+
   /*
* Actually do UID/GID downgrade, and chroot, if requested.
* May be delayed by --client, --pull, or --up-delay.
*/
   do_uid_gid_chroot (c, c->c2.did_open_tun);

-  /* finalize the TCP/UDP socket */
-  if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP)
-do_init_socket_2 (c);
-
   /* initialize timers */
   if (c->mode == CM_P2P || child)
 do_init_timers (c, false);
-- 
1.9.1




[Openvpn-devel] [PATCH 09/10] Added directive to specify HTTP proxy credentials in config.

2016-03-03 Thread James Yonan
The inline directive http-proxy-user-pass can be used to
specify proxy credentials in config, e.g.:

http-proxy proxy.tld 3128 auto-nct

foo
bar


This usage is already supported by OpenVPN 3.

Signed-off-by: James Yonan 
---
 src/openvpn/misc.c|  8 
 src/openvpn/misc.h|  2 ++
 src/openvpn/options.c | 13 +
 src/openvpn/proxy.c   |  2 ++
 src/openvpn/proxy.h   |  1 +
 5 files changed, 26 insertions(+)

diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index 05ed073..4766a17 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
@@ -1090,6 +1090,14 @@ get_user_pass_cr (struct user_pass *up,
  if (!strlen (up->password))
strcpy (up->password, "ok");
}
+  else if (flags & GET_USER_PASS_INLINE_CREDS)
+   {
+ struct buffer buf;
+ buf_set_read (, (uint8_t*) auth_file, strlen (auth_file) + 1);
+ if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
+   buf_parse (, '\n', up->username, USER_PASS_LEN);
+ buf_parse (, '\n', up->password, USER_PASS_LEN);
+   }
   else if (from_authfile)
 {
   /*
diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h
index 65a6e55..b694096 100644
--- a/src/openvpn/misc.h
+++ b/src/openvpn/misc.h
@@ -256,6 +256,8 @@ struct static_challenge_info {};
 #define GET_USER_PASS_STATIC_CHALLENGE   (1<<8) /* SCRV1 protocol -- 
static challenge */
 #define GET_USER_PASS_STATIC_CHALLENGE_ECHO  (1<<9) /* SCRV1 protocol -- echo 
response */

+#define GET_USER_PASS_INLINE_CREDS (1<<10)  /* indicates that auth_file is 
actually inline creds */
+
 bool get_user_pass_cr (struct user_pass *up,
   const char *auth_file,
   const char *prefix,
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index b53f7ac..8f560a7 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -5121,6 +5121,19 @@ add_option (struct options *options,
  ho->auth_method_string = "none";
}
 }
+  else if (streq (p[0], "http-proxy-user-pass") && p[1])
+{
+  struct http_proxy_options *ho;
+  VERIFY_PERMISSION (OPT_P_GENERAL);
+  ho = init_http_proxy_options_once (>ce.http_proxy_options, 
>gc);
+  if (streq (p[1], INLINE_FILE_TAG) && p[2])
+   {
+ ho->auth_file = p[2];
+ ho->inline_creds = true;
+   }
+  else
+   ho->auth_file = p[1];
+}
   else if (streq (p[0], "http-proxy-retry") && !p[1])
 {
   struct http_proxy_options *ho;
diff --git a/src/openvpn/proxy.c b/src/openvpn/proxy.c
index 2568e19..865a026 100644
--- a/src/openvpn/proxy.c
+++ b/src/openvpn/proxy.c
@@ -241,6 +241,8 @@ get_user_pass_http (struct http_proxy_info *p, const bool 
force)
   unsigned int flags = GET_USER_PASS_MANAGEMENT;
   if (p->queried_creds)
flags |= GET_USER_PASS_PREVIOUS_CREDS_FAILED;
+  if (p->options.inline_creds)
+   flags |= GET_USER_PASS_INLINE_CREDS;
   get_user_pass (_proxy_user_pass,
 p->options.auth_file,
 UP_TYPE_PROXY,
diff --git a/src/openvpn/proxy.h b/src/openvpn/proxy.h
index 4715940..864d3b9 100644
--- a/src/openvpn/proxy.h
+++ b/src/openvpn/proxy.h
@@ -58,6 +58,7 @@ struct http_proxy_options {
   const char *http_version;
   const char *user_agent;
   struct http_custom_header custom_headers[MAX_CUSTOM_HTTP_HEADER];
+  bool inline_creds;
 };

 struct http_proxy_options_simple {
-- 
1.9.1




[Openvpn-devel] [PATCH 08/10] Added ./configure flag to disable user-defined scripts.

2016-03-03 Thread James Yonan
Added ./configure --disable-scripts build flag to ignore the
"script-security" directive in configs.  This can be used to
prevent configs from raising the script-security level to
allow user-defined script execution.

At the C level, script support is enabled by:

  /* Enable user-defined scripting */
  #define ENABLE_SCRIPTS 1

or disabled by ensuring that ENABLE_SCRIPTS is undefined.

If ENABLE_SCRIPTS is undefined, OpenVPN will log "[NOSCRIPTS]"
in the initial version info line.

This patch assumes that script_security defaults to
SSEC_BUILT_IN or less.

Signed-off-by: James Yonan 
---
 configure.ac  | 8 
 src/openvpn/options.c | 7 +++
 2 files changed, 15 insertions(+)

diff --git a/configure.ac b/configure.ac
index b75d51f..c3ff472 100644
--- a/configure.ac
+++ b/configure.ac
@@ -128,6 +128,13 @@ AC_ARG_ENABLE(
 )

 AC_ARG_ENABLE(
+   [scripts],
+   [AS_HELP_STRING([--disable-scripts], [disable user-defined scripting 
support @<:@default=yes@:>@])],
+   ,
+   [enable_scripts="yes"]
+)
+
+AC_ARG_ENABLE(
[pkcs11],
[AS_HELP_STRING([--enable-pkcs11], [enable pkcs11 support 
@<:@default=no@:>@])],
,
@@ -1059,6 +1066,7 @@ test "${ac_cv_header_sys_uio_h}" = "yes" && 
AC_DEFINE([HAVE_IOVEC], [1], [struct
 test "${enable_multi}" = "yes" && AC_DEFINE([ENABLE_CLIENT_SERVER], [1], 
[Enable client/server capability])
 test "${enable_server}" = "no" && AC_DEFINE([ENABLE_CLIENT_ONLY], [1], [Enable 
client capability only])
 test "${enable_management}" = "yes" && AC_DEFINE([ENABLE_MANAGEMENT], [1], 
[Enable management server capability])
+test "${enable_scripts}" = "yes" && AC_DEFINE([ENABLE_SCRIPTS], [1], [Enable 
user-defined scripting])
 test "${enable_multihome}" = "yes" && AC_DEFINE([ENABLE_MULTIHOME], [1], 
[Enable multi-homed UDP server capability])
 test "${enable_debug}" = "yes" && AC_DEFINE([ENABLE_DEBUG], [1], [Enable 
debugging support])
 test "${enable_small}" = "yes" && AC_DEFINE([ENABLE_SMALL], [1], [Enable 
smaller executable size])
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 0942a4d..b53f7ac 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -99,6 +99,9 @@ const char title_string[] =
 #if ENABLE_IP_PKTINFO
   " [MH]"
 #endif
+#ifndef ENABLE_SCRIPTS
+  " [NOSCRIPTS]"
+#endif
   " [IPv6]"
   " built on " __DATE__
 ;
@@ -5476,7 +5479,11 @@ add_option (struct options *options,
   else if (streq (p[0], "script-security") && p[1] && !p[2])
 {
   VERIFY_PERMISSION (OPT_P_GENERAL);
+#ifdef ENABLE_SCRIPTS
   script_security = atoi (p[1]);
+#else
+  msg (M_WARN, "NOTE: script-security directive ignored due to build 
setting");
+#endif
 }
   else if (streq (p[0], "mssfix") && !p[2])
 {
-- 
1.9.1




[Openvpn-devel] [PATCH 07/10] Implemented x509-track for PolarSSL.

2016-03-03 Thread James Yonan
Signed-off-by: James Yonan 
---
 src/openvpn/ssl_verify_polarssl.c | 166 ++
 src/openvpn/syshead.h |   2 +-
 2 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/src/openvpn/ssl_verify_polarssl.c 
b/src/openvpn/ssl_verify_polarssl.c
index 9d0d086..ab693d2 100644
--- a/src/openvpn/ssl_verify_polarssl.c
+++ b/src/openvpn/ssl_verify_polarssl.c
@@ -198,6 +198,172 @@ x509_get_subject(x509_crt *cert, struct gc_arena *gc)
   return subject;
 }

+#ifdef ENABLE_X509_TRACK
+
+/* these match NID's in OpenSSL crypto/objects/objects.h */
+#define NID_undef  0
+#define NID_sha164
+#define NID_commonName  13
+#define NID_countryName 14
+#define NID_localityName15
+#define NID_stateOrProvinceName 16
+#define NID_organizationName   17
+#define NID_organizationalUnitName  18
+#define NID_pkcs9_emailAddress  48
+
+struct nid_entry {
+  const char *name;
+  int nid;
+};
+
+static const struct nid_entry nid_list[] = {
+  { "SHA1", NID_sha1 },
+  { "CN",   NID_commonName },
+  { "C",NID_countryName },
+  { "L",NID_localityName },
+  { "ST",   NID_stateOrProvinceName },
+  { "O",NID_organizationName },
+  { "OU",   NID_organizationalUnitName },
+  { "emailAddress", NID_pkcs9_emailAddress },
+  { NULL, 0 }
+};
+
+static int
+name_to_nid(const char *name)
+{
+  const struct nid_entry *e = nid_list;
+  while (e->name)
+{
+  if (!strcmp(name, e->name))
+   return e->nid;
+  ++e;
+}
+  return NID_undef;
+}
+
+static void
+do_setenv_x509 (struct env_set *es, const char *name, char *value, int depth)
+{
+  char *name_expand;
+  size_t name_expand_size;
+
+  string_mod (value, CC_ANY, CC_CRLF, '?');
+  msg (D_X509_ATTR, "X509 ATTRIBUTE name='%s' value='%s' depth=%d", name, 
value, depth);
+  name_expand_size = 64 + strlen (name);
+  name_expand = (char *) malloc (name_expand_size);
+  check_malloc_return (name_expand);
+  openvpn_snprintf (name_expand, name_expand_size, "X509_%d_%s", depth, name);
+  setenv_str (es, name_expand, value);
+  free (name_expand);
+}
+
+static void
+do_setenv_nid_value(struct env_set *es, const struct x509_track *xt, const 
x509_name *xn,
+   int depth, struct gc_arena *gc)
+{
+  size_t i;
+  char *val;
+
+  for (i = 0; i < xn->val.len; ++i)
+if (xn->val.p[i] == '\0') /* error if embedded null in value */
+  return;
+  val = gc_malloc(xn->val.len+1, false, gc);
+  memcpy(val, xn->val.p, xn->val.len);
+  val[xn->val.len] = '\0';
+  do_setenv_x509(es, xt->name, val, depth);
+}
+
+static void
+do_setenv_nid(struct env_set *es, const struct x509_track *xt, const x509_crt 
*cert,
+ int depth, struct gc_arena *gc)
+{
+  const x509_name *xn;
+  for (xn = >subject; xn != NULL; xn = xn->next)
+{
+  switch (xt->nid)
+   {
+   case NID_commonName:
+ if (OID_CMP(OID_AT_CN, >oid))
+   do_setenv_nid_value(es, xt, xn, depth, gc);
+ break;
+   case NID_countryName:
+ if (OID_CMP(OID_AT_COUNTRY, >oid))
+   do_setenv_nid_value(es, xt, xn, depth, gc);
+ break;
+   case NID_localityName:
+ if (OID_CMP(OID_AT_LOCALITY, >oid))
+   do_setenv_nid_value(es, xt, xn, depth, gc);
+ break;
+   case NID_stateOrProvinceName:
+ if (OID_CMP(OID_AT_STATE, >oid))
+   do_setenv_nid_value(es, xt, xn, depth, gc);
+ break;
+   case NID_organizationName:
+ if (OID_CMP(OID_AT_ORGANIZATION, >oid))
+   do_setenv_nid_value(es, xt, xn, depth, gc);
+ break;
+   case NID_organizationalUnitName:
+ if (OID_CMP(OID_AT_ORG_UNIT, >oid))
+   do_setenv_nid_value(es, xt, xn, depth, gc);
+ break;
+   case NID_pkcs9_emailAddress:
+ if (OID_CMP(OID_PKCS9_EMAIL, >oid))
+   do_setenv_nid_value(es, xt, xn, depth, gc);
+ break;
+   }
+}
+}
+
+void
+x509_track_add (const struct x509_track **ll_head, const char *name, int 
msglevel, struct gc_arena *gc)
+{
+  struct x509_track *xt;
+  ALLOC_OBJ_CLEAR_GC (xt, struct x509_track, gc);
+  if (*name == '+')
+{
+  xt->flags |= XT_FULL_CHAIN;
+  ++name;
+}
+  xt->name = name;
+  xt->nid = name_to_nid(name);
+  if (xt->nid != NID_undef)
+{
+  xt->next = *ll_head;
+  *ll_head = xt;
+}
+  else
+msg(msglevel, "x509_track: no such attribute '%s'", name);
+}
+
+void
+x509_setenv_track (const struct x509_track *xt, struct env_set *es, const int 
depth, x509_crt *cert)
+{
+  struct gc_arena gc = gc_new();
+  while (xt)
+{
+  if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
+   {
+ switch (xt->nid)
+   {
+   case NID_sha1:
+ {
+   unsigned char *sha1_hash = x509_get_sha1_hash(cert, );
+   char 

[Openvpn-devel] [PATCH 06/10] PolarSSL x509_get_sha1_hash now returns correct SHA1 fingerprint.

2016-03-03 Thread James Yonan
Signed-off-by: James Yonan 
---
 src/openvpn/ssl_verify_polarssl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/openvpn/ssl_verify_polarssl.c 
b/src/openvpn/ssl_verify_polarssl.c
index e87d2e2..9d0d086 100644
--- a/src/openvpn/ssl_verify_polarssl.c
+++ b/src/openvpn/ssl_verify_polarssl.c
@@ -176,7 +176,7 @@ unsigned char *
 x509_get_sha1_hash (x509_crt *cert, struct gc_arena *gc)
 {
   unsigned char *sha1_hash = gc_malloc(SHA_DIGEST_LENGTH, false, gc);
-  sha1(cert->tbs.p, cert->tbs.len, sha1_hash);
+  sha1(cert->raw.p, cert->raw.len, sha1_hash);
   return sha1_hash;
 }

-- 
1.9.1




[Openvpn-devel] [PATCH 05/10] Extended x509-track for OpenSSL to report SHA1 fingerprint.

2016-03-03 Thread James Yonan
For example:

  x509-track "+SHA1"

will extract the SHA1 fingerprints for all certs in the
peer chain.

This patch is ported from OpenVPN 2.1.

Signed-off-by: James Yonan 
---
 src/openvpn/ssl_verify_openssl.c | 114 +--
 1 file changed, 74 insertions(+), 40 deletions(-)

diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c
index d014f9d..cde884b 100644
--- a/src/openvpn/ssl_verify_openssl.c
+++ b/src/openvpn/ssl_verify_openssl.c
@@ -305,6 +305,27 @@ err:

 #ifdef ENABLE_X509_TRACK

+/*
+ * x509-track implementation -- save X509 fields to environment,
+ * using the naming convention:
+ *
+ *  X509_{cert_depth}_{name}={value}
+ *
+ * This function differs from x509_setenv below in the following ways:
+ *
+ * (1) Only explicitly named attributes in xt are saved, per usage
+ * of "x509-track" program options.
+ * (2) Only the level 0 cert info is saved unless the XT_FULL_CHAIN
+ * flag is set in xt->flags (corresponds with prepending a '+'
+ * to the name when specified by "x509-track" program option).
+ * (3) This function supports both X509 subject name fields as
+ * well as X509 V3 extensions.
+ * (4) This function can return the SHA1 fingerprint of a cert, e.g.
+ *   x509-track "+SHA1"
+ * will return the SHA1 fingerprint for each certificate in the
+ * peer chain.
+ */
+
 void
 x509_track_add (const struct x509_track **ll_head, const char *name, int 
msglevel, struct gc_arena *gc)
 {
@@ -346,58 +367,71 @@ do_setenv_x509 (struct env_set *es, const char *name, 
char *value, int depth)
 void
 x509_setenv_track (const struct x509_track *xt, struct env_set *es, const int 
depth, X509 *x509)
 {
+  struct gc_arena gc = gc_new();
   X509_NAME *x509_name = X509_get_subject_name (x509);
   const char nullc = '\0';
-  int i;

   while (xt)
 {
   if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
{
- i = X509_NAME_get_index_by_NID(x509_name, xt->nid, -1);
- if (i >= 0)
+ switch (xt->nid)
{
- X509_NAME_ENTRY *ent = X509_NAME_get_entry(x509_name, i);
- if (ent)
-   {
- ASN1_STRING *val = X509_NAME_ENTRY_get_data (ent);
- unsigned char *buf;
- buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b 
ASN1_STRING_to_UTF8 requires this workaround */
- if (ASN1_STRING_to_UTF8 (, val) > 0)
-   {
- do_setenv_x509(es, xt->name, (char *)buf, depth);
- OPENSSL_free (buf);
-   }
-   }
-   }
- else
-   {
- i = X509_get_ext_by_NID(x509, xt->nid, -1);
- if (i >= 0)
-   {
- X509_EXTENSION *ext = X509_get_ext(x509, i);
- if (ext)
-   {
- BIO *bio = BIO_new(BIO_s_mem());
- if (bio)
-   {
- if (X509V3_EXT_print(bio, ext, 0, 0))
-   {
- if (BIO_write(bio, , 1) == 1)
-   {
- char *str;
- BIO_get_mem_data(bio, );
- do_setenv_x509(es, xt->name, str, depth);
-   }
-   }
- BIO_free(bio);
-   }
-   }
-   }
+   case NID_sha1:
+ {
+   char *sha1_fingerprint = format_hex_ex(x509->sha1_hash, 
SHA_DIGEST_LENGTH, 0, 1 | FHE_CAPS, ":", );
+   do_setenv_x509(es, xt->name, sha1_fingerprint, depth);
+ }
+ break;
+   default:
+ {
+   int i = X509_NAME_get_index_by_NID(x509_name, xt->nid, -1);
+   if (i >= 0)
+ {
+   X509_NAME_ENTRY *ent = X509_NAME_get_entry(x509_name, i);
+   if (ent)
+ {
+   ASN1_STRING *val = X509_NAME_ENTRY_get_data (ent);
+   unsigned char *buf;
+   buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b 
ASN1_STRING_to_UTF8 requires this workaround */
+   if (ASN1_STRING_to_UTF8 (, val) > 0)
+ {
+   do_setenv_x509(es, xt->name, (char *)buf, depth);
+   OPENSSL_free (buf);
+ }
+ }
+ }
+   else
+ {
+   i = X509_get_ext_by_NID(x509, xt->nid, -1);
+   if (i >= 0)
+ {
+   X509_EXTENSION *ext = X509_get_ext(x509, i);
+   if (ext)
+ {
+   BIO *bio = BIO_new(BIO_s_mem());
+   

[Openvpn-devel] [PATCH 04/10] Added flags parameter to format_hex_ex.

2016-03-03 Thread James Yonan
We add the flags parameter without changing the signature of
the function by repurposing the space_break parameter into
space_break_flags where the lower 8 bits are used for the
previous space_break parameter and the higher bits are used
for flag values.

Added new flag FHE_CAPS that formats the generated hex string
in upper case.

Signed-off-by: James Yonan 
---
 src/openvpn/buffer.c | 11 +++
 src/openvpn/buffer.h |  4 +++-
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c
index bc67d65..52c6ab9 100644
--- a/src/openvpn/buffer.c
+++ b/src/openvpn/buffer.c
@@ -435,18 +435,21 @@ gc_transfer (struct gc_arena *dest, struct gc_arena *src)

 char *
 format_hex_ex (const uint8_t *data, int size, int maxoutput,
-  int space_break, const char* separator,
+  unsigned int space_break_flags, const char* separator,
   struct gc_arena *gc)
 {
   struct buffer out = alloc_buf_gc (maxoutput ? maxoutput :
-   ((size * 2) + (size / space_break) * (int) 
strlen (separator) + 2),
+   ((size * 2) + (size / (space_break_flags & 
FHE_SPACE_BREAK_MASK)) * (int) strlen (separator) + 2),
gc);
   int i;
   for (i = 0; i < size; ++i)
 {
-  if (separator && i && !(i % space_break))
+  if (separator && i && !(i % (space_break_flags & FHE_SPACE_BREAK_MASK)))
buf_printf (, "%s", separator);
-  buf_printf (, "%02x", data[i]);
+  if (space_break_flags & FHE_CAPS)
+   buf_printf (, "%02X", data[i]);
+  else
+   buf_printf (, "%02x", data[i]);
 }
   buf_catrunc (, "[more...]");
   return (char *)out.data;
diff --git a/src/openvpn/buffer.h b/src/openvpn/buffer.h
index 24f52aa..8070439 100644
--- a/src/openvpn/buffer.h
+++ b/src/openvpn/buffer.h
@@ -403,9 +403,11 @@ bool buf_parse (struct buffer *buf, const int delim, char 
*line, const int size)
 /*
  * Hex dump -- Output a binary buffer to a hex string and return it.
  */
+#define FHE_SPACE_BREAK_MASK 0xFF /* space_break parameter in lower 8 bits */
+#define FHE_CAPS 0x100/* output hex in caps */
 char *
 format_hex_ex (const uint8_t *data, int size, int maxoutput,
-  int space_break, const char* separator,
+  unsigned int space_break_flags, const char* separator,
   struct gc_arena *gc);

 static inline char *
-- 
1.9.1




[Openvpn-devel] [PATCH 03/10] tls_serial_{n} value should be distinguishable as hex or decimal.

2016-03-03 Thread James Yonan
To accomplish this, prepend 'x' before hex serial numbers, so they
can be distinguished from decimal serial numbers.  For example:

  tls_serial_1 = "x4D:9B:7C:94"

is equivalent to:

  tls_serial_1 = "1302035604"

Currently, only PolarSSL generates hex serial numbers while
OpenSSL returns decimal serial numbers.

RFC 5280, published in 2008, decrees that serial numbers can be
up to 20 bytes long, hence it is necessary to support SSL
libraries that return the serial number as a hex string.

Signed-off-by: James Yonan 
---
 src/openvpn/ssl_verify_polarssl.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/openvpn/ssl_verify_polarssl.c 
b/src/openvpn/ssl_verify_polarssl.c
index a2e6a8e..e87d2e2 100644
--- a/src/openvpn/ssl_verify_polarssl.c
+++ b/src/openvpn/ssl_verify_polarssl.c
@@ -161,11 +161,12 @@ char *
 backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, struct gc_arena *gc)
 {
   char *buf = NULL;
-  size_t len = cert->serial.len * 3 + 1;
+  size_t len = cert->serial.len * 3;

-  buf = gc_malloc(len, true, gc);
+  buf = gc_malloc(len+1, true, gc);

-  if(x509_serial_gets(buf, len-1, >serial) < 0)
+  buf[0] = 'x';
+  if(x509_serial_gets(buf+1, len, >serial) < 0)
 buf = NULL;

   return buf;
-- 
1.9.1




[Openvpn-devel] [PATCH 02/10] Added PIP_OPT_MASK for process_ip_header fast exit path.

2016-03-03 Thread James Yonan
Define PIP_OPT_MASK to represent all flags of interest to
process_ip_header, so that it can have a fast exit path
if no flags are set.

Merged from OpenVPN 2.1

Signed-off-by: James Yonan 
---
 src/openvpn/forward.c | 8 +---
 src/openvpn/forward.h | 4 +++-
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
index 4a91f92..ef554fc 100644
--- a/src/openvpn/forward.c
+++ b/src/openvpn/forward.c
@@ -1054,13 +1054,7 @@ process_ip_header (struct context *c, unsigned int 
flags, struct buffer *buf)
* The --passtos and --mssfix options require
* us to examine the IPv4 header.
*/
-
-  if (flags & (PIP_MSSFIX
-#if PASSTOS_CAPABILITY
- | PIPV4_PASSTOS
-#endif
- | PIPV4_CLIENT_NAT
- ))
+  if (flags & PIP_OPT_MASK)
{
  struct buffer ipbuf = *buf;
  if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), ))
diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h
index af3b0a6..7debcb1 100644
--- a/src/openvpn/forward.h
+++ b/src/openvpn/forward.h
@@ -249,9 +249,11 @@ bool send_control_channel_string (struct context *c, const 
char *str, int msglev

 #define PIPV4_PASSTOS (1<<0)
 #define PIP_MSSFIX(1<<1) /* v4 and v6 */
-#define PIPV4_OUTGOING(1<<2)
 #define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
 #define PIPV4_CLIENT_NAT  (1<<4)
+#define PIP_OPT_MASK  0x /* all possible options for */
+ /* process_ip_header() */
+#define PIPV4_OUTGOING(1<<16)

 void process_ip_header (struct context *c, unsigned int flags, struct buffer 
*buf);

-- 
1.9.1




[Openvpn-devel] [PATCH 01/10] Added "remote-override" config directive.

2016-03-03 Thread James Yonan
remote-override  -- replace the hostname in all remote
directives with alt-remote.

Merged from OpenVPN 2.1

Signed-off-by: James Yonan 
---
 doc/openvpn.8 | 5 +
 src/openvpn/options.c | 8 +++-
 src/openvpn/options.h | 2 ++
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/doc/openvpn.8 b/doc/openvpn.8
index 628d877..249100d 100644
--- a/doc/openvpn.8
+++ b/doc/openvpn.8
@@ -281,6 +281,11 @@ DNS caching.  For example, "foo.bar.gov" would be modified 
to
 ".foo.bar.gov".
 .\"*
 .TP
+.B \-\-remote-override [alt-remote]
+Replace the hostname in all remote directives with
+.B alt-remote.
+.\"*
+.TP
 .B 
 Define a client connection
 profile.  Client connection profiles are groups of OpenVPN options that
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 02def3a..0942a4d 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -118,6 +118,7 @@ static const char usage_message[] =
   "--remote host [port] : Remote host name or ip address.\n"
   "--remote-random : If multiple --remote options specified, choose one 
randomly.\n"
   "--remote-random-hostname : Add a random string to remote DNS name.\n"
+  "--remote-override a : Replace the hostname in all remote directives with 
a.\n"
   "--mode m: Major mode, m = 'p2p' (default, point-to-point) or 
'server'.\n"
   "--proto p   : Use protocol p for communicating with peer.\n"
   "  p = udp (default), tcp-server, or tcp-client\n"
@@ -4565,6 +4566,11 @@ add_option (struct options *options,
goto err;
 }
 #endif
+  else if (streq (p[0], "remote-override") && p[1])
+{
+  VERIFY_PERMISSION (OPT_P_GENERAL);
+  options->remote_override = p[1];
+}
   else if (streq (p[0], "remote") && p[1] && !p[4])
 {
   struct remote_entry re;
@@ -4573,7 +4579,7 @@ add_option (struct options *options,
   re.af=0;

   VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
-  re.remote = p[1];
+  re.remote = options->remote_override ? options->remote_override : p[1];
   if (p[2])
{
  re.remote_port = p[2];
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 23d3992..e281069 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -213,6 +213,8 @@ struct options

   struct remote_host_store *rh_store;

+  const char *remote_override;
+
   bool remote_random;
   const char *ipchange;
   const char *dev;
-- 
1.9.1