summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2013-05-31 16:55:52 +0200
committerArne Schwabe <arne@rfc2549.org>2013-05-31 16:55:52 +0200
commit59645fe5e45de8cf87924a9ad83df4e283765043 (patch)
tree9a5117698e60455e7c917b851ac5ff26ed273442
parentd1f3e24621dcd5404fd9af7d9214c5ff2a07d438 (diff)
Update OpenVPN to current -master
--HG-- extra : rebase_source : 7d9f6d9e6ac62a8843f925e33c48a671ff153f91
-rw-r--r--openvpn/src/openvpn/common.h2
-rw-r--r--openvpn/src/openvpn/init.c23
-rw-r--r--openvpn/src/openvpn/manage.c30
-rw-r--r--openvpn/src/openvpn/multi.c52
-rw-r--r--openvpn/src/openvpn/multi.h3
-rw-r--r--openvpn/src/openvpn/options.c95
-rw-r--r--openvpn/src/openvpn/options.h1
-rw-r--r--openvpn/src/openvpn/socket.c11
-rw-r--r--openvpn/src/openvpn/ssl.c61
-rw-r--r--openvpn/src/openvpn/ssl_common.h10
10 files changed, 169 insertions, 119 deletions
diff --git a/openvpn/src/openvpn/common.h b/openvpn/src/openvpn/common.h
index dd2c83f4..2f85bec2 100644
--- a/openvpn/src/openvpn/common.h
+++ b/openvpn/src/openvpn/common.h
@@ -100,6 +100,6 @@ typedef unsigned long ptr_type;
/*
* Script security warning
*/
-#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."
+#define SCRIPT_SECURITY_WARNING "WARNING: External program may not be called unless '--script-security 2' or higher is enabled. See --help text or man page for detailed info."
#endif
diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c
index 335ebab1..f130cdfd 100644
--- a/openvpn/src/openvpn/init.c
+++ b/openvpn/src/openvpn/init.c
@@ -2221,7 +2221,12 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
to.renegotiate_seconds = options->renegotiate_seconds;
to.single_session = options->single_session;
#ifdef ENABLE_PUSH_PEER_INFO
- to.push_peer_info = options->push_peer_info;
+ if (options->push_peer_info) /* all there is */
+ to.push_peer_info_detail = 2;
+ else if (options->pull) /* pull clients send some details */
+ to.push_peer_info_detail = 1;
+ else /* default: no peer-info at all */
+ to.push_peer_info_detail = 0;
#endif
/* should we not xmit any packets until we get an initial
@@ -2545,12 +2550,16 @@ do_option_warnings (struct context *c)
msg (M_WARN, "NOTE: --connect-timeout option is not supported on this OS");
#endif
- if (script_security >= SSEC_SCRIPTS)
- msg (M_WARN, "NOTE: the current --script-security setting may allow this configuration to call user-defined scripts");
- else if (script_security >= SSEC_PW_ENV)
- msg (M_WARN, "WARNING: the current --script-security setting may allow passwords to be passed to scripts via environmental variables");
- else
- msg (M_WARN, "NOTE: " PACKAGE_NAME " 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables");
+ /* If a script is used, print appropiate warnings */
+ if (o->user_script_used)
+ {
+ if (script_security >= SSEC_SCRIPTS)
+ msg (M_WARN, "NOTE: the current --script-security setting may allow this configuration to call user-defined scripts");
+ else if (script_security >= SSEC_PW_ENV)
+ msg (M_WARN, "WARNING: the current --script-security setting may allow passwords to be passed to scripts via environmental variables");
+ else
+ msg (M_WARN, "NOTE: starting with " PACKAGE_NAME " 2.1, '--script-security 2' or higher is required to call user-defined scripts or executables");
+ }
}
static void
diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c
index 4e96d07f..23e76527 100644
--- a/openvpn/src/openvpn/manage.c
+++ b/openvpn/src/openvpn/manage.c
@@ -2458,33 +2458,6 @@ management_notify_generic (struct management *man, const char *str)
#ifdef MANAGEMENT_DEF_AUTH
-static bool
-validate_peer_info_line(const char *line)
-{
- uint8_t c;
- int state = 0;
- while ((c=*line++))
- {
- switch (state)
- {
- case 0:
- case 1:
- if (c == '=' && state == 1)
- state = 2;
- else if (isalnum(c) || c == '_')
- state = 1;
- else
- return false;
- case 2:
- if (isprint(c))
- ;
- else
- return false;
- }
- }
- return (state == 2);
-}
-
static void
man_output_peer_info_env (struct management *man, struct man_def_auth_context *mdac)
{
@@ -2523,7 +2496,8 @@ management_notify_client_needing_auth (struct management *management,
mode = "REAUTH";
msg (M_CLIENT, ">CLIENT:%s,%lu,%u", mode, mdac->cid, mda_key_id);
man_output_extra_env (management, "CLIENT");
- man_output_peer_info_env(management, mdac);
+ if (management->connection.env_filter_level>0)
+ man_output_peer_info_env(management, mdac);
man_output_env (es, true, management->connection.env_filter_level, "CLIENT");
mdac->flags |= DAF_INITIAL_AUTH;
}
diff --git a/openvpn/src/openvpn/multi.c b/openvpn/src/openvpn/multi.c
index f016b149..50f398dd 100644
--- a/openvpn/src/openvpn/multi.c
+++ b/openvpn/src/openvpn/multi.c
@@ -1562,6 +1562,58 @@ multi_client_connect_mda (struct multi_context *m,
#endif
+/* helper to parse peer_info received from multi client, validate
+ * (this is untrusted data) and put into environment
+ */
+bool
+validate_peer_info_line(char *line)
+{
+ uint8_t c;
+ int state = 0;
+ while (*line)
+ {
+ c = *line;
+ switch (state)
+ {
+ case 0:
+ case 1:
+ if (c == '=' && state == 1)
+ state = 2;
+ else if (isalnum(c) || c == '_')
+ state = 1;
+ else
+ return false;
+ case 2:
+ /* after the '=', replace non-printable or shell meta with '_' */
+ if (!isprint(c) || isspace(c) ||
+ c == '$' || c == '(' || c == '`' )
+ *line = '_';
+ }
+ line++;
+ }
+ return (state == 2);
+}
+
+void
+multi_output_peer_info_env (struct env_set *es, const char * peer_info)
+{
+ char line[256];
+ struct buffer buf;
+ buf_set_read (&buf, (const uint8_t *) peer_info, strlen(peer_info));
+ while (buf_parse (&buf, '\n', line, sizeof (line)))
+ {
+ chomp (line);
+ if (validate_peer_info_line(line) &&
+ (strncmp(line, "IV_", 3) == 0 || strncmp(line, "UV_", 3) == 0) )
+ {
+ msg (M_INFO, "peer info: %s", line);
+ env_set_add(es, line);
+ }
+ else
+ msg (M_WARN, "validation failed on peer_info line received from client");
+ }
+}
+
static void
multi_client_connect_setenv (struct multi_context *m,
struct multi_instance *mi)
diff --git a/openvpn/src/openvpn/multi.h b/openvpn/src/openvpn/multi.h
index fc2ffb24..7b97b0d2 100644
--- a/openvpn/src/openvpn/multi.h
+++ b/openvpn/src/openvpn/multi.h
@@ -312,6 +312,9 @@ void multi_close_instance_on_signal (struct multi_context *m, struct multi_insta
void init_management_callback_multi (struct multi_context *m);
void uninit_management_callback_multi (struct multi_context *m);
+bool validate_peer_info_line(char *line);
+void multi_output_peer_info_env (struct env_set *es, const char * peer_info);
+
/*
* Return true if our output queue is not full
*/
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index 37909ca9..f74ad8ef 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -2714,28 +2714,6 @@ options_postprocess_filechecks (struct options *options)
errs |= check_file_access (CHKACC_FILE, options->tmp_dir,
R_OK|W_OK|X_OK, "Temporary directory (--tmp-dir)");
- /* ** Script hooks that accept an optionally quoted and/or escaped executable path, ** */
- /* ** optionally followed by arguments ** */
- errs |= check_cmd_access (options->auth_user_pass_verify_script,
- "--auth-user-pass-verify script");
- errs |= check_cmd_access (options->client_connect_script,
- "--client-connect script");
- errs |= check_cmd_access (options->client_disconnect_script,
- "--client-disconnect script");
- errs |= check_cmd_access (options->tls_verify,
- "--tls-verify script");
- errs |= check_cmd_access (options->up_script,
- "--up script");
- errs |= check_cmd_access (options->down_script,
- "--down script");
- errs |= check_cmd_access (options->ipchange,
- "--ipchange script");
- errs |= check_cmd_access (options->route_script,
- "--route-up script");
- errs |= check_cmd_access (options->route_predown_script,
- "--route-pre-down script");
- errs |= check_cmd_access (options->learn_address_script,
- "--learn-address script");
#endif /* P2MP_SERVER */
if (errs)
@@ -3995,11 +3973,28 @@ msglevel_forward_compatible (struct options *options, const int msglevel)
}
static void
-warn_multiple_script (const char *script, const char *type) {
- if (script) {
- msg (M_WARN, "Multiple --%s scripts defined. "
- "The previously configured script is overridden.", type);
- }
+set_user_script (struct options *options,
+ const char **script,
+ const char *new_script,
+ const char *type)
+{
+ if (*script) {
+ msg (M_WARN, "Multiple --%s scripts defined. "
+ "The previously configured script is overridden.", type);
+ }
+ *script = new_script;
+ options->user_script_used = true;
+
+#ifndef ENABLE_SMALL
+ {
+ char script_name[100];
+ openvpn_snprintf (script_name, sizeof(script_name),
+ "--%s script", type);
+
+ if (check_cmd_access (*script, script_name))
+ msg (M_USAGE, "Please correct this error.");
+ }
+#endif
}
@@ -4442,8 +4437,10 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->ipchange, "ipchange");
- options->ipchange = string_substitute (p[1], ',', ' ', &options->gc);
+ set_user_script (options,
+ &options->ipchange,
+ string_substitute (p[1], ',', ' ', &options->gc),
+ "ipchange");
}
else if (streq (p[0], "float"))
{
@@ -4489,16 +4486,14 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->up_script, "up");
- options->up_script = p[1];
+ set_user_script (options, &options->up_script, p[1], "up");
}
else if (streq (p[0], "down") && p[1])
{
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->down_script, "down");
- options->down_script = p[1];
+ set_user_script (options, &options->down_script, p[1], "down");
}
else if (streq (p[0], "down-pre"))
{
@@ -4995,8 +4990,7 @@ add_option (struct options *options,
#ifdef ENABLE_OCC
else if (streq (p[0], "explicit-exit-notify"))
{
- VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
-/* VERIFY_PERMISSION (OPT_P_EXPLICIT_NOTIFY); */
+ VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION|OPT_P_EXPLICIT_NOTIFY);
if (p[1])
{
options->ce.explicit_exit_notification = positive_atoi (p[1]);
@@ -5144,16 +5138,17 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->route_script, "route-up");
- options->route_script = p[1];
+ set_user_script (options, &options->route_script, p[1], "route-up");
}
else if (streq (p[0], "route-pre-down") && p[1])
{
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->route_predown_script, "route-pre-down");
- options->route_predown_script = p[1];
+ set_user_script (options,
+ &options->route_predown_script,
+ p[1],
+ "route-pre-down");
}
else if (streq (p[0], "route-noexec"))
{
@@ -5520,32 +5515,33 @@ add_option (struct options *options,
msg (msglevel, "--auth-user-pass-verify requires a second parameter ('via-env' or 'via-file')");
goto err;
}
- warn_multiple_script (options->auth_user_pass_verify_script, "auth-user-pass-verify");
- options->auth_user_pass_verify_script = p[1];
+ set_user_script (options,
+ &options->auth_user_pass_verify_script,
+ p[1], "auth-user-pass-verify");
}
else if (streq (p[0], "client-connect") && p[1])
{
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->client_connect_script, "client-connect");
- options->client_connect_script = p[1];
+ set_user_script (options, &options->client_connect_script,
+ p[1], "client-connect");
}
else if (streq (p[0], "client-disconnect") && p[1])
{
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->client_disconnect_script, "client-disconnect");
- options->client_disconnect_script = p[1];
+ set_user_script (options, &options->client_disconnect_script,
+ p[1], "client-disconnect");
}
else if (streq (p[0], "learn-address") && p[1])
{
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->learn_address_script, "learn-address");
- options->learn_address_script = p[1];
+ set_user_script (options, &options->learn_address_script,
+ p[1], "learn-address");
}
else if (streq (p[0], "tmp-dir") && p[1])
{
@@ -6481,8 +6477,9 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- warn_multiple_script (options->tls_verify, "tls-verify");
- options->tls_verify = string_substitute (p[1], ',', ' ', &options->gc);
+ set_user_script (options, &options->tls_verify,
+ string_substitute (p[1], ',', ' ', &options->gc),
+ "tls-verify");
}
#ifndef ENABLE_CRYPTO_POLARSSL
else if (streq (p[0], "tls-export-cert") && p[1])
diff --git a/openvpn/src/openvpn/options.h b/openvpn/src/openvpn/options.h
index 56359357..cc92da32 100644
--- a/openvpn/src/openvpn/options.h
+++ b/openvpn/src/openvpn/options.h
@@ -289,6 +289,7 @@ struct options
const char *writepid;
const char *up_script;
const char *down_script;
+ bool user_script_used;
bool down_pre;
bool up_delay;
bool up_restart;
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c
index 548ea72c..115caaac 100644
--- a/openvpn/src/openvpn/socket.c
+++ b/openvpn/src/openvpn/socket.c
@@ -2819,6 +2819,7 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
struct iovec iov;
struct msghdr mesg;
struct cmsghdr *cmsg;
+ union openvpn_pktinfo opi;
iov.iov_base = BPTR (buf);
iov.iov_len = BLEN (buf);
@@ -2828,11 +2829,10 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
{
case AF_INET:
{
- struct openvpn_in4_pktinfo msgpi4;
mesg.msg_name = &to->dest.addr.sa;
mesg.msg_namelen = sizeof (struct sockaddr_in);
- mesg.msg_control = &msgpi4;
- mesg.msg_controllen = sizeof msgpi4;
+ mesg.msg_control = &opi;
+ mesg.msg_controllen = sizeof (struct openvpn_in4_pktinfo);
mesg.msg_flags = 0;
cmsg = CMSG_FIRSTHDR (&mesg);
cmsg->cmsg_len = sizeof (struct openvpn_in4_pktinfo);
@@ -2857,12 +2857,11 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
}
case AF_INET6:
{
- struct openvpn_in6_pktinfo msgpi6;
struct in6_pktinfo *pkti6;
mesg.msg_name = &to->dest.addr.sa;
mesg.msg_namelen = sizeof (struct sockaddr_in6);
- mesg.msg_control = &msgpi6;
- mesg.msg_controllen = sizeof msgpi6;
+ mesg.msg_control = &opi;
+ mesg.msg_controllen = sizeof (struct openvpn_in6_pktinfo);
mesg.msg_flags = 0;
cmsg = CMSG_FIRSTHDR (&mesg);
cmsg->cmsg_len = sizeof (struct openvpn_in6_pktinfo);
diff --git a/openvpn/src/openvpn/ssl.c b/openvpn/src/openvpn/ssl.c
index 9ca409f1..f2b04488 100644
--- a/openvpn/src/openvpn/ssl.c
+++ b/openvpn/src/openvpn/ssl.c
@@ -67,6 +67,7 @@
#include "ssl.h"
#include "ssl_verify.h"
#include "ssl_backend.h"
+#include "multi.h"
#include "memdbg.h"
@@ -1106,6 +1107,8 @@ tls_multi_free (struct tls_multi *multi, bool clear)
#ifdef MANAGEMENT_DEF_AUTH
man_def_auth_set_client_reason(multi, NULL);
+#endif
+#if P2MP_SERVER
free (multi->peer_info);
#endif
@@ -1775,7 +1778,7 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
bool ret = false;
#ifdef ENABLE_PUSH_PEER_INFO
- if (session->opt->push_peer_info) /* write peer info */
+ if (session->opt->push_peer_info_detail > 0)
{
struct env_set *es = session->opt->es;
struct env_item *e;
@@ -1803,25 +1806,28 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
buf_printf (&out, "IV_PLAT=win\n");
#endif
- /* push mac addr */
- {
- struct route_gateway_info rgi;
- get_default_gateway (&rgi);
- if (rgi.flags & RGI_HWADDR_DEFINED)
- buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc));
- }
-
/* push compression status */
#ifdef USE_COMP
comp_generate_peer_info_string(&session->opt->comp_options, &out);
#endif
- /* push env vars that begin with UV_ */
+ if (session->opt->push_peer_info_detail >= 2)
+ {
+ /* push mac addr */
+ struct route_gateway_info rgi;
+ get_default_gateway (&rgi);
+ if (rgi.flags & RGI_HWADDR_DEFINED)
+ buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc));
+ }
+
+ /* push env vars that begin with UV_ and IV_OPENVPN_GUI_VERSION*/
for (e=es->list; e != NULL; e=e->next)
{
if (e->string)
{
- if (!strncmp(e->string, "UV_", 3) && buf_safe(&out, strlen(e->string)+1))
+ if (((strncmp(e->string, "UV_", 3)==0 && session->opt->push_peer_info_detail >= 2)
+ || (strncmp(e->string,"IV_OPENVPN_GUI_VERSION=",sizeof("IV_OPENVPN_GUI_VERSION=")-1)==0))
+ && buf_safe(&out, strlen(e->string)+1))
buf_printf (&out, "%s\n", e->string);
}
}
@@ -1996,6 +2002,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
struct gc_arena gc = gc_new ();
char *options;
+ struct user_pass *up;
/* allocate temporary objects */
ALLOC_ARRAY_CLEAR_GC (options, char, TLS_OPTIONS_LEN, &gc);
@@ -2031,15 +2038,25 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
ks->authenticated = false;
+ /* always extract username + password fields from buf, even if not
+ * authenticating for it, because otherwise we can't get at the
+ * peer_info data which follows behind
+ */
+ ALLOC_OBJ_CLEAR_GC (up, struct user_pass, &gc);
+ username_status = read_string (buf, up->username, USER_PASS_LEN);
+ password_status = read_string (buf, up->password, USER_PASS_LEN);
+
+#if P2MP_SERVER
+ /* get peer info from control channel */
+ free (multi->peer_info);
+ multi->peer_info = read_string_alloc (buf);
+ if ( multi->peer_info )
+ multi_output_peer_info_env (session->opt->es, multi->peer_info);
+#endif
+
if (verify_user_pass_enabled(session))
{
/* Perform username/password authentication */
- struct user_pass *up;
-
- ALLOC_OBJ_CLEAR_GC (up, struct user_pass, &gc);
- username_status = read_string (buf, up->username, USER_PASS_LEN);
- password_status = read_string (buf, up->password, USER_PASS_LEN);
-
if (!username_status || !password_status)
{
CLEAR (*up);
@@ -2050,14 +2067,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
}
}
-#ifdef MANAGEMENT_DEF_AUTH
- /* get peer info from control channel */
- free (multi->peer_info);
- multi->peer_info = read_string_alloc (buf);
-#endif
-
verify_user_pass(up, multi, session);
- CLEAR (*up);
}
else
{
@@ -2071,6 +2081,9 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
ks->authenticated = true;
}
+ /* clear username and password from memory */
+ CLEAR (*up);
+
/* Perform final authentication checks */
if (ks->authenticated)
{
diff --git a/openvpn/src/openvpn/ssl_common.h b/openvpn/src/openvpn/ssl_common.h
index 47dbefbe..7e52f9a2 100644
--- a/openvpn/src/openvpn/ssl_common.h
+++ b/openvpn/src/openvpn/ssl_common.h
@@ -233,7 +233,7 @@ struct tls_options
bool disable_occ;
#endif
#ifdef ENABLE_PUSH_PEER_INFO
- bool push_peer_info;
+ int push_peer_info_detail;
#endif
int transition_window;
int handshake_window;
@@ -481,14 +481,16 @@ struct tls_multi
*/
char *client_reason;
+ /* Time of last call to tls_authentication_status */
+ time_t tas_last;
+#endif
+
+#if P2MP_SERVER
/*
* A multi-line string of general-purpose info received from peer
* over control channel.
*/
char *peer_info;
-
- /* Time of last call to tls_authentication_status */
- time_t tas_last;
#endif
/*