Browse code

Merge branch 'feat_misc' into beta2.2

Conflicts:
Makefile.am
- Copyright update
- Added configure.h to CLEANFILES
options.c
- Copyright update
- More verbose information about enabled features

Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>

David Sommerseth authored on 2010/07/23 05:33:16
Showing 16 changed files
... ...
@@ -6,6 +6,7 @@
6 6
 #             packet compression.
7 7
 #
8 8
 #  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
9
+#  Copyright (C) 2010      David Sommerseth <dazo@users.sourceforge.net>
9 10
 #
10 11
 #  This program is free software; you can redistribute it and/or modify
11 12
 #  it under the terms of the GNU General Public License version 2
... ...
@@ -37,7 +38,7 @@ MAINTAINERCLEANFILES = \
37 37
 	$(srcdir)/depcomp $(srcdir)/aclocal.m4 \
38 38
 	$(srcdir)/config.guess $(srcdir)/config.sub \
39 39
 	$(srcdir)/openvpn.spec
40
-CLEANFILES = openvpn.8.html
40
+CLEANFILES = openvpn.8.html configure.h
41 41
 
42 42
 EXTRA_DIST = \
43 43
 	easy-rsa \
... ...
@@ -64,7 +65,8 @@ dist_noinst_SCRIPTS = \
64 64
 	$(TESTS) \
65 65
 	doclean \
66 66
 	domake-win \
67
-	t_cltsrv-down.sh
67
+	t_cltsrv-down.sh \
68
+	configure_h.awk configure_log.awk
68 69
 
69 70
 dist_noinst_DATA = \
70 71
 	openvpn.spec \
... ...
@@ -140,6 +142,12 @@ openvpn_SOURCES = \
140 140
 	win32.h win32.c \
141 141
 	cryptoapi.h cryptoapi.c
142 142
 
143
+nodist_openvpn_SOURCES = configure.h
144
+options.$(OBJEXT): configure.h
145
+
146
+configure.h: Makefile
147
+	awk -f $(srcdir)/configure_h.awk config.h > $@
148
+	awk -f $(srcdir)/configure_log.awk config.log >> $@
143 149
 
144 150
 dist-hook:
145 151
 	cd $(distdir) && for i in $(EXTRA_DIST) $(SUBDIRS) ; do find $$i -name .svn -type d -prune -exec rm -rf '{}' ';' ; rm -f `find $$i -type f | grep -E '(^|\/)\.?\#|\~$$|\.s?o$$'` ; done
... ...
@@ -97,6 +97,6 @@ typedef unsigned long ptr_type;
97 97
 /*
98 98
  * Script security warning
99 99
  */
100
-#define SCRIPT_SECURITY_WARNING "openvpn_execve: external program may not be called unless '--script-security 2' or higher is enabled.  Use '--script-security 3 system' for backward compatibility with 2.1_rc8 and earlier.  See --help text or man page for detailed info."
100
+#define SCRIPT_SECURITY_WARNING "WARNING: External program may not be called unless '--script-security 2' or higher is enabled.  Use '--script-security 3 system' for backward compatibility with 2.1_rc8 and earlier.  See --help text or man page for detailed info."
101 101
 
102 102
 #endif
103 103
new file mode 100644
... ...
@@ -0,0 +1,39 @@
0
+#
1
+#  OpenVPN -- An application to securely tunnel IP networks
2
+#             over a single UDP port, with support for SSL/TLS-based
3
+#             session authentication and key exchange,
4
+#             packet encryption, packet authentication, and
5
+#             packet compression.
6
+#
7
+#  Copyright (C) 2010  David Sommerseth <dazo@users.sourceforge.net>
8
+#
9
+#  This program is free software; you can redistribute it and/or modify
10
+#  it under the terms of the GNU General Public License version 2
11
+#  as published by the Free Software Foundation.
12
+#
13
+#  This program is distributed in the hope that it will be useful,
14
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+#  GNU General Public License for more details.
17
+#
18
+#  You should have received a copy of the GNU General Public License
19
+#  along with this program (see the file COPYING included with this
20
+#  distribution); if not, write to the Free Software Foundation, Inc.,
21
+#  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+#
23
+#
24
+#  This script will build up a line which can be included into a C program.
25
+#  The line will contain all interesting #define statements from f.ex. ./config.h
26
+#
27
+
28
+BEGIN {
29
+	printf ("#define CONFIGURE_DEFINES \"")
30
+}
31
+
32
+/^#define (ENABLE|DISABLE|DEPRECATED|USE)_/ {
33
+	printf (" %s", $2)
34
+}
35
+
36
+END {
37
+	printf ("\"\n")
38
+}
0 39
new file mode 100644
... ...
@@ -0,0 +1,33 @@
0
+#
1
+#  OpenVPN -- An application to securely tunnel IP networks
2
+#             over a single UDP port, with support for SSL/TLS-based
3
+#             session authentication and key exchange,
4
+#             packet encryption, packet authentication, and
5
+#             packet compression.
6
+#
7
+#  Copyright (C) 2010  David Sommerseth <dazo@users.sourceforge.net>
8
+#
9
+#  This program is free software; you can redistribute it and/or modify
10
+#  it under the terms of the GNU General Public License version 2
11
+#  as published by the Free Software Foundation.
12
+#
13
+#  This program is distributed in the hope that it will be useful,
14
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+#  GNU General Public License for more details.
17
+#
18
+#  You should have received a copy of the GNU General Public License
19
+#  along with this program (see the file COPYING included with this
20
+#  distribution); if not, write to the Free Software Foundation, Inc.,
21
+#  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+#
23
+#
24
+#  This script will build up a line which can be included into a C program.
25
+#  The line will only contain the first entry of the ./configure line from
26
+#  ./config.log.
27
+#
28
+
29
+/\$ (.*)\/configure/ {
30
+	printf ("#define CONFIGURE_CALL \"%s\"\n", $0)
31
+	exit 0
32
+}
... ...
@@ -192,6 +192,12 @@ while [ $# -gt 0 ]; do
192 192
 		     $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --list-objects --login --slot "$PKCS11_SLOT"
193 193
 		     exit 0;;
194 194
 
195
+        --help|--usage)
196
+                    usage
197
+                    exit ;;
198
+        --version)
199
+                    echo "$PROGNAME $VERSION"
200
+                    exit ;;
195 201
 	# errors
196 202
 	--*        ) die "$PROGNAME: unknown option: $1" ;;
197 203
 	*          ) break ;;
... ...
@@ -1191,7 +1191,7 @@ do_route (const struct options *options,
1191 1191
       struct argv argv = argv_new ();
1192 1192
       setenv_str (es, "script_type", "route-up");
1193 1193
       argv_printf (&argv, "%sc", options->route_script);
1194
-      openvpn_execve_check (&argv, es, S_SCRIPT, "Route script failed");
1194
+      openvpn_run_script (&argv, es, 0, "--route-up");
1195 1195
       argv_reset (&argv);
1196 1196
     }
1197 1197
 
... ...
@@ -2024,6 +2024,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
2024 2024
 #endif
2025 2025
 
2026 2026
   to.verify_command = options->tls_verify;
2027
+  to.verify_export_cert = options->tls_export_cert;
2027 2028
   to.verify_x509name = options->tls_remote;
2028 2029
   to.crl_file = options->crl_file;
2029 2030
   to.ns_cert_type = options->ns_cert_type;
... ...
@@ -230,7 +230,7 @@ run_up_down (const char *command,
230 230
 		  ifconfig_local, ifconfig_remote,
231 231
 		  context);
232 232
       argv_msg (M_INFO, &argv);
233
-      openvpn_execve_check (&argv, es, S_SCRIPT|S_FATAL, "script failed");
233
+      openvpn_run_script (&argv, es, S_FATAL, "--up/--down");
234 234
       argv_reset (&argv);
235 235
     }
236 236
 
... ...
@@ -493,6 +493,7 @@ openvpn_execve_allowed (const unsigned int flags)
493 493
     return script_security >= SSEC_BUILT_IN;
494 494
 }
495 495
 
496
+
496 497
 #ifndef WIN32
497 498
 /*
498 499
  * Run execve() inside a fork().  Designed to replicate the semantics of system() but
... ...
@@ -504,6 +505,7 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
504 504
 {
505 505
   struct gc_arena gc = gc_new ();
506 506
   int ret = -1;
507
+  static bool warn_shown = false;
507 508
 
508 509
   if (a && a->argv[0])
509 510
     {
... ...
@@ -540,9 +542,10 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
540 540
 	      ASSERT (0);
541 541
 	    }
542 542
 	}
543
-      else
543
+      else if (!warn_shown && (script_security < SSEC_SCRIPTS))
544 544
 	{
545 545
 	  msg (M_WARN, SCRIPT_SECURITY_WARNING);
546
+          warn_shown = true;
546 547
 	}
547 548
 #else
548 549
       msg (M_WARN, "openvpn_execve: execve function not available");
... ...
@@ -136,6 +136,15 @@ bool openvpn_execve_check (const struct argv *a, const struct env_set *es, const
136 136
 bool openvpn_execve_allowed (const unsigned int flags);
137 137
 int openvpn_system (const char *command, const struct env_set *es, unsigned int flags);
138 138
 
139
+static inline bool
140
+openvpn_run_script (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *hook)
141
+{
142
+  char msg[256];
143
+
144
+  openvpn_snprintf(msg, sizeof(msg), "WARNING: Failed running command (%s)", hook);
145
+  return openvpn_execve_check(a, es, flags | S_SCRIPT, msg);
146
+};
147
+
139 148
 #ifdef HAVE_STRERROR
140 149
 /* a thread-safe version of strerror */
141 150
 const char* strerror_ts (int errnum, struct gc_arena *gc);
... ...
@@ -308,6 +317,7 @@ void get_user_pass_auto_userid (struct user_pass *up, const char *tag);
308 308
 extern const char *iproute_path;
309 309
 #endif
310 310
 
311
+/* Script security */
311 312
 #define SSEC_NONE      0 /* strictly no calling of external programs */
312 313
 #define SSEC_BUILT_IN  1 /* only call built-in programs such as ifconfig, route, netsh, etc.*/
313 314
 #define SSEC_SCRIPTS   2 /* allow calling of built-in programs and user-defined scripts */
... ...
@@ -109,7 +109,7 @@ learn_address_script (const struct multi_context *m,
109 109
 		   mroute_addr_print (addr, &gc));
110 110
       if (mi)
111 111
 	argv_printf_cat (&argv, "%s", tls_common_name (mi->context.c2.tls_multi, false));
112
-      if (!openvpn_execve_check (&argv, es, S_SCRIPT, "WARNING: learn-address command failed"))
112
+      if (!openvpn_run_script (&argv, es, 0, "--learn-address"))
113 113
 	ret = false;
114 114
       argv_reset (&argv);
115 115
     }
... ...
@@ -480,7 +480,7 @@ multi_client_disconnect_script (struct multi_context *m,
480 480
 	  struct argv argv = argv_new ();
481 481
 	  setenv_str (mi->context.c2.es, "script_type", "client-disconnect");
482 482
 	  argv_printf (&argv, "%sc", mi->context.options.client_disconnect_script);
483
-	  openvpn_execve_check (&argv, mi->context.c2.es, S_SCRIPT, "client-disconnect command failed");
483
+	  openvpn_run_script (&argv, mi->context.c2.es, 0, "--client-disconnect");
484 484
 	  argv_reset (&argv);
485 485
 	}
486 486
 #ifdef MANAGEMENT_DEF_AUTH
... ...
@@ -1594,7 +1594,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
1594 1594
 		       mi->context.options.client_connect_script,
1595 1595
 		       dc_file);
1596 1596
 
1597
-	  if (openvpn_execve_check (&argv, mi->context.c2.es, S_SCRIPT, "client-connect command failed"))
1597
+	  if (openvpn_run_script (&argv, mi->context.c2.es, 0, "--client-connect"))
1598 1598
 	    {
1599 1599
 	      multi_client_connect_post (m, mi, dc_file, option_permissions_mask, &option_types_found);
1600 1600
 	      ++cc_succeeded_count;
... ...
@@ -4244,11 +4244,23 @@ test).
4244 4244
 
4245 4245
 .B cmd
4246 4246
 should return 0 to allow the TLS handshake to proceed, or 1 to fail.
4247
+
4248
+Note that
4249
+.B cmd
4250
+is a command line and as such may (if enclosed in quotes) contain
4251
+whitespace separated arguments.  The first word of
4247 4252
 .B cmd
4248
-is executed as
4253
+is the shell command to execute and the remaining words are its
4254
+arguments.
4255
+When
4256
+.B cmd
4257
+is executed two arguments are appended, as follows:
4249 4258
 
4250 4259
 .B cmd certificate_depth X509_NAME_oneline
4251 4260
 
4261
+These arguments are, respectively, the current certificate depth and
4262
+the X509 common name (cn) of the peer.
4263
+
4252 4264
 This feature is useful if the peer you want to trust has a certificate
4253 4265
 which was signed by a certificate authority who also signed many
4254 4266
 other certificates, where you don't necessarily want to trust all of them,
... ...
@@ -4262,14 +4274,14 @@ in the OpenVPN distribution.
4262 4262
 
4263 4263
 See the "Environmental Variables" section below for
4264 4264
 additional parameters passed as environmental variables.
4265
-
4266
-Note that
4267
-.B cmd
4268
-can be a shell command with multiple arguments, in which
4269
-case all OpenVPN-generated arguments will be appended
4270
-to
4271
-.B cmd
4272
-to build a command line which will be passed to the script.
4265
+.\"*********************************************************
4266
+.TP
4267
+.B --tls-export-cert directory
4268
+Store the certificates the clients uses upon connection to this
4269
+directory. This will be done before --tls-verify is called.  The
4270
+certificates will use a temporary name and will be deleted when
4271
+the tls-verify script returns.  The file name used for the certificate
4272
+is available via the peer_cert environment variable.
4273 4273
 .\"*********************************************************
4274 4274
 .TP
4275 4275
 .B \-\-tls-remote name
... ...
@@ -5262,6 +5274,11 @@ than their names as denoted on the command line
5262 5262
 or configuration file.
5263 5263
 .\"*********************************************************
5264 5264
 .TP
5265
+.B peer_cert
5266
+Temporary file name containing the client certificate upon
5267
+connection.  Useful in conjunction with --tls-verify
5268
+.\"*********************************************************
5269
+.TP
5265 5270
 .B script_context
5266 5271
 Set to "init" or "restart" prior to up/down script execution.
5267 5272
 For more information, see
... ...
@@ -45,6 +45,8 @@
45 45
 #include "pool.h"
46 46
 #include "helper.h"
47 47
 #include "manage.h"
48
+#include "configure.h"
49
+#include <ctype.h>
48 50
 
49 51
 #include "memdbg.h"
50 52
 
... ...
@@ -503,6 +505,8 @@ static const char usage_message[] =
503 503
   "--key file      : Local private key in .pem format.\n"
504 504
   "--pkcs12 file   : PKCS#12 file containing local private key, local certificate\n"
505 505
   "                  and optionally the root CA certificate.\n"
506
+  "--x509-username-field : Field used in x509 certificat to be username.\n"
507
+  "                        Default is CN.\n"
506 508
 #ifdef WIN32
507 509
   "--cryptoapicert select-string : Load the certificate and private key from the\n"
508 510
   "                  Windows Certificate System Store.\n"
... ...
@@ -533,6 +537,9 @@ static const char usage_message[] =
533 533
   "                  tests of certification.  cmd should return 0 to allow\n"
534 534
   "                  TLS handshake to proceed, or 1 to fail.  (cmd is\n"
535 535
   "                  executed as 'cmd certificate_depth X509_NAME_oneline')\n"
536
+  "--tls-export-cert [directory] : Get peer cert in PEM format and store it \n"
537
+  "                  in an openvpn temporary file in [directory]. Peer cert is \n"
538
+  "                  stored before tls-verify script execution and deleted after.\n"
536 539
   "--tls-remote x509name: Accept connections only from a host with X509 name\n"
537 540
   "                  x509name. The remote host must also pass all other tests\n"
538 541
   "                  of verification.\n"
... ...
@@ -755,6 +762,7 @@ init_options (struct options *o, const bool init_gc)
755 755
   o->renegotiate_seconds = 3600;
756 756
   o->handshake_window = 60;
757 757
   o->transition_window = 3600;
758
+  o->x509_username_field = X509_USERNAME_FIELD_DEFAULT;
758 759
 #endif
759 760
 #endif
760 761
 #ifdef ENABLE_PKCS11
... ...
@@ -1333,6 +1341,7 @@ show_settings (const struct options *o)
1333 1333
 #endif
1334 1334
   SHOW_STR (cipher_list);
1335 1335
   SHOW_STR (tls_verify);
1336
+  SHOW_STR (tls_export_cert);
1336 1337
   SHOW_STR (tls_remote);
1337 1338
   SHOW_STR (crl_file);
1338 1339
   SHOW_INT (ns_cert_type);
... ...
@@ -2061,6 +2070,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
2061 2061
       MUST_BE_UNDEF (pkcs12_file);
2062 2062
       MUST_BE_UNDEF (cipher_list);
2063 2063
       MUST_BE_UNDEF (tls_verify);
2064
+      MUST_BE_UNDEF (tls_export_cert);
2064 2065
       MUST_BE_UNDEF (tls_remote);
2065 2066
       MUST_BE_UNDEF (tls_timeout);
2066 2067
       MUST_BE_UNDEF (renegotiate_bytes);
... ...
@@ -2903,6 +2913,12 @@ usage_version (void)
2903 2903
   msg (M_INFO|M_NOPREFIX, "%s", title_string);
2904 2904
   msg (M_INFO|M_NOPREFIX, "Originally developed by James Yonan");
2905 2905
   msg (M_INFO|M_NOPREFIX, "Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>");
2906
+#ifndef ENABLE_SMALL
2907
+#ifdef CONFIGURE_CALL
2908
+  msg (M_INFO|M_NOPREFIX, "\n%s\n", CONFIGURE_CALL);
2909
+#endif
2910
+  msg (M_INFO|M_NOPREFIX, "Compile time defines: %s", CONFIGURE_DEFINES);
2911
+#endif
2906 2912
   openvpn_exit (OPENVPN_EXIT_STATUS_USAGE); /* exit point */
2907 2913
 }
2908 2914
 
... ...
@@ -5730,6 +5746,11 @@ add_option (struct options *options,
5730 5730
 	goto err;
5731 5731
       options->tls_verify = string_substitute (p[1], ',', ' ', &options->gc);
5732 5732
     }
5733
+  else if (streq (p[0], "tls-export-cert") && p[1])
5734
+    {
5735
+      VERIFY_PERMISSION (OPT_P_GENERAL);
5736
+      options->tls_export_cert = p[1];
5737
+    }
5733 5738
   else if (streq (p[0], "tls-remote") && p[1])
5734 5739
     {
5735 5740
       VERIFY_PERMISSION (OPT_P_GENERAL);
... ...
@@ -5855,6 +5876,13 @@ add_option (struct options *options,
5855 5855
 	}
5856 5856
       options->key_method = key_method;
5857 5857
     }
5858
+  else if (streq (p[0], "x509-username-field") && p[1])
5859
+    {
5860
+      char *s = p[1];
5861
+      VERIFY_PERMISSION (OPT_P_GENERAL);
5862
+      while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */
5863
+      options->x509_username_field = p[1];
5864
+    }
5858 5865
 #endif /* USE_SSL */
5859 5866
 #endif /* USE_CRYPTO */
5860 5867
 #ifdef ENABLE_PKCS11
... ...
@@ -465,6 +465,7 @@ struct options
465 465
   const char *pkcs12_file;
466 466
   const char *cipher_list;
467 467
   const char *tls_verify;
468
+  const char *tls_export_cert;
468 469
   const char *tls_remote;
469 470
   const char *crl_file;
470 471
 
... ...
@@ -508,6 +509,9 @@ struct options
508 508
      within n seconds of handshake initiation. */
509 509
   int handshake_window;
510 510
 
511
+  /* Field used to be the username in X509 cert. */
512
+  char *x509_username_field;
513
+
511 514
   /* Old key allowed to live n seconds after new key goes active */
512 515
   int transition_window;
513 516
 
... ...
@@ -1695,7 +1695,7 @@ link_socket_connection_initiated (const struct buffer *buf,
1695 1695
       struct argv argv = argv_new ();
1696 1696
       setenv_str (es, "script_type", "ipchange");
1697 1697
       ipchange_fmt (true, &argv, info, &gc);
1698
-      openvpn_execve_check (&argv, es, S_SCRIPT, "ip-change command failed");
1698
+      openvpn_run_script (&argv, es, 0, "--ipchange");
1699 1699
       argv_reset (&argv);
1700 1700
     }
1701 1701
 
... ...
@@ -687,6 +687,51 @@ string_mod_sslname (char *str, const unsigned int restrictive_flags, const unsig
687 687
     string_mod (str, restrictive_flags, 0, '_');
688 688
 }
689 689
 
690
+/* Get peer cert and store it in pem format in a temporary file
691
+ * in tmp_dir
692
+ */
693
+
694
+const char *
695
+get_peer_cert(X509_STORE_CTX *ctx, const char *tmp_dir, struct gc_arena *gc)
696
+{
697
+  X509 *peercert;
698
+  FILE *peercert_file;
699
+  const char *peercert_filename="";
700
+
701
+  if(!tmp_dir)
702
+      return NULL;
703
+
704
+  /* get peer cert */
705
+  peercert = X509_STORE_CTX_get_current_cert(ctx);
706
+  if(!peercert)
707
+    {
708
+      msg (M_ERR, "Unable to get peer certificate from current context");
709
+      return NULL;
710
+    }
711
+
712
+  /* create tmp file to store peer cert */
713
+  peercert_filename = create_temp_filename (tmp_dir, "pcf", gc);
714
+
715
+  /* write peer-cert in tmp-file */
716
+  peercert_file = fopen(peercert_filename, "w+");
717
+  if(!peercert_file)
718
+    {
719
+      msg (M_ERR, "Failed to open temporary file : %s", peercert_filename);
720
+      return NULL;
721
+    }
722
+  if(PEM_write_X509(peercert_file,peercert)<0)
723
+    {
724
+      msg (M_ERR, "Failed to write peer certificate in PEM format");
725
+      fclose(peercert_file);
726
+      return NULL;
727
+    }
728
+
729
+  fclose(peercert_file);
730
+  return peercert_filename;
731
+}
732
+
733
+char * x509_username_field; /* GLOBAL */
734
+
690 735
 /*
691 736
  * Our verify callback function -- check
692 737
  * that an incoming peer certificate is good.
... ...
@@ -697,7 +742,7 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
697 697
 {
698 698
   char *subject = NULL;
699 699
   char envname[64];
700
-  char common_name[TLS_CN_LEN];
700
+  char common_name[TLS_USERNAME_LEN];
701 701
   SSL *ssl;
702 702
   struct tls_session *session;
703 703
   const struct tls_options *opt;
... ...
@@ -729,18 +774,20 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
729 729
   string_mod_sslname (subject, X509_NAME_CHAR_CLASS, opt->ssl_flags);
730 730
   string_replace_leading (subject, '-', '_');
731 731
 
732
-  /* extract the common name */
733
-  if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), "CN", common_name, TLS_CN_LEN))
732
+  /* extract the username (default is CN) */
733
+  if (!extract_x509_field_ssl (X509_get_subject_name (ctx->current_cert), x509_username_field, common_name, sizeof(common_name)))
734 734
     {
735 735
       if (!ctx->error_depth)
736
-	{
737
-	  msg (D_TLS_ERRORS, "VERIFY ERROR: could not extract Common Name from X509 subject string ('%s') -- note that the Common Name length is limited to %d characters",
738
-	       subject,
739
-	       TLS_CN_LEN);
740
-	  goto err;
741
-	}
736
+        {
737
+          msg (D_TLS_ERRORS, "VERIFY ERROR: could not extract %s from X509 subject string ('%s') -- note that the username length is limited to %d characters",
738
+                 x509_username_field,
739
+                 subject,
740
+                 TLS_USERNAME_LEN);
741
+          goto err;
742
+        }
742 743
     }
743 744
 
745
+
744 746
   string_mod_sslname (common_name, COMMON_NAME_CHAR_CLASS, opt->ssl_flags);
745 747
 
746 748
   cert_hash_remember (session, ctx->error_depth, ctx->current_cert->sha1_hash);
... ...
@@ -906,32 +953,48 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
906 906
   /* run --tls-verify script */
907 907
   if (opt->verify_command)
908 908
     {
909
+      const char *tmp_file;
910
+      struct gc_arena gc;
909 911
       int ret;
910 912
 
911 913
       setenv_str (opt->es, "script_type", "tls-verify");
912 914
 
915
+      if (opt->verify_export_cert)
916
+        {
917
+          gc = gc_new();
918
+          if (tmp_file=get_peer_cert(ctx, opt->verify_export_cert,&gc))
919
+           {
920
+             setenv_str(opt->es, "peer_cert", tmp_file);
921
+           }
922
+        }
923
+
913 924
       argv_printf (&argv, "%sc %d %s",
914 925
 		   opt->verify_command,
915 926
 		   ctx->error_depth,
916 927
 		   subject);
917 928
       argv_msg_prefix (D_TLS_DEBUG, &argv, "TLS: executing verify command");
918
-      ret = openvpn_execve (&argv, opt->es, S_SCRIPT);
929
+      ret = openvpn_run_script (&argv, opt->es, 0, "--tls-verify script");
919 930
 
920
-      if (system_ok (ret))
931
+      if (opt->verify_export_cert)
932
+        {
933
+           if (tmp_file)
934
+              delete_file(tmp_file);
935
+           gc_free(&gc);
936
+        }
937
+
938
+      if (ret)
921 939
 	{
922 940
 	  msg (D_HANDSHAKE, "VERIFY SCRIPT OK: depth=%d, %s",
923 941
 	       ctx->error_depth, subject);
924 942
 	}
925 943
       else
926 944
 	{
927
-	  if (!system_executed (ret))
928
-	    argv_msg_prefix (M_ERR, &argv, "Verify command failed to execute");
929 945
 	  msg (D_HANDSHAKE, "VERIFY SCRIPT ERROR: depth=%d, %s",
930 946
 	       ctx->error_depth, subject);
931 947
 	  goto err;		/* Reject connection */
932 948
 	}
933 949
     }
934
-  
950
+
935 951
   /* check peer cert against CRL */
936 952
   if (opt->crl_file)
937 953
     {
... ...
@@ -1749,7 +1812,8 @@ init_ssl (const struct options *options)
1749 1749
     }
1750 1750
   else
1751 1751
 #endif
1752
-    SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1752
+  x509_username_field = (char *) options->x509_username_field;
1753
+  SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1753 1754
 			verify_callback);
1754 1755
 
1755 1756
   /* Connection information callback */
... ...
@@ -3190,7 +3254,6 @@ verify_user_pass_script (struct tls_session *session, const struct user_pass *up
3190 3190
   struct gc_arena gc = gc_new ();
3191 3191
   struct argv argv = argv_new ();
3192 3192
   const char *tmp_file = "";
3193
-  int retval;
3194 3193
   bool ret = false;
3195 3194
 
3196 3195
   /* Is username defined? */
... ...
@@ -3233,16 +3296,11 @@ verify_user_pass_script (struct tls_session *session, const struct user_pass *up
3233 3233
 
3234 3234
       /* format command line */
3235 3235
       argv_printf (&argv, "%sc %s", session->opt->auth_user_pass_verify_script, tmp_file);
3236
-      
3236
+
3237 3237
       /* call command */
3238
-      retval = openvpn_execve (&argv, session->opt->es, S_SCRIPT);
3238
+      ret = openvpn_run_script (&argv, session->opt->es, 0,
3239
+				"--auth-user-pass-verify");
3239 3240
 
3240
-      /* test return status of command */
3241
-      if (system_ok (retval))
3242
-	ret = true;
3243
-      else if (!system_executed (retval))
3244
-	argv_msg_prefix (D_TLS_ERRORS, &argv, "TLS Auth Error: user-pass-verify script failed to execute");
3245
-	  
3246 3241
       if (!session->opt->auth_user_pass_verify_script_via_file)
3247 3242
 	setenv_del (session->opt->es, "password");
3248 3243
     }
... ...
@@ -3688,9 +3746,9 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
3688 3688
 	s2 = verify_user_pass_script (session, up);
3689 3689
 
3690 3690
       /* check sizing of username if it will become our common name */
3691
-      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_CN_LEN)
3691
+      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_USERNAME_LEN)
3692 3692
 	{
3693
-	  msg (D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_CN_LEN);
3693
+	  msg (D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_USERNAME_LEN);
3694 3694
 	  s1 = OPENVPN_PLUGIN_FUNC_ERROR;
3695 3695
 	}
3696 3696
 
... ...
@@ -278,8 +278,8 @@
278 278
  * Buffer sizes (also see mtu.h).
279 279
  */
280 280
 
281
-/* Maximum length of common name */
282
-#define TLS_CN_LEN 64
281
+/* Maximum length of the username in cert */
282
+#define TLS_USERNAME_LEN 64
283 283
 
284 284
 /* Legal characters in an X509 or common name */
285 285
 #define X509_NAME_CHAR_CLASS   (CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT|CC_COLON|CC_SLASH|CC_EQUAL)
... ...
@@ -288,6 +288,9 @@
288 288
 /* Maximum length of OCC options string passed as part of auth handshake */
289 289
 #define TLS_OPTIONS_LEN 512
290 290
 
291
+/* Default field in X509 to be username */
292
+#define X509_USERNAME_FIELD_DEFAULT "CN"
293
+
291 294
 /*
292 295
  * Range of key exchange methods
293 296
  */
... ...
@@ -444,6 +447,7 @@ struct tls_options
444 444
 
445 445
   /* cert verification parms */
446 446
   const char *verify_command;
447
+  const char *verify_export_cert;
447 448
   const char *verify_x509name;
448 449
   const char *crl_file;
449 450
   int ns_cert_type;
... ...
@@ -952,6 +952,8 @@ int
952 952
 openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags)
953 953
 {
954 954
   int ret = -1;
955
+  static bool exec_warn = false;
956
+
955 957
   if (a && a->argv[0])
956 958
     {
957 959
       if (openvpn_execve_allowed (flags))
... ...
@@ -1002,9 +1004,10 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
1002 1002
 	      ASSERT (0);
1003 1003
 	    }
1004 1004
 	}
1005
-      else
1005
+      else if (!exec_warn && (script_security < SSEC_SCRIPTS))
1006 1006
 	{
1007 1007
 	  msg (M_WARN, SCRIPT_SECURITY_WARNING);
1008
+          exec_warn = true;
1008 1009
 	}
1009 1010
     }
1010 1011
   else