On Nov 30, 2005, at 4:42 PM, Victor Duchovni wrote:
This is completely doable. Example code to be found in many SSL
applications.

        http://www.postfix.org/TLS_README.html#server_vrfy_client
        http://www.postfix.org/TLS_README.html#server_access
        http://www.postfix.org/postconf.5.html#permit_tls_clientcerts

Source code:

        http://www.postfix.org/dowload.html

get 2.3-20051128 and look at:

        src/tls/tls_verify.c
        src/tls/tls_server.c
        src/tls/tls_client.c

Sorry, I don't actually see that the postfix code is doing what I want. I see that you're computing the client's fingerprint in tls_server.c, but that's only after SSL has verified the client certificate. In my case, the client has a self-signed certificate, so the verification fails. As a result (I think), SSL_get_peer_certificate is returning NULL (see sample code below).

Sean
--
                   Boredom is always counterrevolutionary.


// Simple echo server using TLS

int
main(int argc, char *argv[])
{
    SSL_load_error_strings();
    SSL_library_init();

    SSL_CTX *ctx = SSL_CTX_new(TLSv1_server_method());
    assert(ctx);

SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                       NULL);

if (!SSL_CTX_use_certificate_file(ctx, "server-cert.pem", SSL_FILETYPE_PEM))
        error("server: load cert error");

if (!SSL_CTX_use_PrivateKey_file(ctx, "server-priv.pem", SSL_FILETYPE_PEM))
        error("server: load key error");

    if (!SSL_CTX_check_private_key(ctx))
        error("server: private key doesn't match cert");

    SSL *ssl = SSL_new(ctx);
    assert(ssl);

    int ssock = socket(AF_INET, SOCK_STREAM, 0);

    int n = 1;
    setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(2000);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(ssock, (const sockaddr*) &addr, sizeof(addr))) {
        perror("bind:");
        assert(0);
    }

    if (listen(ssock, 5))
        assert(0);

    while (1) {
        printf("server: waiting for accept\n");
        socklen_t addrlen = sizeof(addr);
        int sock = accept(ssock, (sockaddr*) &addr, &addrlen);
        if (sock <= 0)
            assert(0);

        printf("server: tcp accept succeeded\n");

        if (!SSL_set_fd(ssl, sock))
            assert(0);

        int ret;
        if ((ret = SSL_accept(ssl)) == 0) {
            int err = SSL_get_error(ssl, ret);
            printf("server: accept err=%d\n", err);
            assert(0);
        }

        printf("server: ssl accept succeeded\n");

        // XXX: this fails:
        assert(SSL_get_verify_result(ssl) == X509_V_OK);

        X509 *peer = SSL_get_peer_certificate(ssl);

// XXX: and if you comment out the above assert, this fails, too:
        assert(peer);

        int n;
        char readbuf[256];
        while ((n = SSL_read(ssl, readbuf, sizeof(readbuf))) > 0) {
            printf("server: read %d bytes\n", n);
            if (SSL_write(ssl, readbuf, n) != n)
                break;
            printf("server: wrote %d bytes\n", n);
        }

        printf("server: connection closed\n");
    }

    return 0;
}

Attachment: PGP.sig
Description: This is a digitally signed message part

Reply via email to