client certificates issued by my own CA with Apache

11,840

It doesn't really make sense to talk about a "self-signed CA". Your title ("Self-signed client SSL certificates [...]") suggests you're talking about self-signed client certificate. You're not: you're talking about client certificates issued by your own CA.

You've put your SSLVerifyClient directive within a Directory section, which would imply a re-negotiation to get the client certificate, once the client has made a request trying to access that directory.

Since there is no DocumentRoot directive in your configuration, it's not clear whether a request on / will try to access this directory (this may depend on compilation options depending on how it was packaged, but /var/www isn't the default value otherwise).

Putting SSLVerifyClient directly in your virtual host should at least make openssl s_client see a client-certificate request. Fixing the DocumentRoot might not be enough, since you'd need to make the HTTP request to trigger the renegotiation.

Share:
11,840

Related videos on Youtube

user2919956
Author by

user2919956

Updated on July 12, 2022

Comments

  • user2919956
    user2919956 almost 2 years

    Trying to get an HTTPS session working using client certificates from a self-signed CA. The connection should check that all certificates are valid, both client and server side.

    The process I followed is roundly as follows:

    1. Create Certificate Authority

      openssl genrsa -out CA.key 4096
      openssl req -new -key CA.key -out CA.csr
      openssl x509 -req -days 365 -in CA.csr -out CA.crt -signkey CA.key
      
    2. Create Server Certificate

      openssl genrsa -out server.key 4096
      openssl req -new -key server.key -out server.csr
      openssl ca -in server.csr -cert CA.crt -keyfile CA.key -out server.crt
      
    3. Create Client Certificate

      openssl genrsa -out client.key 4096
      openssl req -new -key client.key -out client.csr
      openssl ca -in client.csr -cert CA.crt -keyfile CA.key -out client.crt
      
    4. Configure Apache

      <VirtualHost _default_:443>
        SSLEngine on
        SSLCertificateFile "server.crt"
        SSLCertificateKeyFile "server.key"
        SSLCACertificateFile "CA.crt"
        <Directory "/var/www">
            SSLVerifyClient optional
            SSLVerifyDepth 10
            SSLOptions +StdEnvVars +ExportCertData
        </Directory>
      </VirtualHost>  
      

    Now I try and make a test connection:

    wget \
        --post-data 'id=1234' \
        --certificate=client.crt \
        --ca-certificate=CA.crt  \
        https://test.example.com:443
    

    The resulting output from wget shows (over and over), in part:

    HTTP request sent, awaiting response... No data received.
    Retrying.
    

    Checking the SSL error log from Apache give me the following messages:

    [debug] ssl_engine_io.c(1606): [client xx.xx.xx.xx] total of 41 bytes in buffer, eos=1
    [client xx.xx.xx.xx] Requesting connection re-negotiation
    [debug] ssl_engine_io.c(1908): OpenSSL: I/O error, 5 bytes expected to read on BIO#80b075190 [mem: 80b0ca003]
    [debug] ssl_engine_kernel.c(771): [client xx.xx.xx.xx] Performing full renegotiation: complete handshake protocol (client does support secure renegotiation)
    [debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSL renegotiate ciphers
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 write hello request A
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 flush data
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 write hello request C
    [info] [client xx.xx.xx.xx] Awaiting re-negotiation handshake
    [debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: before accept initialization
    [debug] ssl_engine_io.c(1908): OpenSSL: I/O error, 5 bytes expected to read on BIO#80b075190 [mem: 80b0ca003]
    [debug] ssl_engine_kernel.c(1929): OpenSSL: Exit: error in SSLv3 read client hello B
    [error] [client xx.xx.xx.xx] Re-negotiation handshake failed: Not accepted by client!?
    [debug] ssl_engine_io.c(1650): [client xx.xx.xx.xx] read from buffered SSL brigade, mode 0, 8192 bytes
    [debug] ssl_engine_io.c(1725): [client xx.xx.xx.xx] buffered SSL brigade exhausted
    [debug] ssl_engine_io.c(1650): [client xx.xx.xx.xx] read from buffered SSL brigade, mode 2, 0 bytes
    [info] [client XX:XX:XX:XX::xx] Connection to child 3 established (server register.kiosk.tain.com:443)
    [info] Seeding PRNG with 656 bytes of entropy
    [debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start 
    [debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: before/accept initialization
    

    Run the openssl client to see if there's anything to help in here:

    openssl s_client \
        -showcerts \
        -connect test.example.com:443 \
        -cert client.crt \
        -key client.key \
        -CAfile CA.crt
    

    In the reply I see the following:

    ---
    Server certificate
    subject=/C=XX/ST=XXXXX/O=XXXX/CN=test.example.com
    issuer=/O=XXXX/L=XXXXX/ST=XXXXX/C=SE/CN=XXXX Certificate Authority
    ---
    No client certificate CA names sent
    ---
    SSL handshake has read 3846 bytes and written 519 bytes
    ---
    New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-GCM-SHA384
    Server public key is 4096 bit
    

    "No client certificate CA names sent" looks different to what I am expecting. I want client certificates.

    Where am I going wrong?