SSL_get_ex_data_X509_STORE_CTX_idx,
SSL_CTX_set_verify, SSL_set_verify,
SSL_CTX_set_verify_depth, SSL_set_verify_depth,
-SSL_verify_cb
+SSL_verify_cb,
+SSL_verify_client_post_handshake,
+SSL_set_post_handshake_auth
- set peer certificate verification parameters
=head1 SYNOPSIS
#include <openssl/ssl.h>
+ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
+
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb verify_callback);
- void SSL_set_verify(SSL *s, int mode, SSL_verify_cb verify_callback);
+ void SSL_set_verify(SSL *ssl, int mode, SSL_verify_cb verify_callback);
SSL_get_ex_data_X509_STORE_CTX_idx(void);
void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
- void SSL_set_verify_depth(SSL *s, int depth);
+ void SSL_set_verify_depth(SSL *ssl, int depth);
-
- typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
+ int SSL_verify_client_post_handshake(SSL *ssl);
+ void SSL_set_post_handshake_auth(SSL *ssl, int val);
=head1 DESCRIPTION
SSL_set_verify_depth() sets the maximum B<depth> for the certificate chain
verification that shall be allowed for B<ssl>.
+SSL_set_post_handshake_auth() enables the Post-Handshake Authentication
+extension to be added to the ClientHello such that post-handshake authentication
+can be requested by the server. If B<val> is 0 then the extension is not sent,
+otherwise it is. By default the extension is not sent. A certificate callback
+will need to be set via SSL_CTX_set_client_cert_cb() if no certificate is
+provided at initialization.
+
+SSL_verify_client_post_handshake() causes a CertificateRequest message to be
+sent by a server on the given B<ssl> connection. The SSL_VERIFY_PEER flag must
+be set; the SSL_VERIFY_POST_HANDSHAKE flag is optional.
+
=head1 NOTES
The verification of certificates can be controlled by a set of logically
immediately terminated with an alert message containing the reason for
the verification failure.
The behaviour can be controlled by the additional
-SSL_VERIFY_FAIL_IF_NO_PEER_CERT and SSL_VERIFY_CLIENT_ONCE flags.
+SSL_VERIFY_FAIL_IF_NO_PEER_CERT, SSL_VERIFY_CLIENT_ONCE and
+SSL_VERIFY_POST_HANDSHAKE flags.
B<Client mode:> the server certificate is verified. If the verification process
fails, the TLS/SSL handshake is
=item SSL_VERIFY_CLIENT_ONCE
-B<Server mode:> only request a client certificate on the initial TLS/SSL
-handshake. Do not ask for a client certificate again in case of a
-renegotiation. This flag must be used together with SSL_VERIFY_PEER.
+B<Server mode:> only request a client certificate once during the
+connection. Do not ask for a client certificate again during
+renegotiation or post-authentication if a certificate was requested
+during the initial handshake. This flag must be used together with
+SSL_VERIFY_PEER.
+
+B<Client mode:> ignored
+
+=item SSL_VERIFY_POST_HANDSHAKE
+
+B<Server mode:> the server will not send a client certificate request
+during the initial handshake, but will send the request via
+SSL_verify_client_post_handshake(). This allows the SSL_CTX or SSL
+to be configured for post-handshake peer verification before the
+handshake occurs. This flag must be used together with
+SSL_VERIFY_PEER. TLSv1.3 only; no effect on pre-TLSv1.3 connections.
B<Client mode:> ignored
failure will lead to a termination of the TLS/SSL handshake with an
alert message, if SSL_VERIFY_PEER is set.
+After calling SSL_force_post_handshake_auth(), the client will need to add a
+certificate or certificate callback to its configuration before it can
+successfully authenticate. This must be called before SSL_connect().
+
+SSL_verify_client_post_handshake() requires that verify flags have been
+previously set, and that a client sent the post-handshake authentication
+extension. When the client returns a certificate the verify callback will be
+invoked. A write operation must take place for the Certificate Request to be
+sent to the client, this can be done with SSL_do_handshake() or SSL_write_ex().
+Only one certificate request may be outstanding at any time.
+
+When post-handshake authentication occurs, a refreshed NewSessionTicket
+message is sent to the client.
+
=head1 BUGS
In client mode, it is not checked whether the SSL_VERIFY_PEER flag
The SSL*_set_verify*() functions do not provide diagnostic information.
+The SSL_verify_client_post_handshake() function returns 1 if the request
+succeeded, and 0 if the request failed. The error stack can be examined
+to determine the failure reason.
+
=head1 EXAMPLES
The following code sequence realizes an example B<verify_callback> function
int always_continue;
} mydata_t;
int mydata_index;
+
...
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
- char buf[256];
- X509 *err_cert;
- int err, depth;
- SSL *ssl;
- mydata_t *mydata;
-
- err_cert = X509_STORE_CTX_get_current_cert(ctx);
- err = X509_STORE_CTX_get_error(ctx);
- depth = X509_STORE_CTX_get_error_depth(ctx);
-
- /*
- * Retrieve the pointer to the SSL of the connection currently treated
- * and the application specific data stored into the SSL object.
- */
- ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
- mydata = SSL_get_ex_data(ssl, mydata_index);
-
- X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
-
- /*
- * Catch a too long certificate chain. The depth limit set using
- * SSL_CTX_set_verify_depth() is by purpose set to "limit+1" so
- * that whenever the "depth>verify_depth" condition is met, we
- * have violated the limit and want to log this error condition.
- * We must do it here, because the CHAIN_TOO_LONG error would not
- * be found explicitly; only errors introduced by cutting off the
- * additional certificates would be logged.
- */
- if (depth > mydata->verify_depth) {
- preverify_ok = 0;
- err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
- X509_STORE_CTX_set_error(ctx, err);
- }
- if (!preverify_ok) {
- printf("verify error:num=%d:%s:depth=%d:%s\n", err,
- X509_verify_cert_error_string(err), depth, buf);
- }
- else if (mydata->verbose_mode)
- {
- printf("depth=%d:%s\n", depth, buf);
- }
-
- /*
- * At this point, err contains the last verification error. We can use
- * it for something special
- */
- if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
- {
- X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
- printf("issuer= %s\n", buf);
- }
-
- if (mydata->always_continue)
- return 1;
- else
- return preverify_ok;
+ char buf[256];
+ X509 *err_cert;
+ int err, depth;
+ SSL *ssl;
+ mydata_t *mydata;
+
+ err_cert = X509_STORE_CTX_get_current_cert(ctx);
+ err = X509_STORE_CTX_get_error(ctx);
+ depth = X509_STORE_CTX_get_error_depth(ctx);
+
+ /*
+ * Retrieve the pointer to the SSL of the connection currently treated
+ * and the application specific data stored into the SSL object.
+ */
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ mydata = SSL_get_ex_data(ssl, mydata_index);
+
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
+
+ /*
+ * Catch a too long certificate chain. The depth limit set using
+ * SSL_CTX_set_verify_depth() is by purpose set to "limit+1" so
+ * that whenever the "depth>verify_depth" condition is met, we
+ * have violated the limit and want to log this error condition.
+ * We must do it here, because the CHAIN_TOO_LONG error would not
+ * be found explicitly; only errors introduced by cutting off the
+ * additional certificates would be logged.
+ */
+ if (depth > mydata->verify_depth) {
+ preverify_ok = 0;
+ err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ X509_STORE_CTX_set_error(ctx, err);
+ }
+ if (!preverify_ok) {
+ printf("verify error:num=%d:%s:depth=%d:%s\n", err,
+ X509_verify_cert_error_string(err), depth, buf);
+ } else if (mydata->verbose_mode) {
+ printf("depth=%d:%s\n", depth, buf);
+ }
+
+ /*
+ * At this point, err contains the last verification error. We can use
+ * it for something special
+ */
+ if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
+ X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
+ printf("issuer= %s\n", buf);
+ }
+
+ if (mydata->always_continue)
+ return 1;
+ else
+ return preverify_ok;
}
...
mydata_index = SSL_get_ex_new_index(0, "mydata index", NULL, NULL, NULL);
...
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
verify_callback);
/*
...
SSL_accept(ssl); /* check of success left out for clarity */
- if (peer = SSL_get_peer_certificate(ssl))
- {
- if (SSL_get_verify_result(ssl) == X509_V_OK)
- {
- /* The client sent a certificate which verified OK */
- }
+ if (peer = SSL_get_peer_certificate(ssl)) {
+ if (SSL_get_verify_result(ssl) == X509_V_OK) {
+ /* The client sent a certificate which verified OK */
+ }
}
=head1 SEE ALSO
L<SSL_get_peer_certificate(3)>,
L<SSL_CTX_set_cert_verify_callback(3)>,
L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>,
+L<SSL_CTX_set_client_cert_cb(3)>,
L<CRYPTO_get_ex_new_index(3)>
+=head1 HISTORY
+
+The SSL_VERIFY_POST_HANDSHAKE option, and the SSL_verify_client_post_handshake()
+and SSL_set_post_handshake_auth() functions were added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy