aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--init.c2
-rw-r--r--openvpn.819
-rw-r--r--options.c26
-rw-r--r--options.h3
-rw-r--r--ssl.c21
-rw-r--r--ssl.h7
6 files changed, 57 insertions, 21 deletions
diff --git a/init.c b/init.c
index fc37ac0..519dc8b 100644
--- 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
diff --git a/openvpn.8 b/openvpn.8
index 4adabbd..1b81077 100644
--- 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
diff --git a/options.c b/options.c
index f7d8a93..05a6960 100644
--- 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])
{
diff --git a/options.h b/options.h
index 14d6bf5..1770bc8 100644
--- 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 c45674d..ebd03a6 100644
--- 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 f3bae32..6921cf3 100644
--- 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