[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[Libevent-users] Certificate validation problem when using libevent



Hello,

I have a weird problem with the program below.
I compile it on Mac OS 10.8.2 and if I link it against the default
OpenSSL version (0.9.8) it ignores the results of the verify callback.
If I link it against the newest OpenSSL version available via Mac
Ports, it works as expected (if the certificate is not valid, it
aborts the connection immediately).

If I test both versions with a programm not using libevent (and with
blocking calls) it works as expected.
I think the problem is hidden in the combination of libevent and the
default OpenSSL version, but I don't know where to look or even if it
is libevent or OpenSSL related. (I tried libevent 2.0.21 and an alpha
version.)

I think it is ok to use the Mac Ports OpenSSL version for developing
purposes but later it should work without having to install it.

Regards
Björn


#include <event2/dns.h>
#include <event2/bufferevent.h>
#include <event2/bufferevent_ssl.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <event2/event.h>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/hmac.h>

#include <stdio.h>

void readcb(struct bufferevent *bev, void *ptr)
{
    char buf[1024];
    int n;
    struct evbuffer *input = bufferevent_get_input(bev);
    while ((n = evbuffer_remove(input, buf, sizeof(buf))) > 0) {
        fwrite(buf, 1, n, stdout);
    }
}

void eventcb(struct bufferevent *bev, short events, void *ptr)
{
    SSL *ssl = bufferevent_openssl_get_ssl(bev);
    X509 *peer;
    if (events & BEV_EVENT_CONNECTED) {
        printf("Connect okay\n");
        if ((peer = SSL_get_peer_certificate(ssl)))
        {
            if (SSL_get_verify_result(ssl) == X509_V_OK)
            {
                /* The client sent a certificate which verified OK */
                printf("ok\n");
            }
        }
    } else if (events & (BEV_EVENT_ERROR|BEV_EVENT_EOF)) {
        struct event_base *base = ptr;
        if (events & BEV_EVENT_ERROR) {
            int err = bufferevent_socket_get_dns_error(bev);
            if (err)
                printf("DNS error: %s\n", evutil_gai_strerror(err));
        }

        bufferevent_free(bev);
        event_base_loopexit(base, NULL);
    }
}

static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {

    printf("preverify_ok: %d\n", preverify_ok);
    return preverify_ok;

}

int main(int argc, char **argv)
{
    struct event_base *base;
    struct evdns_base *dns_base;
    struct bufferevent *bev;
    SSL_CTX *ssl_ctx;
    SSL *ssl;

    SSL_load_error_strings();
    SSL_library_init();
    RAND_poll();

    ssl_ctx = SSL_CTX_new(SSLv3_method());

    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, verify_callback);

    if (SSL_CTX_load_verify_locations(ssl_ctx, "root.crt", NULL) !=
1){ fprintf(stderr, "Couldn't load certificate trust store.\n");
        return -1;
    }

    ssl = SSL_new(ssl_ctx);

    base = event_base_new();
    dns_base = evdns_base_new(base, 1);

    bev = bufferevent_openssl_socket_new(base, -1, ssl,
BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev, readcb, NULL, eventcb, base);
    bufferevent_enable(bev, EV_READ|EV_WRITE);

    evbuffer_add_printf(bufferevent_get_output(bev), "GET /\r\n");
    bufferevent_socket_connect_hostname(
                                        bev, dns_base, AF_UNSPEC,
"www.google.com", 443);
    event_base_dispatch(base);

    return 0;
}
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.