Claus Assmann <[EMAIL PROTECTED]>:

>>> Question: is there some simple way to find out whether the client
>>> has been authenticated? I registered a callback with SSL_CTX_set_verify,
>>> but I don't completely understand it...

>> Do you have to use a callback?  You can use SSL_get_verify_result
>> and SSL_get_peer_certificate.  If the former returns X509_V_OK and
>> the latter returns non-NULL, then you have an authenticated
>> certificate.

> Thanks for your help! I've tried this, and run into a new problem:
> how do I correctly set the verify_mode? Reading the code,
> SSL_VERIFY_CLIENT_ONCE and SSL_VERIFY_PEER seem to be useful for
> my purpose (try to verify the client, but don't fail). However,
> setting ctx->verify_mode to SSL_VERIFY_CLIENT_ONCE doesn't seem to
> work: the server doesn't ask for a certificate then. If also
> SSL_VERIFY_PEER is set, the connection fails if the client doesn't
> provide a certificate (although I assumed this only happens if
> SSL_VERIFY_FAIL_IF_NO_PEER_CERT is set). So it seems I have to
> install a callback (that always returns 1).

SSL_VERIFY_FAIL_IF_NO_PEER_CERT should not be set for your
application, obviously.  Verification will still fail and the protocol
be aborted if the client presents a certificate and OpenSSL does not
like it.  To change this behaviour, you don't have to provide an X.509
verification callback with SSL_CTX_set_verify (as s_client, s_server
and ssltest do); you can use SSL_CTX_set_cert_verify_callback, which
sets a higher level callback (app_verify_callback).  All this is still
quite confusing in the library source code -- the naming is not alway
consistent, and various members of the structures are never used.  The
relevant code for this is the following in ssl_verify_cert_chain
(ssl/ssl_cert.c; this extract is simplified by hand-processing the
#ifndef):

        if (s->ctx->app_verify_callback != NULL)
                i=s->ctx->app_verify_callback(&ctx);
        else
                i=X509_verify_cert(&ctx);

        s->verify_result=ctx.error;

SSL_CTX_set_cert_verify_callback takes two arguments, the second of
which is never used.  Obviously the idea was the second one would be
passed to the callback -- this will likely be done so in OpenSSL
0.9.5.  All your callback has to do is call X509_verify_cert and
return 1 if that function returned 0.  X509_verify_cert sets
ctx.error, so that the application can see that something went wrong.

Example code:

static int
verify_dont_fail_cb(X509_STORE_CTX *c)
{
    int i;
    
    i = X509_verify_cert(c); /* sets c->error */
    if (i == 0)
        return 1;
    else
        return i;
}


SSL_CTX *
tls_create_ctx(..., int fail_unless_verified_p, ...)
{
        .....

        SSL_CTX_set_verify(ret, SSL_VERIFY_PEER | (fail_unless_verified_p ? 
SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), 0);
        if (!fail_unless_verified_p)
            SSL_CTX_set_cert_verify_callback(ret, verify_dont_fail_cb, NULL);

        .....
}
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to