NAME
SSL_CTX_set_verify, SSL_set_verify, SSL_CTX_set_verify_depth, SSL_set_verify_depth — set peer certificate verification parametersSYNOPSIS
#include <openssl/ssl.h>SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
SSL_set_verify(SSL *s, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
SSL_set_verify_depth(SSL *s, int depth);
verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx);
DESCRIPTION
SSL_CTX_set_verify() sets the verification flags for ctx to be mode and specifies the verify_callback function to be used. If no callback function shall be specified, the NULL pointer can be used for verify_callback.NOTES
The verification of certificates can be controlled by a set of bitwise ORed mode flags:- SSL_VERIFY_NONE
- 
Server mode: the server will not send a client certificate request to the client, so the client will not send a certificate.Client mode: if not using an anonymous cipher (by default disabled), the server will send a certificate which will be checked. The result of the certificate verification process can be checked after the TLS/SSL handshake using the SSL_get_verify_result(3) function. The handshake will be continued regardless of the verification result.
- SSL_VERIFY_PEER
- 
Server mode: the server sends a client certificate request to the client. The certificate returned (if any) is checked. If the verification process fails, the TLS/SSL handshake is 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.Client mode: the server certificate is verified. If the verification process fails, the TLS/SSL handshake is immediately terminated with an alert message containing the reason for the verification failure. If no server certificate is sent, because an anonymous cipher is used, SSL_VERIFY_PEER is ignored.
- SSL_VERIFY_FAIL_IF_NO_PEER_CERT
- 
Server mode: if the client did not return a certificate, the TLS/SSL handshake is immediately terminated with a “handshake failure” alert. This flag must be used together with SSL_VERIFY_PEER.Client mode: ignored
- SSL_VERIFY_CLIENT_ONCE
- 
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.Client mode: ignored
RETURN VALUES
The SSL*_set_verify*() functions do not provide diagnostic information.EXAMPLES
The following code sequence realizes an example verify_callback function that will always continue the TLS/SSL handshake regardless of verification failure, if wished. The callback realizes a verification depth limit with more informational output.
... 
 
typedef struct { 
	int	verbose_mode; 
	int	verify_depth; 
	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(ctx->current_cert), 
		    buf, 256); 
		printf("issuer= %s\n", buf); 
	} 
 
	if (mydata->always_continue) 
		return 1; 
	else 
		return preverify_ok; 
} 
... 
 
mydata_t mydata; 
 
... 
 
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, 
    verify_callback); 
 
/* 
 * Let the verify_callback catch the verify_depth error so that we get 
 * an appropriate error in the logfile. 
 */ 
SSL_CTX_set_verify_depth(verify_depth + 1); 
 
/* 
 * Set up the SSL specific data into "mydata" and store it into the SSL 
 * structure. 
 */ 
mydata.verify_depth = verify_depth; ... 
SSL_set_ex_data(ssl, mydata_index, &mydata); 
 
... 
 
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 */ 
	} 
}
