jart / cosmopolitan

build-once run-anywhere c library
ISC License
18.32k stars 628 forks source link

Redbean and letsencrypt? #816

Open vortinen opened 1 year ago

vortinen commented 1 year ago

As far as I can tell, redbean's SSL cert and key are set at initialization with Program* or -C/-K, and can't be changed after that. This makes using letsencrypt/zerossl tricky, since the server needs to be restarted to update the certificate.

Is there a way to avoid this? Would it be feasible to change ProgramCertificate and ProgramPrivateKey to be called after initialization?

pkulchenko commented 1 year ago

My understanding that the key can be changed, but you may need to call (not yet documented) function ProgramSslInit after the keys have changed. See #360 for the changes I made to introduce the function and maybe #435 for some related ideas.

Can you test if that works for your use case and report back?

vortinen commented 1 year ago

Thanks for the pointer Paul. It does indeed look like TlsInit can be called after init, but the wrapping LuaProgramSslInit is guarded by OnlyCallFromInitLua. That was added in this commit - @jart @pkulchenko what do you think about removing it?

This may also need a way of passing the new certificates before calling ProgramSslInit. I tried removing the init check from ProgramCertificate and ProgramPrivateKey as well, and didn't see any change in the reported public key after running

>: ProgramCertificate(Slurp("new_cert.pem"))
>: ProgramPrivateKey(Slurp("new_key.pem"))
>: ProgramSslInit()

Using openssl s_client -connect localhost:8080 </dev/null | openssl x509 -inform pem -text.

But I'm not sure what these functions are really doing :)

pkulchenko commented 1 year ago

That was added in this commit - @jart @pkulchenko what do you think about removing it?

Yes, this is definitely something that can be adjusted, but it shouldn't prevent you from calling it from REPL. Where are you trying to call it from?

This may also need a way of passing the new certificates before calling ProgramSslInit. I tried removing the init check from ProgramCertificate and ProgramPrivateKey as well, and didn't see any change in the reported public key after running.

I don't think certificates are reloaded when ProgramSslInit() is being executed. Can you try moving LoadCertificates call before the sslinitialized check in ProgramSslInit()?

  LoadCertificates(); --<-- move it here
  if (sslinitialized) return;
  sslinitialized = true;
vortinen commented 1 year ago

Thanks Paul, I'm hoping to call this from somewhere in .lua/ - my idea here is to fork a process and run dehydrated periodically, to simplify deployments.

Below are some debug logs after your suggested change. Based on the ProgramSslInit serial numbers it looks like the new cert isn't being picked up. I'll dig into why tomorrow unless you have any thoughts here?

D2023-05-21T06:14:13.645027:tool/net/redbean.c:5016:redbean:1181368] (lua) LuaRunAsset("/.init.lua")
I2023-05-21T06:14:13+000060:tool/net/redbean.c:7060:redbean:1181368] (srvr) listen http://127.0.0.1:8080
I2023-05-21T06:14:13+000017:tool/net/redbean.c:7060:redbean:1181368] (srvr) listen http://192.168.0.144:8080
I2023-05-21T06:14:13+000014:tool/net/redbean.c:7060:redbean:1181368] (srvr) listen http://100.89.89.116:8080
E2023-05-21T06:14:13+000062:(null):0:redbean:1181368] (added by vortinen in TlsIinit) loading certificates
V2023-05-21T06:14:13+000005:tool/net/redbean.c:2016:redbean:1181368] (ssl) could not find non-CA SSL certificate key pair with -addext keyUsage=digitalSignature -addext extendedKeyUsage=serverAuth
V2023-05-21T06:14:13+000005:tool/net/redbean.c:2019:redbean:1181368] (ssl) could not find CA key signing key pair with -addext keyUsage=keyCertSign
V2023-05-21T06:14:13+000004:tool/net/redbean.c:2021:redbean:1181368] (ssl) generating self-signed ssl certificates
D2023-05-21T06:14:13+001246:net/https/logcertificate.c:28:redbean:1181368] generated EC certificate
 cert. version     : 3
 serial number     : 98:02:22:BA:78:B7:21:BC:E0:D7:13:B3:83:29:31:89
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-20 13:14:13
 expires on        : 2024-05-21 13:14:13
 signed using      : ECDSA with SHA256
 EC key size       : 256 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-21T06:14:13+000017:tool/net/redbean.c:688:redbean:1181368] (ssl) using EC certificate "CN=blah" for HTTPS server
D2023-05-21T06:14:13+082055:net/https/logcertificate.c:28:redbean:1181368] generated RSA certificate
 cert. version     : 3
 serial number     : FA:B1:CC:CD:40:9A:C4:D4:AB:18:AF:22:41:D2:36:52
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-20 13:14:13
 expires on        : 2024-05-21 13:14:13
 signed using      : RSA with SHA-256
 RSA key size      : 2048 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature, Key Encipherment
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-21T06:14:13+000008:tool/net/redbean.c:688:redbean:1181368] (ssl) using RSA certificate "CN=blah" for HTTPS server
E2023-05-21T06:14:13+000878:(null):0:redbean:1181368] (added by vortinen in TlsIinit) finished TlsInit
D2023-05-21T06:14:13+000019:tool/net/redbean.c:7128:redbean:1181368] ReplEventLoop()
D2023-05-21T06:14:13+000045:tool/net/redbean.c:7098:redbean:1181368] (repl) event loop

>: ProgramCertificate(Slurp("cert1.pem"))
D2023-05-21T06:14:16.306708:net/https/logcertificate.c:28:redbean:1181368] loaded certificate
 cert. version     : 3
 serial number     : 2C:AE:B8:E1:A3:07:72:32:68:D7:20:FE:CB:48:60:AE:25:1F:D2:3D
 issuer name       : C=XX, ST=StateName, L=CityName, O=CompanyName, OU=CompanySectionName, CN=CommonNameOrHostname
 subject name      : C=XX, ST=StateName, L=CityName, O=CompanyName, OU=CompanySectionName, CN=CommonNameOrHostname
 issued  on        : 2023-05-15 09:41:59
 expires on        : 2033-05-12 09:41:59
 signed using      : RSA with SHA-256
 RSA key size      : 4096 bits
 basic constraints : CA=true

>: ProgramPrivateKey(Slurp("key1.pem"))

>: ProgramSslInit()
E2023-05-21T06:14:22.594496:(null):0:redbean:1181368] (added by vortinen in TlsIinit) loading certificates
D2023-05-21T06:14:22+000022:net/https/logcertificate.c:28:redbean:1181368] using server certificate
 cert. version     : 3
 serial number     : 98:02:22:BA:78:B7:21:BC:E0:D7:13:B3:83:29:31:89
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-20 13:14:13
 expires on        : 2024-05-21 13:14:13
 signed using      : ECDSA with SHA256
 EC key size       : 256 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-21T06:14:22+000019:tool/net/redbean.c:688:redbean:1181368] (ssl) using EC certificate "CN=blah" for HTTPS server
D2023-05-21T06:14:22+000014:net/https/logcertificate.c:28:redbean:1181368] using client certificate
 cert. version     : 3
 serial number     : 98:02:22:BA:78:B7:21:BC:E0:D7:13:B3:83:29:31:89
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-20 13:14:13
 expires on        : 2024-05-21 13:14:13
 signed using      : ECDSA with SHA256
 EC key size       : 256 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-21T06:14:22+000021:tool/net/redbean.c:688:redbean:1181368] (ssl) using EC certificate "CN=blah" for HTTPS client
D2023-05-21T06:14:22+000012:net/https/logcertificate.c:28:redbean:1181368] using server certificate
 cert. version     : 3
 serial number     : FA:B1:CC:CD:40:9A:C4:D4:AB:18:AF:22:41:D2:36:52
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-20 13:14:13
 expires on        : 2024-05-21 13:14:13
 signed using      : RSA with SHA-256
 RSA key size      : 2048 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature, Key Encipherment
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-21T06:14:22+000020:tool/net/redbean.c:688:redbean:1181368] (ssl) using RSA certificate "CN=blah" for HTTPS server
D2023-05-21T06:14:22+000011:net/https/logcertificate.c:28:redbean:1181368] using client certificate
 cert. version     : 3
 serial number     : FA:B1:CC:CD:40:9A:C4:D4:AB:18:AF:22:41:D2:36:52
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-20 13:14:13
 expires on        : 2024-05-21 13:14:13
 signed using      : RSA with SHA-256
 RSA key size      : 2048 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature, Key Encipherment
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-21T06:14:22+000012:tool/net/redbean.c:688:redbean:1181368] (ssl) using RSA certificate "CN=blah" for HTTPS client

>:
pkulchenko commented 1 year ago

@vortinen, I may be misinterpreting what's going on here, but I suspect it has something to do with the certificates you're using.

Let's go step by step over this:

  1. You can use ProgramCertificate and ProgramPrivateKey to load certificates/keys you need. You don't need to call anything else (like ProgramSslInit) if you call these functions before the server is loaded. Does this work for you (do you see the certificates loaded) or not? For example, you can use (-K/-C command line options) to pass the certificates:

    -K PATH | tls private key path              [repeatable]
    -C PATH | tls certificate(s) path           [repeatable]
  2. If it does work, then you can try (1) not loading the certificates, (2) starting the server, and (3) then running ProgramCerfiticate and ProgramPrivateKey functions from the main server process to load any additional keys (for example, from OnServerHeartbeat hook); in this case you'd need to call the modified ProgramSslInit function, as it would reload certificates. This is not going to have the desired effect when you run it from a forked process, even though it should still work (just within the context of the forked process without any impact on the main server instance).

This looks like this is exactly what you're doing in your trace/example, so I think you can skip this step (but I'll keep it here in case for completeness someone else runs into the same issue).

  1. If it does not work, then there is something with the certificates that prevents them from loading. There are only 3 things in LoadCertificate call that can do this:
    if (certs.p[i].key && certs.p[i].cert && !certs.p[i].cert->ca_istrue && // 1. !certs.p[i].cert->ca_istrue check
        !mbedtls_x509_crt_check_key_usage(certs.p[i].cert,                       // 2. KU_DIGITAL_SIGNATURE check
                                          MBEDTLS_X509_KU_DIGITAL_SIGNATURE)) {
      if (!mbedtls_x509_crt_check_extended_key_usage(
              certs.p[i].cert, MBEDTLS_OID_SERVER_AUTH,                          // 3. MBEDTLS_OID_SERVER_AUTH check
              MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH))) {
        LogCertificate("using server certificate", certs.p[i].cert);
        UseCertificate(&conf, certs.p + i, "server");
        havecert = true;
      }

You may want to modify this function to see which of these checks is failing on the key/cert you're loading.

I suspect that in this case this has something to do with the last option and there is something in the certificate you're using that doesn't pass one of these checks for some reason.

I'm hoping to call this from somewhere in .lua/ - my idea here is to fork a process and run dehydrated periodically, to simplify deployments.

As I mentioned earlier in my comment, the certificates need to be loaded from the main process, so you'll have to save them in a file and then send some signal to the main process to re-read the files and load the updated/new certificates, otherwise it's not going to affect the current server configuration.

vortinen commented 1 year ago

Thanks for the detailed instructions Paul, some progress: it seems the keys are indeed being loaded correctly, but then possibly being ignored. Read on.

Step 1

I've generated some keys using the command shown on redbean.dev:

openssl req -x509 -newkey rsa:2048 \
  -keyout certs/ca.key -out certs/ca.crt -days 6570 -nodes \
  -subj '/C=US/ST=CA/O=Jane Doe/CN=My Root CA 1' \
  -addext 'keyUsage = critical,cRLSign,keyCertSign'

And loaded them with -C/-K as follows on unmodified redbean commit cc1732bc4:

build/redbean.com -vvv -C certs/ca.crt -K certs/ca.key
D2023-05-26T04:34:00.813766:tool/net/redbean.c:802:redbean:1429308] (srvr) ProgramFile("certs/ca.crt")
D2023-05-26T04:34:00+000101:net/https/logcertificate.c:28:redbean:1429308] loaded certificate
 cert. version     : 3
 serial number     : 4F:7E:F6:BD:07:2E:80:FB:45:3F:CB:14:38:8D:29:FE:04:FF:18:58
 issuer name       : C=US, ST=CA, O=Jane Doe, CN=My Root CA 1
 subject name      : C=US, ST=CA, O=Jane Doe, CN=My Root CA 1
 issued  on        : 2023-05-26 11:32:55
 expires on        : 2041-05-21 11:32:55
 signed using      : RSA with SHA-256
 RSA key size      : 2048 bits
 basic constraints : CA=true
 key usage         : Key Cert Sign, CRL Sign
D2023-05-26T04:34:00+000017:tool/net/redbean.c:802:redbean:1429308] (srvr) ProgramFile("certs/ca.key")
D2023-05-26T04:34:00+000142:tool/net/redbean.c:5016:redbean:1429308] (lua) LuaRunAsset("/.init.lua")
I2023-05-26T04:34:00+000057:tool/net/redbean.c:7060:redbean:1429308] (srvr) listen http://127.0.0.1:8080
I2023-05-26T04:34:00+000018:tool/net/redbean.c:7060:redbean:1429308] (srvr) listen http://192.168.0.144:8080
I2023-05-26T04:34:00+000018:tool/net/redbean.c:7060:redbean:1429308] (srvr) listen http://100.89.89.116:8080
D2023-05-26T04:34:00+000053:tool/net/redbean.c:2013:redbean:1429308] (ssl) generating ssl certificates using "C=US, ST=CA, O=Jane Doe, CN=My Root CA 1"
D2023-05-26T04:34:00+005165:net/https/logcertificate.c:28:redbean:1429308] generated EC certificate
 cert. version     : 3
 serial number     : 74:EE:27:F6:60:B7:7B:BA:A7:58:09:F9:04:61:57:30
 issuer name       : C=US, ST=CA, O=Jane Doe, CN=My Root CA 1
 subject name      : CN=blah
 issued  on        : 2023-05-25 11:34:00
 expires on        : 2024-05-26 11:34:00
 signed using      : RSA with SHA-256
 EC key size       : 256 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-26T04:34:00+000018:tool/net/redbean.c:688:redbean:1429308] (ssl) using EC certificate "CN=blah" for HTTPS server
V2023-05-26T04:34:00+000006:tool/net/redbean.c:688:redbean:1429308] (ssl) using EC certificate "CN=blah" for HTTPS client
D2023-05-26T04:34:00+149295:net/https/logcertificate.c:28:redbean:1429308] generated RSA certificate
 cert. version     : 3
 serial number     : 8E:85:77:A0:8C:EB:AE:05:02:CE:D9:CA:5D:16:E9:27
 issuer name       : C=US, ST=CA, O=Jane Doe, CN=My Root CA 1
 subject name      : CN=blah
 issued  on        : 2023-05-25 11:34:00
 expires on        : 2024-05-26 11:34:00
 signed using      : RSA with SHA-256
 RSA key size      : 2048 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature, Key Encipherment
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-26T04:34:00+000008:tool/net/redbean.c:688:redbean:1429308] (ssl) using RSA certificate "CN=blah" for HTTPS server
V2023-05-26T04:34:00+000002:tool/net/redbean.c:688:redbean:1429308] (ssl) using RSA certificate "CN=blah" for HTTPS client
D2023-05-26T04:34:00+000904:tool/net/redbean.c:7128:redbean:1429308] ReplEventLoop()
D2023-05-26T04:34:00+000040:tool/net/redbean.c:7098:redbean:1429308] (repl) event loop
>:

From the logs, Redbean does correctly load the certs!

This might be my ignorance of SSL but I'm surprised redbean generates new certs. If they're somehow derived from 4F:7E and this is WAI then I think we're done as - spoiler - step 2 shows the same pattern :) If not, that seems like a bug?

Step 2

Doing this for completeness. tldr: same thing. The keys are being loaded successfully with the modified redbean (yay!) but generated keys are in the picture.

Here's my redbean.c diff:

diff --git a/tool/net/redbean.c b/tool/net/redbean.c
index a80f0abe4..3d848a832 100644
--- a/tool/net/redbean.c
+++ b/tool/net/redbean.c
@@ -4608,7 +4608,7 @@ static int LuaProgramSslCiphersuite(lua_State *L) {
 static int LuaProgramPrivateKey(lua_State *L) {
   size_t n;
   const char *p;
-  OnlyCallFromInitLua(L, "ProgramPrivateKey");
+  //OnlyCallFromInitLua(L, "ProgramPrivateKey");
   p = luaL_checklstring(L, 1, &n);
   ProgramPrivateKey(p, n);
   return 0;
@@ -4617,7 +4617,7 @@ static int LuaProgramPrivateKey(lua_State *L) {
 static int LuaProgramCertificate(lua_State *L) {
   size_t n;
   const char *p;
-  OnlyCallFromInitLua(L, "ProgramCertificate");
+  //OnlyCallFromInitLua(L, "ProgramCertificate");
   p = luaL_checklstring(L, 1, &n);
   ProgramCertificate(p, n);
   return 0;
@@ -4660,7 +4660,7 @@ static int LuaProgramSslFetchVerify(lua_State *L) {
 }

 static int LuaProgramSslInit(lua_State *L) {
-  OnlyCallFromInitLua(L, "SslInit");
+  //OnlyCallFromInitLua(L, "SslInit");
   TlsInit();
   return 0;
 }
@@ -7214,10 +7214,11 @@ static void TlsInit(void) {
                                         mbedtls_ssl_ticket_parse, &ssltick);
   }

+  flogf(1, 0, 0, NULL, "%s", "LOADED CERTIFICATES BEFORE RETURNING");
+  LoadCertificates();
   if (sslinitialized) return;
   sslinitialized = true;

-  LoadCertificates();
   mbedtls_ssl_conf_sni(&conf, TlsRoute, 0);
   mbedtls_ssl_conf_dbg(&conf, TlsDebug, 0);
   mbedtls_ssl_conf_dbg(&confcli, TlsDebug, 0);

And my .init.lua is simply:

function OnServerHeartbeat()
  Log(kLogError, "STARTED SERVER HEARTBEAT")
  ProgramPrivateKey(Slurp("certs/ca.key"))
  ProgramCertificate(Slurp("certs/ca.crt"))
  ProgramSslInit()
  Log(kLogError, "FINISHED SERVER HEARTBEAT")
end

Here's one heartbeat:

E2023-05-26T05:01:04.660952:/zip/.init.lua:2:changeme:1432832] STARTED SERVER HEARTBEAT
D2023-05-26T05:01:04+000150:net/https/logcertificate.c:28:changeme:1432832] loaded certificate
 cert. version     : 3
 serial number     : 4F:7E:F6:BD:07:2E:80:FB:45:3F:CB:14:38:8D:29:FE:04:FF:18:58
 issuer name       : C=US, ST=CA, O=Jane Doe, CN=My Root CA 1
 subject name      : C=US, ST=CA, O=Jane Doe, CN=My Root CA 1
 issued  on        : 2023-05-26 11:32:55
 expires on        : 2041-05-21 11:32:55
 signed using      : RSA with SHA-256
 RSA key size      : 2048 bits
 basic constraints : CA=true
 key usage         : Key Cert Sign, CRL Sign
E2023-05-26T05:01:04+000019:(null):0:changeme:1432832] LOADED CERTIFICATES BEFORE RETURNING
D2023-05-26T05:01:04+000014:net/https/logcertificate.c:28:changeme:1432832] using server certificate
 cert. version     : 3
 serial number     : 06:16:D4:20:BC:71:DB:F4:15:43:09:5F:7A:B2:11:40
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-25 12:00:14
 expires on        : 2024-05-26 12:00:14
 signed using      : ECDSA with SHA256
 EC key size       : 256 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-26T05:01:04+000013:tool/net/redbean.c:688:changeme:1432832] (ssl) using EC certificate "CN=blah" for HTTPS server
D2023-05-26T05:01:04+000014:net/https/logcertificate.c:28:changeme:1432832] using client certificate
 cert. version     : 3
 serial number     : 06:16:D4:20:BC:71:DB:F4:15:43:09:5F:7A:B2:11:40
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-25 12:00:14
 expires on        : 2024-05-26 12:00:14
 signed using      : ECDSA with SHA256
 EC key size       : 256 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-26T05:01:04+000012:tool/net/redbean.c:688:changeme:1432832] (ssl) using EC certificate "CN=blah" for HTTPS client
D2023-05-26T05:01:04+000013:net/https/logcertificate.c:28:changeme:1432832] using server certificate
 cert. version     : 3
 serial number     : 8B:6E:42:2A:A5:27:CD:F1:A8:94:0B:18:85:29:3C:B8
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-25 12:00:14
 expires on        : 2024-05-26 12:00:14
 signed using      : RSA with SHA-256
 RSA key size      : 2048 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature, Key Encipherment
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-26T05:01:04+000013:tool/net/redbean.c:688:changeme:1432832] (ssl) using RSA certificate "CN=blah" for HTTPS server
D2023-05-26T05:01:04+000011:net/https/logcertificate.c:28:changeme:1432832] using client certificate
 cert. version     : 3
 serial number     : 8B:6E:42:2A:A5:27:CD:F1:A8:94:0B:18:85:29:3C:B8
 issuer name       : CN=blah
 subject name      : CN=blah
 issued  on        : 2023-05-25 12:00:14
 expires on        : 2024-05-26 12:00:14
 signed using      : RSA with SHA-256
 RSA key size      : 2048 bits
 basic constraints : CA=false
 subject alt name  :
     iPAddress : 192.168.0.144
     iPAddress : 100.89.89.116
 key usage         : Digital Signature, Key Encipherment
 ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
V2023-05-26T05:01:04+000014:tool/net/redbean.c:688:changeme:1432832] (ssl) using RSA certificate "CN=blah" for HTTPS client
E2023-05-26T05:01:04+000007:/zip/.init.lua:6:changeme:1432832] FINISHED SERVER HEARTBEAT

The "CN=blah" certs are generated by redbean, and the "C=US ..." keys are my self-signed certs. It looks like the generated certs are being chosen.

Step 3

I'll skip this since it looks like the certs are loaded correctly.

Misc

As I mentioned earlier in my comment, the certificates need to be loaded from the main process, so you'll have to save them in a file and then send some signal to the main process to re-read the files and load the updated/new certificates, otherwise it's not going to affect the current server configuration.

Yes this makes sense, thanks for pointing it out.

pkulchenko commented 1 year ago

@vortinen, the only strange thing I can see is that the loaded certificate is kind of issued in the future (although this may still be local time vs GMT, not sure):

D2023-05-26T04:34:00+000101:net/https/logcertificate.c:28:redbean:1429308] loaded certificate
 cert. version     : 3
 serial number     : 4F:7E:F6:BD:07:2E:80:FB:45:3F:CB:14:38:8D:29:FE:04:FF:18:58
 issuer name       : C=US, ST=CA, O=Jane Doe, CN=My Root CA 1
 subject name      : C=US, ST=CA, O=Jane Doe, CN=My Root CA 1
 issued  on        : 2023-05-26 11:32:55

The "local" time appears to be 05-26 04:34, but the cert is issued on 05-26 11:32, so it's not a surprise that it's not being applied, as it's not valid yet. Can you check the issuance time and see if fixing it changes something in the result?

This might be my ignorance of SSL but I'm surprised redbean generates new certs.

I'm surprised a bit myself, but suspect that's the outcome of the timing issue, as it doesn't say using server certificate for 4F:7E:... cert, so it likely fails on mbedtls_x509_crt_check_key_usage. I think more DEBUG logging on these failures would be helpful in troubleshooting this issue.

vortinen commented 1 year ago

Thanks for bearing with me, you were exactly right :) The self-signed cert was failing both the ca_istrue and KU_DIGITAL_SIGNATURE checks, but using a proper letsencrypt cert works as expected.

This now works with the final diff below. Would you accept a PR?

diff --git a/tool/net/redbean.c b/tool/net/redbean.c
index a80f0abe4..63424a9ed 100644
--- a/tool/net/redbean.c
+++ b/tool/net/redbean.c
@@ -4608,7 +4608,6 @@ static int LuaProgramSslCiphersuite(lua_State *L) {
 static int LuaProgramPrivateKey(lua_State *L) {
   size_t n;
   const char *p;
-  OnlyCallFromInitLua(L, "ProgramPrivateKey");
   p = luaL_checklstring(L, 1, &n);
   ProgramPrivateKey(p, n);
   return 0;
@@ -4617,7 +4616,6 @@ static int LuaProgramPrivateKey(lua_State *L) {
 static int LuaProgramCertificate(lua_State *L) {
   size_t n;
   const char *p;
-  OnlyCallFromInitLua(L, "ProgramCertificate");
   p = luaL_checklstring(L, 1, &n);
   ProgramCertificate(p, n);
   return 0;
@@ -4660,7 +4658,6 @@ static int LuaProgramSslFetchVerify(lua_State *L) {
 }

 static int LuaProgramSslInit(lua_State *L) {
-  OnlyCallFromInitLua(L, "SslInit");
   TlsInit();
   return 0;
 }
@@ -7214,10 +7211,10 @@ static void TlsInit(void) {
                                         mbedtls_ssl_ticket_parse, &ssltick);
   }

+  LoadCertificates();
   if (sslinitialized) return;
   sslinitialized = true;

-  LoadCertificates();
   mbedtls_ssl_conf_sni(&conf, TlsRoute, 0);
   mbedtls_ssl_conf_dbg(&conf, TlsDebug, 0);
   mbedtls_ssl_conf_dbg(&confcli, TlsDebug, 0);
pkulchenko commented 1 year ago

The self-signed cert was failing both the ca_istrue and KU_DIGITAL_SIGNATURE checks, but using a proper letsencrypt cert works as expected.

Any idea why it was failing? The self-signed one that is generated by redbean is passing these checks, right?

This now works with the final diff below. Would you accept a PR?

I think so, although I'd consider the following changes:

If you want to submit a PR with these changes, you need to assign your copyright to Justine Tunney (the creator of the project), see https://github.com/jart/cosmopolitan/blob/master/CONTRIBUTING.md#copyright-assignment for details and reasoning.