]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Added server-side --auth-user-pass-optional directive, to allow
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Tue, 28 Oct 2008 20:01:05 +0000 (20:01 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Tue, 28 Oct 2008 20:01:05 +0000 (20:01 +0000)
connections by clients that do not specify a username/password, when a
user-defined authentication script/module is in place (via
--auth-user-pass-verify, --management-client-auth, or a plugin module).

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3461 e7ae566f-a301-0410-adde-c780ea21d3b5

init.c
openvpn.8
options.c
options.h
ssl.c
ssl.h

diff --git a/init.c b/init.c
index fc37ac04170b9d45b973dbb76e80792cafaa2e45..519dc8bcbe10eac1520f1863c1c0f9f81c1de666 100644 (file)
--- a/init.c
+++ b/init.c
@@ -1756,7 +1756,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
   to.auth_user_pass_verify_script = options->auth_user_pass_verify_script;
   to.auth_user_pass_verify_script_via_file = options->auth_user_pass_verify_script_via_file;
   to.tmp_dir = options->tmp_dir;
-  to.username_as_common_name = options->username_as_common_name;
+  to.ssl_flags = options->ssl_flags;
   if (options->ccd_exclusive)
     to.client_config_dir_exclusive = options->client_config_dir;
 #endif
index 4adabbd2c834161723d1eab804b28bc67556aad2..1b81077054c8e199d5387d6a9bc9954561cc1463 100644 (file)
--- a/openvpn.8
+++ b/openvpn.8
@@ -102,6 +102,7 @@ openvpn \- secure IP tunnel daemon.
 [\ \fB\-\-askpass\fR\ \fI[file]\fR\ ]
 [\ \fB\-\-auth\-nocache\fR\ ]
 [\ \fB\-\-auth\-retry\fR\ \fItype\fR\ ]
+[\ \fB\-\-auth\-user\-pass\-optional\fR\ ]
 [\ \fB\-\-auth\-user\-pass\-verify\fR\ \fIscript\fR\ ]
 [\ \fB\-\-auth\-user\-pass\fR\ \fIup\fR\ ]
 [\ \fB\-\-auth\fR\ \fIalg\fR\ ]
@@ -3250,6 +3251,24 @@ For a sample script that performs PAM authentication, see
 in the OpenVPN source distribution.
 .\"*********************************************************
 .TP
+.B --auth-user-pass-optional
+Allow connections by clients that do not specify a username/password.
+Normally, when
+.B --auth-user-pass-verify
+or
+.B --management-client-auth
+is specified (or an authentication plugin module), the
+OpenVPN server daemon will require connecting clients to specify a
+username and password.  This option makes the submission of a username/password
+by clients optional, passing the responsibility to the user-defined authentication
+module/script to accept or deny the client based on other factors
+(such as the setting of X509 certificate fields).  When this option is used,
+and a connecting client does not submit a username/password, the user-defined
+authentication module/script will see the username and password as being set
+to empty strings ("").  The authentication module/script MUST have logic
+to detect this condition and respond accordingly.
+.\"*********************************************************
+.TP
 .B --client-cert-not-required
 Don't require client certificate, client will authenticate
 using username/password only.  Be aware that using this directive
index f7d8a93f9fd2f232a9bead0b7254525b7e41e03c..05a6960c3f2f370123cd1c194ac951bf3ea8d207 100644 (file)
--- a/options.c
+++ b/options.c
@@ -381,6 +381,8 @@ static const char usage_message[] =
   "                  run script cmd to verify.  If method='via-env', pass\n"
   "                  user/pass via environment, if method='via-file', pass\n"
   "                  user/pass via temporary file.\n"
+  "--auth-user-pass-optional : Allow connections by clients that don't\n"
+  "                  specify a username/password.\n"
   "--client-to-client : Internally route client-to-client traffic.\n"
   "--duplicate-cn  : Allow multiple clients with the same common name to\n"
   "                  concurrently connect.\n"
@@ -965,10 +967,9 @@ show_p2mp_parms (const struct options *o)
   SHOW_INT (cf_per);
   SHOW_INT (max_clients);
   SHOW_INT (max_routes_per_client);
-  SHOW_BOOL (client_cert_not_required);
-  SHOW_BOOL (username_as_common_name)
   SHOW_STR (auth_user_pass_verify_script);
   SHOW_BOOL (auth_user_pass_verify_script_via_file);
+  SHOW_INT (ssl_flags);
 #if PORT_SHARE
   SHOW_STR (port_share_host);
   SHOW_INT (port_share_port);
@@ -1702,10 +1703,12 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
                             || PLUGIN_OPTION_LIST (options)
                             || MAN_CLIENT_AUTH_ENABLED (options));
          const char *postfix = "must be used with --management-client-auth, an --auth-user-pass-verify script, or plugin";
-         if (options->client_cert_not_required && !ccnr)
+         if ((options->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED) && !ccnr)
            msg (M_USAGE, "--client-cert-not-required %s", postfix);
-         if (options->username_as_common_name && !ccnr)
+         if ((options->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && !ccnr)
            msg (M_USAGE, "--username-as-common-name %s", postfix);
+         if ((options->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) && !ccnr)
+           msg (M_USAGE, "--auth-user-pass-optional %s", postfix);
        }
     }
   else
@@ -1735,10 +1738,12 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
        msg (M_USAGE, "--duplicate-cn requires --mode server");
       if (options->cf_max || options->cf_per)
        msg (M_USAGE, "--connect-freq requires --mode server");
-      if (options->client_cert_not_required)
+      if (options->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)
        msg (M_USAGE, "--client-cert-not-required requires --mode server");
-      if (options->username_as_common_name)
+      if (options->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME)
        msg (M_USAGE, "--username-as-common-name requires --mode server");
+      if (options->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL)
+       msg (M_USAGE, "--auth-user-pass-optional requires --mode server");
       if (options->auth_user_pass_verify_script)
        msg (M_USAGE, "--auth-user-pass-verify requires --mode server");
 #if PORT_SHARE
@@ -4559,12 +4564,17 @@ add_option (struct options *options,
   else if (streq (p[0], "client-cert-not-required"))
     {
       VERIFY_PERMISSION (OPT_P_GENERAL);
-      options->client_cert_not_required = true;
+      options->ssl_flags |= SSLF_CLIENT_CERT_NOT_REQUIRED;
     }
   else if (streq (p[0], "username-as-common-name"))
     {
       VERIFY_PERMISSION (OPT_P_GENERAL);
-      options->username_as_common_name = true;
+      options->ssl_flags |= SSLF_USERNAME_AS_COMMON_NAME;
+    }
+  else if (streq (p[0], "auth-user-pass-optional"))
+    {
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      options->ssl_flags |= SSLF_AUTH_USER_PASS_OPTIONAL;
     }
   else if (streq (p[0], "auth-user-pass-verify") && p[1])
     {
index 14d6bf5e6fcc3b56556d8186f154f54664ff0956..1770bc8358c82e5c45212bf784c72b0a98f9ad06 100644 (file)
--- a/options.h
+++ b/options.h
@@ -385,10 +385,9 @@ struct options
   int max_clients;
   int max_routes_per_client;
 
-  bool client_cert_not_required;
-  bool username_as_common_name;
   const char *auth_user_pass_verify_script;
   bool auth_user_pass_verify_script_via_file;
+  unsigned int ssl_flags; /* set to SSLF_x flags from ssl.h */
 #if PORT_SHARE
   char *port_share_host;
   int port_share_port;
diff --git a/ssl.c b/ssl.c
index c45674d0c006e9ebcb0b93b8b7bf4fd82b300c20..ebd03a61e3e2bfcb061f82334fa89184e58879ec 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -1555,7 +1555,7 @@ init_ssl (const struct options *options)
 
   /* Require peer certificate verification */
 #if P2MP_SERVER
-  if (options->client_cert_not_required)
+  if (options->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)
     {
       msg (M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION --client-cert-not-required may accept clients which do not present a certificate");
     }
@@ -2958,7 +2958,7 @@ verify_user_pass_script (struct tls_session *session, const struct user_pass *up
   bool ret = false;
 
   /* Is username defined? */
-  if (strlen (up->username))
+  if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen (up->username))
     {
       /* Set environmental variables prior to calling script */
       setenv_str (session->opt->es, "script_type", "user-pass-verify");
@@ -3025,7 +3025,7 @@ verify_user_pass_plugin (struct tls_session *session, const struct user_pass *up
   int retval = OPENVPN_PLUGIN_FUNC_ERROR;
 
   /* Is username defined? */
-  if (strlen (up->username))
+  if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen (up->username))
     {
       /* set username/password in private env space */
       setenv_str (session->opt->es, "username", raw_username);
@@ -3077,7 +3077,7 @@ verify_user_pass_management (struct tls_session *session, const struct user_pass
   int retval = KMDA_ERROR;
 
   /* Is username defined? */
-  if (strlen (up->username))
+  if ((session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL) || strlen (up->username))
     {
       /* set username/password in private env space */
       setenv_str (session->opt->es, "username", raw_username);
@@ -3336,9 +3336,12 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
       if (!read_string (buf, up->username, USER_PASS_LEN)
          || !read_string (buf, up->password, USER_PASS_LEN))
        {
-         msg (D_TLS_ERRORS, "TLS Error: Auth Username/Password was not provided by peer");
          CLEAR (*up);
-         goto error;
+         if (!(session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL))
+           {
+             msg (D_TLS_ERRORS, "TLS Error: Auth Username/Password was not provided by peer");
+             goto error;
+           }
        }
 
       /* preserve raw username before string_mod remapping, for plugins */
@@ -3361,7 +3364,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
        s2 = verify_user_pass_script (session, up);
 
       /* check sizing of username if it will become our common name */
-      if (session->opt->username_as_common_name && strlen (up->username) >= TLS_CN_LEN)
+      if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_CN_LEN)
        {
          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);
          s1 = OPENVPN_PLUGIN_FUNC_ERROR;
@@ -3384,7 +3387,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
            ks->auth_deferred = true;
 #endif
            
-         if (session->opt->username_as_common_name)
+         if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME))
            set_common_name (session, up->username);
          msg (D_HANDSHAKE, "TLS: Username/Password authentication %s for username '%s' %s",
 #ifdef ENABLE_DEF_AUTH
@@ -3393,7 +3396,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
               "succeeded",
 #endif
               up->username,
-              session->opt->username_as_common_name ? "[CN SET]" : "");
+              (session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) ? "[CN SET]" : "");
        }
       else
        {
diff --git a/ssl.h b/ssl.h
index f3bae329be8cfff2851c11a2751f707b11da852e..6921cf377259f6322f05cb124a346a321d1c21d3 100644 (file)
--- a/ssl.h
+++ b/ssl.h
@@ -456,7 +456,6 @@ struct tls_options
   const char *auth_user_pass_verify_script;
   bool auth_user_pass_verify_script_via_file;
   const char *tmp_dir;
-  bool username_as_common_name;
 
   /* use the client-config-dir as a positive authenticator */
   const char *client_config_dir_exclusive;
@@ -465,6 +464,12 @@ struct tls_options
   struct env_set *es;
   const struct plugin_list *plugins;
 
+  /* configuration file boolean options */
+# define SSLF_CLIENT_CERT_NOT_REQUIRED (1<<0)
+# define SSLF_USERNAME_AS_COMMON_NAME  (1<<1)
+# define SSLF_AUTH_USER_PASS_OPTIONAL  (1<<2)
+  unsigned int ssl_flags;
+
 #ifdef MANAGEMENT_DEF_AUTH
   struct man_def_auth_context *mda_context;
 #endif