diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2013-05-31 16:55:52 +0200 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2013-05-31 16:55:52 +0200 | 
| commit | 59645fe5e45de8cf87924a9ad83df4e283765043 (patch) | |
| tree | 9a5117698e60455e7c917b851ac5ff26ed273442 /openvpn/src | |
| parent | d1f3e24621dcd5404fd9af7d9214c5ff2a07d438 (diff) | |
Update OpenVPN to current -master
--HG--
extra : rebase_source : 7d9f6d9e6ac62a8843f925e33c48a671ff153f91
Diffstat (limited to 'openvpn/src')
| -rw-r--r-- | openvpn/src/openvpn/common.h | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/init.c | 23 | ||||
| -rw-r--r-- | openvpn/src/openvpn/manage.c | 30 | ||||
| -rw-r--r-- | openvpn/src/openvpn/multi.c | 52 | ||||
| -rw-r--r-- | openvpn/src/openvpn/multi.h | 3 | ||||
| -rw-r--r-- | openvpn/src/openvpn/options.c | 95 | ||||
| -rw-r--r-- | openvpn/src/openvpn/options.h | 1 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.c | 11 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl.c | 61 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_common.h | 10 | 
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    /* | 
