2

I'm trying to use a service that uses a self-signed cert.

  1. Download the cert:

    # printf QUIT | openssl s_client -connect my-server.net:443 -showcerts 2>/dev/null >  my-server.net.crt
    
  2. Check that it's self signed (issuer and subject are the same):

    # openssl x509 -subject -issuer -noout -in my-server.net.crt
    subject=O = Acme Co, CN = Controller Fake Certificate
    issuer=O = Acme Co, CN = Controller Fake Certificate
    
  3. Try to use it with curl's --cacert option:

    # curl https://my-server.net  --cacert my-server.net.crt
    curl: (60) SSL certificate problem: unable to get local issuer certificate
    More details here: https://curl.haxx.se/docs/sslcerts.html
    
    curl failed to verify the legitimacy of the server and therefore could not
    establish a secure connection to it. To learn more about this situation and
    how to fix it, please visit the web page mentioned above.
    

I don't understand why curl cannot verify the cert.

Mike Ounsworth
  • 57,707
  • 21
  • 150
  • 207
little-dude
  • 137
  • 1
  • 6
  • 1
    For diagnostics, connecting to your server with your browser will probably give more detailed info about the certificate error than curl does. – Mike Ounsworth Aug 16 '18 at 20:03
  • 4
    Is this really a CA certificate, i.e. has it basic constrains CA true? Otherwise it will be ignored by `--cacert`. – Steffen Ullrich Aug 16 '18 at 20:04
  • @SteffenUllrich you're right it has: `CA:FALSE` – little-dude Aug 16 '18 at 20:43
  • @SteffenUllrich if you add this as an answer, I'll mark it as the accepted answer. – little-dude Aug 16 '18 at 21:08
  • 1
    In general `s_client -showcerts >file` gets the entire _chain_ sent by the server, but `x509 -in file` displays only the first one while `curl --cacert file` or `s_client -CAfile file` would use _all_ of them. However when the leaf cert is selfsigned as here, the server _shouldn't_ be sending any (additional) chain certs. – dave_thompson_085 Aug 17 '18 at 03:13

2 Answers2

3

From the comments:

Is this really a CA certificate, i.e. has it basic constrains CA true? ... – Steffen Ullrich
@SteffenUllrich you're right it has: CA:FALSE – little-dude

Signing a certificate requires that the issuer certificate must have the correct flags so that signing is actually allowed. To correctly sign a certificate the issuer certificate need to have the basic constraints CA set to true. This is true both when signing another certificate as for signing the same certificate (i.e. self-signed). It looks like the certificate had not the correct CA:true flag in the case here.

Moreover, the --cacert option is like its name says only for CA certificates and not for arbitrary certificates. For example if you have the leaf-certificates of a site you cannot just add is as trusted with --cacert since it is (usually) not a CA certificate. It will simply be ignored when reading the certificates from the given file.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
1

Two guesses:

1. Is it allowed to do Server authentication?

Check the Extended / Enhanced Key Usage field of your self-signed cert.

Enhanced Key Usage field of a certificate showing Server Authentication

2. Does the server's hostname appear in the CN or SAN fields?

Curl is going to check that the certificate returned by the server matches the hostname you requested (my-server.net).

Mike Ounsworth
  • 57,707
  • 21
  • 150
  • 207
  • So for the certificate key usages, Firefox lists `Not Critical, Signing, Encipherment`, and extended key usages: `Not Critical, TLS Web Server Authentication`. The Alt Names are listed correctly. So I guess that is all good. The reason it's not working with curl is probably because it has `CA:FALSE` as noted by @SteffenUllrich, then? – little-dude Aug 16 '18 at 20:47
  • 1
    @little-dude Cool. Out of curiosity, how on earth did you manage to generate a self-signed certificate that's not a CA? That is, by definition, an invalid certificate. Does OpenSSL even let you do that? – Mike Ounsworth Aug 16 '18 at 20:57
  • I did not generate it myself, I don't manage that server. I'm going to ask the question and report back :) – little-dude Aug 16 '18 at 20:59
  • Actually, from the CN (`Kubernetes Ingress Controller Fake Certificate` which I shortened a bit in my OP), it looks like the cert if generated by some kubernetes component: https://github.com/kubernetes/ingress-nginx/issues/1984 – little-dude Aug 16 '18 at 21:03
  • @little-dude Hmm. Maybe self-signed certs are allowed to have `CA:False` -- ie they can sign themself, but not any other certs. I'll have to look that up when I'm at a computer. – Mike Ounsworth Aug 16 '18 at 21:07
  • 1
    I still don't know why `ingress-nginx` controller generates these weird certificates, but I know _why_ it served it to me. The server implements [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication) and if I don't specify `-servername` with openssl, it served me this default cert instead of the "real" one. – little-dude Aug 17 '18 at 17:45