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>
| ... | ... |
@@ -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 |