Standard preamble:
========================================================================
..
.... Set up some character translations and predefined strings. \*(-- will
give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
double quote, and \*(R" will give a right double quote. \*(C+ will
give a nicer C++. Capital omega is used to do unbreakable dashes and
therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
nothing in troff, for use with C<>.
.tr \(*W- . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\}
Escape single quotes in literal strings from groff's Unicode transform.
If the F register is >0, we'll generate index entries on stderr for
titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
entries marked with X<> in POD. Of course, you'll have to process the
output yourself in some meaningful fashion.
Avoid warning from groff about undefined register 'F'.
.. .nr rF 0 . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF
Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] .\} . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents . \" corrections for vroff . \" for low resolution devices (crt and lpr) \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} ========================================================================
Title "SSL_CTX_SET_VERIFY 3"
way too many mistakes in technical documents.
\fBSSL_set_verify() sets the verification flags for ssl to be mode and specifies the verify_callback function to be used. If no callback function shall be specified, the \s-1NULL\s0 pointer can be used for verify_callback. In this case last verify_callback set specifically for this ssl remains. If no special callback was set before, the default callback for the underlying \fBctx is used, that was valid at the time ssl was created with \fBSSL_new\|(3). Within the callback function, \fBSSL_get_ex_data_X509_STORE_CTX_idx can be called to get the data index of the current \s-1SSL\s0 object that is doing the verification.
\fBSSL_CTX_set_verify_depth() sets the maximum depth for the certificate chain verification that shall be allowed for ctx.
\fBSSL_set_verify_depth() sets the maximum depth for the certificate chain verification that shall be allowed for ssl.
\fBSSL_CTX_set_post_handshake_auth() and SSL_set_post_handshake_auth() enable the Post-Handshake Authentication extension to be added to the ClientHello such that post-handshake authentication can be requested by the server. If 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 \fBSSL_CTX_set_client_cert_cb() if no certificate is provided at initialization.
\fBSSL_verify_client_post_handshake() causes a CertificateRequest message to be sent by a server on the given ssl connection. The \s-1SSL_VERIFY_PEER\s0 flag must be set; the \s-1SSL_VERIFY_POST_HANDSHAKE\s0 flag is optional.
If the mode is \s-1SSL_VERIFY_NONE\s0 none of the other flags may be set.
The actual verification procedure is performed either using the built-in verification procedure or using another application provided verification function set with \fBSSL_CTX_set_cert_verify_callback\|(3). The following descriptions apply in the case of the built-in procedure. An application provided procedure also has access to the verify depth information and the verify_callback() function, but the way this information is used may be different.
\fBSSL_CTX_set_verify_depth() and SSL_set_verify_depth() set a limit on the number of certificates between the end-entity and trust-anchor certificates. Neither the end-entity nor the trust-anchor certificates count against depth. If the certificate chain needed to reach a trusted issuer is longer than depth+2, X509_V_ERR_CERT_CHAIN_TOO_LONG will be issued. The depth count is \*(L"level 0:peer certificate\*(R", \*(L"level 1: \s-1CA\s0 certificate\*(R", \*(L"level 2: higher level \s-1CA\s0 certificate\*(R", and so on. Setting the maximum depth to 2 allows the levels 0, 1, 2 and 3 (0 being the end-entity and 3 the trust-anchor). The default depth limit is 100, allowing for the peer certificate, at most 100 intermediate \s-1CA\s0 certificates and a final trust anchor certificate.
The verify_callback function is used to control the behaviour when the \s-1SSL_VERIFY_PEER\s0 flag is set. It must be supplied by the application and receives two arguments: preverify_ok indicates, whether the verification of the certificate in question was passed (preverify_ok=1) or not (preverify_ok=0). x509_ctx is a pointer to the complete context used for the certificate chain verification.
The certificate chain is checked starting with the deepest nesting level (the root \s-1CA\s0 certificate) and worked upward to the peer's certificate. At each level signatures and issuer attributes are checked. Whenever a verification error is found, the error number is stored in x509_ctx and verify_callback is called with preverify_ok=0. By applying X509_CTX_store_* functions verify_callback can locate the certificate in question and perform additional steps (see \s-1EXAMPLES\s0). If no error is found for a certificate, verify_callback is called with preverify_ok=1 before advancing to the next level.
The return value of verify_callback controls the strategy of the further verification process. If verify_callback returns 0, the verification process is immediately stopped with \*(L"verification failed\*(R" state. If \s-1SSL_VERIFY_PEER\s0 is set, a verification failure alert is sent to the peer and the \s-1TLS/SSL\s0 handshake is terminated. If verify_callback returns 1, the verification process is continued. If verify_callback always returns 1, the \s-1TLS/SSL\s0 handshake will not be terminated with respect to verification failures and the connection will be established. The calling process can however retrieve the error code of the last verification error using \fBSSL_get_verify_result\|(3) or by maintaining its own error storage managed by verify_callback.
If no verify_callback is specified, the default callback will be used. Its return value is identical to preverify_ok, so that any verification failure will lead to a termination of the \s-1TLS/SSL\s0 handshake with an alert message, if \s-1SSL_VERIFY_PEER\s0 is set.
After calling SSL_set_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().
\fBSSL_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.
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.
All verification errors are printed; information about the certificate chain is printed on request. The example is realized for a server that does allow but not require client certificates.
The example makes use of the ex_data technique to store application data into/retrieve application data from the \s-1SSL\s0 structure (see CRYPTO_get_ex_new_index\|(3), \fBSSL_get_ex_data_X509_STORE_CTX_idx\|(3)).
.Vb 7 ... 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\en", err, X509_verify_cert_error_string(err), depth, buf); } else if (mydata->verbose_mode) { printf("depth=%d:%s\en", 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\en", 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 th 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 */ } } .Ve
Licensed under the OpenSSL license (the \*(L"License\*(R"). You may not use this file except in compliance with the License. You can obtain a copy in the file \s-1LICENSE\s0 in the source distribution or at <https://www.openssl.org/source/license.html>.