to detect this condition and respond accordingly.
.\"*********************************************************
.TP
-.B \-\-client\-cert\-not\-required
+.B \-\-client\-cert\-not\-required (DEPRECATED)
Don't require client certificate, client will authenticate
using username/password only. Be aware that using this directive
is less secure than requiring certificates from all clients.
+
+.B Please note:
+This option is now deprecated and will be removed in OpenVPN v2.5.
+It is replaced by
+.B \-\-verify\-client\-cert
+which allows for more flexibility. The option
+.B \-\-verify\-client\-cert none
+is functionally equivalent to
+.B \-\-client\-cert\-not\-required
+.
+
+.\"*********************************************************
+.TP
+.B \-\-verify\-client\-cert none|optional|require
+Specify whether the client is required to supply a valid certificate.
+
+Possible options are
+
+.B none
+: a client certificate is not required. the client need to authenticate
+using username/password only. Be aware that using this directive
+is less secure than requiring certificates from all clients.
+
If you use this directive, the
entire responsibility of authentication will rest on your
.B \-\-auth\-user\-pass\-verify
script, so keep in mind that bugs in your script
could potentially compromise the security of your VPN.
-If you don't use this directive, but you also specify an
+.B \-\-verify\-client\-cert none
+is functionally equivalent to
+.B \-\-client\-cert\-not\-required.
+
+.B optional
+: a client may present a certificate but it is not required to do so.
+When using this directive, you should also use a
+.B \-\-auth\-user\-pass\-verify
+script to ensure that clients are authenticated using a
+certificate, a username and password, or possibly even both.
+
+Again, the entire responsibility of authentication will rest on your
+.B \-\-auth\-user\-pass\-verify
+script, so keep in mind that bugs in your script
+could potentially compromise the security of your VPN.
+
+.B require
+: this is the default option. A client is required to present a
+certificate, otherwise VPN access is refused.
+
+If you don't use this directive (or use
+.B \-\-verify\-client\-cert require
+) but you also specify an
.B \-\-auth\-user\-pass\-verify
script, then OpenVPN will perform double authentication. The
client certificate verification AND the
" Only valid in a client-specific config file.\n"
"--client-cert-not-required : Don't require client certificate, client\n"
" will authenticate using username/password.\n"
+ "--verify-client-cert [none|optional|require] : perform no, optional or\n"
+ " mandatory client certificate verification.\n"
+ " Default is to require the client to supply a certificate.\n"
"--username-as-common-name : For auth-user-pass authentication, use\n"
" the authenticated username as the common name,\n"
" rather than the common name from the client cert.\n"
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->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)
- msg (M_USAGE, "--client-cert-not-required requires --mode server");
+ if (options->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED || options->ssl_flags & SSLF_CLIENT_CERT_OPTIONAL)
+ msg (M_USAGE, "--client-cert-not-required and --verify-client-cert require --mode server");
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)
{
VERIFY_PERMISSION (OPT_P_GENERAL);
options->ssl_flags |= SSLF_CLIENT_CERT_NOT_REQUIRED;
+ msg (M_WARN, "DEPRECATED OPTION: --client-cert-not-required, use --verify-client-cert instead");
+ }
+ else if (streq (p[0], "verify-client-cert") && !p[2])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+
+ /* Reset any existing flags */
+ options->ssl_flags &= ~SSLF_CLIENT_CERT_OPTIONAL;
+ options->ssl_flags &= ~SSLF_CLIENT_CERT_NOT_REQUIRED;
+ if (p[1])
+ {
+ if (streq (p[1], "none"))
+ options->ssl_flags |= SSLF_CLIENT_CERT_NOT_REQUIRED;
+ else if (streq (p[1], "optional"))
+ options->ssl_flags |= SSLF_CLIENT_CERT_OPTIONAL;
+ else if (!streq (p[1], "require"))
+ {
+ msg (msglevel, "parameter to --verify-client-cert must be 'none', 'optional' or 'require'");
+ goto err;
+ }
+ }
}
else if (streq (p[0], "username-as-common-name") && !p[1])
{
/* configuration file SSL-related boolean and low-permutation 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)
+# define SSLF_CLIENT_CERT_OPTIONAL (1<<1)
+# define SSLF_USERNAME_AS_COMMON_NAME (1<<2)
+# define SSLF_AUTH_USER_PASS_OPTIONAL (1<<3)
# define SSLF_OPT_VERIFY (1<<4)
# define SSLF_CRL_VERIFY_DIR (1<<5)
# define SSLF_TLS_VERSION_MIN_SHIFT 6
{
ASSERT(NULL != ctx);
+ /* default certificate verification flags */
+ int flags = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+
/* process SSL options including minimum TLS version we will accept from peer */
{
long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
if (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");
+ "--client-cert-not-required and --verify-client-cert none "
+ "may accept clients which do not present a certificate");
+
+ flags = 0;
}
- else
+ else if (ssl_flags & SSLF_CLIENT_CERT_OPTIONAL)
+ flags = SSL_VERIFY_PEER;
#endif
- SSL_CTX_set_verify (ctx->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
- verify_callback);
+ SSL_CTX_set_verify (ctx->ctx, flags, verify_callback);
SSL_CTX_set_info_callback (ctx->ctx, info_callback);
}