
#use wml::openssl-macros area=docs page=X509_STORE_CTX_set_verify_cb

<title>Documents, X509_STORE_CTX_set_verify_cb(3)</title>

<h1>X509_STORE_CTX_set_verify_cb(3)</h1>

#use wml::imp::generic

{:
## What's this? [[s|(<STRONG>[^<].+?)</A>(</STRONG><DD>)|$1$2|sg]]
[[s|<P>\s+<P>|<P>|sg]]
[[s|<P>\s+</|</|sg]]
[[s|<DD>\s*<DT>|<DD>&nbsp;<DT>|sg]]
[[s|<DD>\s*</DL>|<DD>&nbsp;</DL>|sg]]
[[s|\[|&#91;|sg]]
[[s|\]|&#93;|sg]]

<!-- INDEX BEGIN -->

<UL>

	<LI><A HREF="#NAME">NAME</A>
	<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
	<LI><A HREF="#WARNING">WARNING</A>
	<LI><A HREF="#NOTES">NOTES</A>
	<LI><A HREF="#RETURN_VALUES">RETURN VALUES</A>
	<LI><A HREF="#EXAMPLES">EXAMPLES</A>
	<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
	<LI><A HREF="#HISTORY">HISTORY</A>
</UL>
<!-- INDEX END -->

<HR>
<P>
<HR>
<H1><A NAME="NAME">NAME</A></H1>
<P>
X509_STORE_CTX_set_verify_cb - set verification callback

</P>
<P>
<HR>
<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
<PRE> #include &lt;openssl/x509_vfy.h&gt;
</PRE>
<PRE> void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
                                int (*verify_cb)(int ok, X509_STORE_CTX *ctx));
</PRE>
<P>
<HR>
<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
<P>
<CODE>X509_STORE_CTX_set_verify_cb()</CODE> sets the verification callback
of <STRONG>ctx</STRONG> to
<STRONG>verify_cb</STRONG> overwriting any existing callback.

</P>
<P>
The verification callback can be used to customise the operation of
certificate verification, either by overriding error conditions or logging
errors for debugging purposes.

</P>
<P>
However a verification callback is <STRONG>not</STRONG> essential and the default operation is often sufficient.

</P>
<P>
The <STRONG>ok</STRONG> parameter to the callback indicates the value the callback should return to
retain the default behaviour. If it is zero then and error condition is
indicated. If it is 1 then no error occurred. If the flag
<STRONG>X509_V_FLAG_NOTIFY_POLICY</STRONG> is set then <STRONG>ok</STRONG> is set to 2 to indicate the policy checking is complete.

</P>
<P>
The <STRONG>ctx</STRONG> parameter to the callback is the <STRONG>X509_STORE_CTX</STRONG> structure that is performing the verification operation. A callback can
examine this structure and receive additional information about the error,
for example by calling <CODE>X509_STORE_CTX_get_current_cert().</CODE>
Additional application data can be passed to the callback via the <STRONG>ex_data</STRONG> mechanism.

</P>
<P>
<HR>
<H1><A NAME="WARNING">WARNING</A></H1>
<P>
In general a verification callback should <STRONG>NOT</STRONG> unconditionally return 1 in all circumstances because this will allow
verification to succeed no matter what the error. This effectively removes
all security from the application because <STRONG>any</STRONG> certificate (including untrusted generated ones) will be accepted.

</P>
<P>
<HR>
<H1><A NAME="NOTES">NOTES</A></H1>
<P>
The verification callback can be set and inherited from the parent
structure performing the operation. In some cases (such as S/MIME
verification) the
<STRONG>X509_STORE_CTX</STRONG> structure is created and destroyed internally and the only way to set a
custom verification callback is by inheriting it from the associated <STRONG>X509_STORE</STRONG>.

</P>
<P>
<HR>
<H1><A NAME="RETURN_VALUES">RETURN VALUES</A></H1>
<P>
<CODE>X509_STORE_CTX_set_verify_cb()</CODE> does not return a value.

</P>
<P>
<HR>
<H1><A NAME="EXAMPLES">EXAMPLES</A></H1>
<P>
Default callback operation:

</P>
<PRE> int verify_callback(int ok, X509_STORE_CTX *ctx)
        {
        return ok;
        }
</PRE>
<P>
Simple example, suppose a certificate in the chain is expired and we wish
to continue after this error:

</P>
<PRE> int verify_callback(int ok, X509_STORE_CTX *ctx)
        {
        /* Tolerate certificate expiration */
        if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED)
                        return 1;
        /* Otherwise don't override */
        return ok;
        }
</PRE>
<P>
More complex example, we don't wish to continue after <STRONG>any</STRONG> certificate has expired just one specific case:

</P>
<PRE> int verify_callback(int ok, X509_STORE_CTX *ctx)
        {
        int err = X509_STORE_CTX_get_error(ctx);
        X509 *err_cert = X509_STORE_CTX_get_current_cert(ctx);
        if (err == X509_V_ERR_CERT_HAS_EXPIRED)
                {
                if (check_is_acceptable_expired_cert(err_cert)
                        return 1;
                }
        return ok;
        }
</PRE>
<P>
Full featured logging callback. In this case the <STRONG>bio_err</STRONG> is assumed to be a global logging <STRONG>BIO</STRONG>, an alternative would to store a BIO in <STRONG>ctx</STRONG> using
<STRONG>ex_data</STRONG>. int <CODE>verify_callback(int</CODE> ok, X509_STORE_CTX *ctx) { X509
*err_cert; int err,depth;

</P>
<PRE>        err_cert = X509_STORE_CTX_get_current_cert(ctx);
        err =   X509_STORE_CTX_get_error(ctx);
        depth = X509_STORE_CTX_get_error_depth(ctx);
</PRE>
<PRE>        BIO_printf(bio_err,&quot;depth=%d &quot;,depth);
        if (err_cert)
                {
                X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert),
                                        0, XN_FLAG_ONELINE);
                BIO_puts(bio_err, &quot;\n&quot;);
                }
        else
                BIO_puts(bio_err, &quot;&lt;no cert&gt;\n&quot;);
        if (!ok)
                BIO_printf(bio_err,&quot;verify error:num=%d:%s\n&quot;,err,
                        X509_verify_cert_error_string(err));
        switch (err)
                {
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
                BIO_puts(bio_err,&quot;issuer= &quot;);
                X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
                                        0, XN_FLAG_ONELINE);
                BIO_puts(bio_err, &quot;\n&quot;);
                break;
        case X509_V_ERR_CERT_NOT_YET_VALID:
        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
                BIO_printf(bio_err,&quot;notBefore=&quot;);
                ASN1_TIME_print(bio_err,X509_get_notBefore(err_cert));
                BIO_printf(bio_err,&quot;\n&quot;);
                break;
        case X509_V_ERR_CERT_HAS_EXPIRED:
        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
                BIO_printf(bio_err,&quot;notAfter=&quot;);
                ASN1_TIME_print(bio_err,X509_get_notAfter(err_cert));
                BIO_printf(bio_err,&quot;\n&quot;);
                break;
        case X509_V_ERR_NO_EXPLICIT_POLICY:
                policies_print(bio_err, ctx);
                break;
                }
        if (err == X509_V_OK &amp;&amp; ok == 2)
                /* print out policies */
</PRE>
<PRE>        BIO_printf(bio_err,&quot;verify return:%d\n&quot;,ok);
        return(ok);
        }
</PRE>
<P>
<HR>
<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
<P>
<A HREF="../crypto/X509_STORE_CTX_get_error.html#">X509_STORE_CTX_get_error(3)</A>

<A HREF="../crypto/X509_STORE_set_verify_cb_func.html#">X509_STORE_set_verify_cb_func(3)</A>

<A HREF="../crypto/X509_STORE_CTX_get_ex_new_index.html#">X509_STORE_CTX_get_ex_new_index(3)</A>



</P>
<P>
<HR>
<H1><A NAME="HISTORY">HISTORY</A></H1>
<P>
<CODE>X509_STORE_CTX_set_verify_cb()</CODE> is available in all versions of
SSLeay and OpenSSL.

</P>
:}


