diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2013-08-18 17:53:34 +0200 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2013-08-18 17:53:34 +0200 | 
| commit | 3a94f66677fe7b5ae3ecd5743462318d322010e4 (patch) | |
| tree | 2a0a74d9a5ef3b4b028d9f76574f27ec8325ebfc /openvpn/src | |
| parent | 94c32221defb9ce513505148f5ae3a037f6a1adc (diff) | |
Rebase OpenVPN to -master
--HG--
extra : rebase_source : 37025b323cf5e6497cbc92744a32b0b69e397af8
Diffstat (limited to 'openvpn/src')
| -rw-r--r-- | openvpn/src/openvpn/init.c | 10 | ||||
| -rw-r--r-- | openvpn/src/openvpn/misc.c | 56 | ||||
| -rw-r--r-- | openvpn/src/openvpn/misc.h | 7 | ||||
| -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 | 60 | ||||
| -rw-r--r-- | openvpn/src/openvpn/options.h | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.c | 1 | ||||
| -rw-r--r-- | openvpn/src/openvpn/socket.h | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl.c | 2 | ||||
| -rw-r--r-- | openvpn/src/openvpn/ssl_openssl.c | 27 | ||||
| -rw-r--r-- | openvpn/src/openvpn/win32.c | 6 | 
12 files changed, 156 insertions, 72 deletions
| diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c index c288e924..8cd136d5 100644 --- a/openvpn/src/openvpn/init.c +++ b/openvpn/src/openvpn/init.c @@ -174,10 +174,12 @@ ce_management_query_proxy (struct context *c)    if (management)      {        gc = gc_new (); -      struct buffer out = alloc_buf_gc (256, &gc); -      buf_printf (&out, ">PROXY:%u,%s,%s", (l ? l->current : 0) + 1, -                  (proto_is_udp (ce->proto) ? "UDP" : "TCP"), np (ce->remote)); -      management_notify_generic (management, BSTR (&out)); +      { +	struct buffer out = alloc_buf_gc (256, &gc); +	buf_printf (&out, ">PROXY:%u,%s,%s", (l ? l->current : 0) + 1, +		    (proto_is_udp (ce->proto) ? "UDP" : "TCP"), np (ce->remote)); +	management_notify_generic (management, BSTR (&out)); +      }        ce->flags |= CE_MAN_QUERY_PROXY;        while (ce->flags & CE_MAN_QUERY_PROXY)          { diff --git a/openvpn/src/openvpn/misc.c b/openvpn/src/openvpn/misc.c index 1120adc4..4688444e 100644 --- a/openvpn/src/openvpn/misc.c +++ b/openvpn/src/openvpn/misc.c @@ -2063,3 +2063,59 @@ compat_flag (unsigned int flag)    return (compat_flags & (flag >> 1));  } + +#if P2MP_SERVER + +/* 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 +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"); +    } +} + +#endif /* P2MP_SERVER */ diff --git a/openvpn/src/openvpn/misc.h b/openvpn/src/openvpn/misc.h index 183898e3..41748bd8 100644 --- a/openvpn/src/openvpn/misc.h +++ b/openvpn/src/openvpn/misc.h @@ -369,4 +369,11 @@ void argv_printf_cat (struct argv *a, const char *format, ...)  #define COMPAT_NO_NAME_REMAPPING  (1<<2)  /** compat flag: --compat-names without char remapping */  bool compat_flag (unsigned int flag); +#if P2MP_SERVER +/* 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); +void output_peer_info_env (struct env_set *es, const char * peer_info); +#endif /* P2MP_SERVER */ +  #endif diff --git a/openvpn/src/openvpn/multi.c b/openvpn/src/openvpn/multi.c index 50f398dd..f016b149 100644 --- a/openvpn/src/openvpn/multi.c +++ b/openvpn/src/openvpn/multi.c @@ -1562,58 +1562,6 @@ 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 7b97b0d2..fc2ffb24 100644 --- a/openvpn/src/openvpn/multi.h +++ b/openvpn/src/openvpn/multi.h @@ -312,9 +312,6 @@ 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 48065f99..8b98b45f 100644 --- a/openvpn/src/openvpn/options.c +++ b/openvpn/src/openvpn/options.c @@ -250,6 +250,8 @@ static const char usage_message[] =    "--setenv name value : Set a custom environmental variable to pass to script.\n"    "--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n"    "                  directives for future OpenVPN versions to be ignored.\n" +  "--ignore-unkown-option opt1 opt2 ...: Relax config file syntax. Allow\n" +  "                  these options to be ignored when unknown\n"    "--script-security level: Where level can be:\n"    "                  0 -- strictly no calling of external programs\n"    "                  1 -- (default) only call built-ins such as ifconfig\n" @@ -4371,6 +4373,48 @@ add_option (struct options *options,  	  uninit_options (&sub);  	}      } +  else if (streq (p[0], "ignore-unknown-option") && p[1]) +    { +      int i; +      int j; +      int numignored=0; +      const char **ignore; + +      VERIFY_PERMISSION (OPT_P_GENERAL); +      /* Find out how many options to be ignored */ +      for (i=1;p[i];i++) +        numignored++; + +      /* add number of options already ignored */ +      for (i=0;options->ignore_unknown_option && +             options->ignore_unknown_option[i]; i++) +        numignored++; + +      /* Allocate array */ +      ALLOC_ARRAY_GC (ignore, const char*, numignored+1, &options->gc); +      for (i=0;options->ignore_unknown_option && +             options->ignore_unknown_option[i]; i++) +        ignore[i]=options->ignore_unknown_option[i]; + +      options->ignore_unknown_option=ignore; + +      for (j=1;p[j];j++) +        { +          /* Allow the user to specify ignore-unknown-option --opt too */ +          if (p[j][0]=='-' && p[j][1]=='-') +            options->ignore_unknown_option[i] = (p[j]+2); +          else +            options->ignore_unknown_option[i] = p[j]; +          i++; +        } + +      options->ignore_unknown_option[i] = NULL; +    } +  else if (streq (p[0], "remote-ip-hint") && p[1]) +    { +      VERIFY_PERMISSION (OPT_P_GENERAL); +      options->remote_ip_hint = p[1]; +    }  #if HTTP_PROXY_OVERRIDE    else if (streq (p[0], "http-proxy-override") && p[1] && p[2])      { @@ -6815,10 +6859,22 @@ add_option (struct options *options,  #endif    else      { +      int i; +      int msglevel= msglevel_fc; +      /* Check if an option is in --ignore-unknown-option and +         set warning level to non fatal */ +      for(i=0; options->ignore_unknown_option && options->ignore_unknown_option[i]; i++) +        { +          if (streq(p[0], options->ignore_unknown_option[i])) +            { +              msglevel = M_WARN; +              break; +            } +        }        if (file) -	msg (msglevel_fc, "Unrecognized option or missing parameter(s) in %s:%d: %s (%s)", file, line, p[0], PACKAGE_VERSION); +	msg (msglevel, "Unrecognized option or missing parameter(s) in %s:%d: %s (%s)", file, line, p[0], PACKAGE_VERSION);        else -	msg (msglevel_fc, "Unrecognized option or missing parameter(s): --%s (%s)", p[0], PACKAGE_VERSION); +	msg (msglevel, "Unrecognized option or missing parameter(s): --%s (%s)", p[0], PACKAGE_VERSION);      }   err:    gc_free (&gc); diff --git a/openvpn/src/openvpn/options.h b/openvpn/src/openvpn/options.h index cc92da32..86760bbf 100644 --- a/openvpn/src/openvpn/options.h +++ b/openvpn/src/openvpn/options.h @@ -186,6 +186,8 @@ struct options    /* enable forward compatibility for post-2.1 features */    bool forward_compatible; +  /* list of options that should be ignored even if unkown */ +  const char **  ignore_unknown_option;    /* persist parms */    bool persist_config; diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 115caaac..ee44ad3c 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -1191,7 +1191,6 @@ resolve_remote (struct link_socket *sock,  	      unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);  	      int retry = 0;  	      int status = -1; -                              if (proto_is_dgram(sock->info.proto))                    flags |= GETADDR_DATAGRAM; diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h index 2b134486..d077a153 100644 --- a/openvpn/src/openvpn/socket.h +++ b/openvpn/src/openvpn/socket.h @@ -1109,7 +1109,7 @@ static inline void  link_socket_set_tos (struct link_socket *ls)  {    if (ls && ls->ptos_defined) -    setsockopt (ls->sd, IPPROTO_IP, IP_TOS, &ls->ptos, sizeof (ls->ptos)); +    setsockopt (ls->sd, IPPROTO_IP, IP_TOS, (const void *)&ls->ptos, sizeof (ls->ptos));  }  #endif diff --git a/openvpn/src/openvpn/ssl.c b/openvpn/src/openvpn/ssl.c index f78cca88..60f5f67f 100644 --- a/openvpn/src/openvpn/ssl.c +++ b/openvpn/src/openvpn/ssl.c @@ -2065,7 +2065,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi    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); +      output_peer_info_env (session->opt->es, multi->peer_info);  #endif    if (verify_user_pass_enabled(session)) diff --git a/openvpn/src/openvpn/ssl_openssl.c b/openvpn/src/openvpn/ssl_openssl.c index 12c725d9..f64177a8 100644 --- a/openvpn/src/openvpn/ssl_openssl.c +++ b/openvpn/src/openvpn/ssl_openssl.c @@ -242,8 +242,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)    const tls_cipher_name_pair *cipher_pair; -  const size_t openssl_ciphers_size = 4096; -  char openssl_ciphers[openssl_ciphers_size]; +  char openssl_ciphers[4096];    size_t openssl_ciphers_len = 0;    openssl_ciphers[0] = '\0'; @@ -282,8 +281,8 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)  	}        // Make sure new cipher name fits in cipher string -      if (((openssl_ciphers_size-1) - openssl_ciphers_len) < current_cipher_len) { -	msg(M_SSLERR, "Failed to set restricted TLS cipher list, too long (>%zu).", openssl_ciphers_size-1); +      if (((sizeof(openssl_ciphers)-1) - openssl_ciphers_len) < current_cipher_len) { +	msg(M_SSLERR, "Failed to set restricted TLS cipher list, too long (>%d).", (int)sizeof(openssl_ciphers)-1);        }        // Concatenate cipher name to OpenSSL cipher string @@ -413,16 +412,34 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,    /* Set Certificate Verification chain */    if (load_ca_file)     { +     /* Add CAs from PKCS12 to the cert store and mark them as trusted.  +      * They're also used to fill in the chain of intermediate certs as +      * necessary. +      */       if (ca && sk_X509_num(ca))        {  	for (i = 0; i < sk_X509_num(ca); i++)  	  { -	      if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) +	    if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i)))  	      msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)");  	    if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i)))  	      msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)");  	  }        } +   } else { +     /* If trusted CA certs were loaded from a PEM file, and we ignore the +      * ones in PKCS12, do load PKCS12-provided certs to the client extra +      * certs chain just in case they include intermediate CAs needed to +      * prove my identity to the other end. This does not make them trusted. +      */ +     if (ca && sk_X509_num(ca)) +      { +	for (i = 0; i < sk_X509_num(ca); i++) +	  { +	    if (!SSL_CTX_add_extra_chain_cert(ctx->ctx,sk_X509_value(ca, i))) +	      msg (M_SSLERR, "Cannot add extra certificate to chain (SSL_CTX_add_extra_chain_cert)"); +	  } +      }     }    return 0;  } diff --git a/openvpn/src/openvpn/win32.c b/openvpn/src/openvpn/win32.c index 178e2c35..022eec5c 100644 --- a/openvpn/src/openvpn/win32.c +++ b/openvpn/src/openvpn/win32.c @@ -870,6 +870,9 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i            WCHAR *cl = wide_cmd_line (a, &gc);            WCHAR *cmd = wide_string (a->argv[0], &gc); +          /* this allows console programs to run, and is ignored otherwise */ +          DWORD proc_flags = CREATE_NO_WINDOW; +            CLEAR (start_info);            CLEAR (proc_info); @@ -879,9 +882,6 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i            start_info.dwFlags = STARTF_USESHOWWINDOW;            start_info.wShowWindow = SW_HIDE; -          /* this allows console programs to run, and is ignored otherwise */ -          DWORD proc_flags = CREATE_NO_WINDOW; -            if (CreateProcessW (cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info))              {                DWORD exit_status = 0; | 
