0

OS: Lubuntu 20.04 desktop (inside Virtualbox)

What happened

I've been using php -S 0.0.0.0:8080 -t /path/to/app/ to provide a simple web server.
But now I need to test my web app over https, and was hoping to use another simple one-liner.

I came across this article, Create a simple HTTPS server with OPENSSL S_SERVER, and followed the instructions:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
which generated key.pem and cert.pem

openssl s_server -key key.pem -cert cert.pem -accept 4433 -www
which started up with

Using default temp DH parameters
ACCEPT

Pointing the browsers (Chromium 123 and Firefox 125) at https://192.168.2.122:4433/ (and having answered 'take me to the page' in response to the self-signed certificate warning) they show the status page as per -www.

Notable lines:
Secure Renegotiation IS NOT supported
no client certificate available

Added (four times) to the terminal output is:

139808479769920:error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown:../ssl/record/rec_layer_s3.c:1543:SSL alert number 46  

Replacing -www with -WWW, and regardless of whether I give a file path, I get the same error on the terminal when a browser tries to connect. And on the browser I get:

Error opening ''
140068799104320:error:02001002:system library:fopen:No such file or directory:../crypto/bio/bss_file.c:69:fopen('','r')
140068799104320:error:2006D080:BIO routines:BIO_new_file:no such file:../crypto/bio/bss_file.c:76:

Web searches for answers

SSL alert number 46. Alert certificate unknown. How to ignore this exceptions?

...this alert is generated by the browser during the TLS handshake: the browser tells the server this way that it will not accept the certificate sent by the server. After this alert is sent the browser will close the connection.
The only way to fix this problem is to use a certificate trusted by the browser. In case of a self-signed certificate this means that you either have to import the certificate into the browser as trusted (in which case Subject Alternative Names in certificate must match the URL) or you add an explicit exception at the warning dialog you get when visiting the site.

There's no warning dialogue that takes care of this, so I can't take that option.

Ramifications of including "localhost" in the subject alternative field of an x509 certificate?

...you cannot know if this is your certificate for localhost or certificate of some other party. Thus, despite valid certificate, you would not know who you are talking to. A consequence is a possibility of man in the middle attack...

So I should not use localhost as a Subject Alternative Name.

Subject Alternative Name

These values are called Subject Alternative Names (SANs). Names include:2 Email addresses, IP addresses, ...

But I can (maybe) use my local ip address.

Which would/might be great if the questions asked at the terminal after issuing the openssl command to create a certificate and key included Subject Alternative Names.

In Let's Encrypt's Certificates for localhost under 'Making and trusting your own certificates', there's a slightly different openssl command (the does contain Subject Alternative Names) to create the certificate. (I still get the same result.) But then it says,

You can then configure your local web server with localhost.crt and localhost.key, and install localhost.crt in your list of locally trusted roots.

Aha, that last part might be the key, so to speak.

A very comprehensive answer to How to make browser trust localhost SSL certificate? shows the use of the command trust anchor path/to/cert.crt.

So, I tried that...
After a restart of Chromium...

With s_server -key localhost.key -cert localhost.crt -www the output still says, "no client certificate available".

And with -WWW, I still get "Error opening '' etc" on the browser. [edited for clarity]

Under the heading 'Trusting certificates in a browser':
"In Chromium, and Firefox you can add (import) certificates to Authorities tab."

I tried importing the certificate in Chromium: "Certificate import error: The Private Key for this Client Certificate is missing or invalid"

The private key is in the same directory as the certificate.

But, in Chromium under 'Other', it's already been imported :) and marked as 'UNTRUSTED' :(

Help!

[Edit] Update:
I managed to get the errors reported by Chromium's Inspect > Security tab down from two (Certificate - Subject Alternative name missing and Certificate - missing) to one by adding
-addext "subjectAltName = DNS:localhost" to the openssl req -x509 ... command. The detail of Certificate - missing is net::ERR_CERT_AUTHORITY_INVALID.

1 Answer 1

0

Notable lines:
Secure Renegotiation IS NOT supported
no client certificate available

With current browser(s) and nonancient OpenSSL, you got a TLSv1.3 connection (look at the bottom of the status page). TLSv1.3 no longer supports RFC5746 "secure renegotiation" because it no longer has any renegotiation of any kind at all.

Client-cert "not available" is not very good wording; it actually means "not sent by client". While not-available is one cause of this, there are other causes as well, and in general the server can't know what happened inside the client, only what the client ended up sending or not sending. In your case, it is most likely because you didn't request client-auth. For s_server to request client-auth aka client-cert, specify -verify {depth} (requested but accept connection if client doesn't send cert) or -Verify {depth} (requested and abort connection if client doesn't send cert). See man 1 openssl-s_server | less "+/ -verify". Depending on what cert(s) you want to use and have accepted, you may also need some of the -CA* and/or -verifyCA* options.

Replacing -www with -WWW, and regardless of whether I give a file path, I get the same error on the terminal (but now beginning 140068799104320) when a browser tries to connect.

The first number in the (ERR_print_errors*) error line is the thread id or process id and changes every time you run the program. The error is the 8-hexit value after the word error:.

And on the browser I get:
Error opening '' ... fopen('','r') ...

If the server is trying to open '' then it DIDN'T get any path in the URL. On my 20.04, which is admittedly WSL but is supposed to be identical userland, when I run -WWW and use my (Windows) browsers to request a valid path I get it, and when I request an invalid path I get an error page specifying that path and correctly saying it doesn't exist or is inaccessible or whatever.

https://stackoverflow.com/questions/57556909/ssl-alert-number-46-alert-certificate-unknown-how-to-ignore-this-exceptions
... import the certificate into the browser as trusted ... or you add an explicit exception at the warning dialog ....
There's no warning dialogue that takes care of this, so I can't take that option.

Yes there was -- the (interstitial) page that said some variation of "Danger Will Robinson self-signed certificate" was the warning dialog. And when you clicked "proceed anyway" that set the exception. In Firefox if you click on the padlock in the URLbar then the right arrow, it says "You have added a security exception for this site." For Chrome click the white-on-red X and it's stated a bit differently: "You have chosen to turn off security warnings for this site."

https://security.stackexchange.com/questions/255410/ramifications-of-including-localhost-in-the-subject-alternative-field-of-an-x5

Actually there's nothing wrong with using localhost in a cert you issue and use and trust by and for yourself only; it's issuing to or trusting somebody else (and especially a CA issuing to anybody) that causes problems. But leave that aside.

So, I tried [trust anchor]
... still says, "no client certificate available".

Of course. You still aren't requesting a client cert.

And with -WWW, I still get "Error opening `'..." on the browser

Before you said '', now you say '...' -- those are very different. If you are getting the path name in the error message then the server DID get the path. Are you sure the path you specified exists and is accessible relative to the working directory where you run the s_server process?

I tried importing the certificate in Chromium: "Certificate import error: The Private Key for this Client Certificate is missing or invalid"

I'm not sure what you did here, but you should not be importing the private key to the browser (client); the server private key should be used only by the server, which in your current case is s_server.

But, in Chromium under 'Other', it's already been imported :) and marked as 'UNTRUSTED' :(

Chrome/ium mostly uses the system store, i.e. on Ubuntu the Ubuntu truststore, and that's presumably where trust anchor (a Ubuntu sysadmin command) put your cert, or at least tried to. I haven't used that method and am not familiar with its requirements or any quirks. I use the update-ca-certificates approach instead (also known as dpkg-reconfigure ca-certificates).

3
  • Many thanks, Dave, for such a comprehensive answer. Who was the professor who said to a student, "I can explain it to you, but I can't understand it for you"? :D -verify seems to have no (useful) effect. I don't understand why the browser has to have its own certificate, or why update-ca-certificates isn't run each time there's a system update. And how can I do the equivalent on my Android phone so I can test those browsers? And, my /etc/ca-certificates.conf only contains lines beginning mozilla/, so presumably this won't help Chromium.
    – AlanQ
    Commented May 11 at 15:34
  • AlanQ: -verify REQUESTS a client cert; if you use TLS 1.2 (or lower, but you should use lower) you can see it in a network capture with Wireshark or similar. But it's still up to the client what cert if any to use; I don't know what keystore Chromium uses on Unix (or any non-Windows), and whatever it is yours may or may not have a usable cert-and-key. The browser needs to trust the server cert, and for client auth it needs to have access to a suitable cert-and-key; neither of those is necessarily 'its own' but both must exist and usually must be different. ... Commented May 13 at 3:14
  • ... I can't help with Android. The Ubuntu ca-certificates package (and most Linuxes I have seen) uses the root certs chosen by Mozilla but with perhaps a handful of obscure exceptions those are the same roots trusted by other programs and used by CAs, and are just fine for Chrome/ium (and also for OpenSSL/nodejs/python/php, NSS/Firefox, GnuTLS, Java, curl, wget, and more). Google has talked about setting up its own root program instead of using OS-supplied stores as now, but I haven't seen any concrete changes. Commented May 13 at 3:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .