New TLS-enabled "fossil server" feature
(1) By Richard Hipp (drh) on 2021-12-26 23:30:32 [link] [source]
I have code on a branch that lets the "fossil server" and "fossil ui" commands work with https instead of just http. To see it work, just come up with a self-signed cert and run:
fossil ui --tls-cert-file mycert.pem
There are a lot of details to fill in before this lands on trunk, but the basic idea seems to be work. On Unix. It is not clear to me how to get this to work with Winsock on Windows. If you have suggestions, please let me know.
Plans:
Get this working for "fossil http" as well.
Add a --acme option to enable the display of any files under the ".well-known" directory that is in the same directory as the repository. This will enable various ACME Protocol clients such as certbot to automatically obtain real certs from Let's Encrypt.
Add the ability to have separate private-key and cert files.
Add the ability to save the private-key and cert filenames as properties, so that TLS can be enabled with a single --tls option instead of having to specify the (combined) cert file as is required for this first prototype.
Get this working on Windows. (This depends on your help - see above.)
Self-signed cert how-to
The self-signed cert in the PEM format should be the concatenation of the private-key and the cert. You can generate it like this:
openssl genrsa -out private-key.pem openssl req -new -key private-key.pem -out request.csr openssl x509 -req -days 365 -in request.csr -signkey private-key.pem -out cert.pem cat private-key.pem cert.pem >mycert.pem ./fossil ui --tls-cert-file mycert.pem
(2) By Richard Hipp (drh) on 2021-12-27 13:41:32 in reply to 1 [link] [source]
With the latest code, you no longer have to mess with self-signed certs. There is a 100-year self-signed cert built into Fossil, which it uses if there are no other alternatives. So with the latest check-in you can just do:
fossil ui --tls
How to get this to work with Chrome?
With Firefox and Safari, when they see a self-signed certificate, they complain loadly, but with a few clicks you can tell them to accept the cert and carry on. But Chrome does not seem to allow this. Chrome would sooner use an unencrypted connection than a connection with a self-signed certificate. Anybody know what that is about?
(4.1) By Warren Young (wyoung) on 2022-01-04 18:44:47 edited from 4.0 in reply to 2 [link] [source]
I got it working without unusual agita…just the usual sort for self-signed certs. 🙄
One (bad) way around this is to download the certificate and add it to your OS's certificate store. Windows and macOS have double-clicky GUI tools for doing this. On Linux, it looks rather more complicated. Once done, reloading the Fossil page will make Chrome (or whatever else uses that OS cert store) look for a matching cert, find it, and load the page without complaint.
EDIT: The big problem with this is that if you decode the hard-coded cert in Fossil, you'll find that it has no Subject Name or SAN field, effectively making it a global wildcard certificate: it matches nothing in particular, so it matches everything. (If it did not, it would match nothing instead, so the feature wouldn't work.) The problem is, one could then take that hard-coded private cert straight out of Fossil's http_ssl.c
file and install it on any other service, and anything relying on that trust store will give that service equal trust because the matching public key is trusted at that global level, without being pinned to any DNS name or IP address.
Moral of the story: if you must use hard-coded certs, don't install them into OS's global trust store. They should only be pinned to a single domain name or IP somehow.
(11) By anonymous on 2022-01-02 10:10:48 in reply to 4.0 [link] [source]
This does mean that I can use the (publically available) fossil private key to MITM attack you for any secure website, of course.
I would VERY VERY STRONGLY recommend NOT TRUSTING the fossil self signed certificate, or any certificate where the private key is publicly available, as you have essentially broken SSL for yourself over the entire internet. Perhaps unlikely anyone would target you in this way, but they could. Certainly I could.
Might be worth including how to remove a certificate from the trust store, or amending your post...!
(12) By Richard Hipp (drh) on 2022-01-02 10:57:37 in reply to 11 [link] [source]
For Firefox at least (I don't know about the others) cert exceptions only apply to a single domain. So if somebody clicks through to access a self-signed cert on "myproject.net", that cert only works for "myproject.net" and you would only be able MITM that one site.
(13) By anonymous on 2022-01-02 19:09:58 in reply to 12 [link] [source]
Apologies - I think I was unclear.
You are completely correct about Firefox, and clicking through, similarly on all major browsers.
The risk I was referring to was the fourth post, suggesting adding this certificate to the OS trust store.
Ironically, this will also not bother Firefox as it doesn't use the OS cert store, but it would affect and essentially compromise all browsers that do use this store.
There is no issue with using the fossil self signed cert for test purposes but do not add the certificate to the OS trust store.
(14) By Richard Hipp (drh) on 2022-01-02 19:20:29 in reply to 13 [link] [source]
do not add the certificate to the OS trust store
I think that is an reasonable statement to put, in a bold font, in the documentation.
(15) By anonymous on 2022-01-02 19:28:32 in reply to 14 [link] [source]
Lovely, thank you.
(18) By Warren Young (wyoung) on 2022-01-04 18:46:35 in reply to 15 [link] [source]
I've edited the post up-thread.
Going forward, it'd be better if Fossil just generated this cert at need based on locally-observed host names and/or IPs, so that you could do as I originally suggested, safely.
That would also work around the 1-year limit on cert lifetimes someone else mentioned. You'd have to periodically refresh the cert, but that's just a small matter of deleting the old saved values (presumably in the config
table somewhere) so Fossil would re-generate a fresh key pair.
(5) By John Rouillard (rouilj) on 2021-12-27 23:23:52 in reply to 2 [link] [source]
There is also the 1 year limit on certificate lifetime. https://cisomag.eccouncil.org/tls-certificate-lifespan/
Initially, it was supposed to apply only to public PKI issued certs. But I think at least Mozilla may have included self-signed certs as well.
It's a little unclear.
Not sure you are tripping over this but....
(3) By anonymous on 2021-12-27 21:09:50 in reply to 1 [source]
One small issue with the /.well-known
page: The name
parameter which is used in the wellknown_page
function is not sanitized at the moment f81d64cace, therefore it is possible to use an URL like this 127.0.0.1:8080/.well-known?name=../etc/passwd
to escape out of the .well-known directory and download arbitrary files (if you can guess their name).
Just in case it is not already on the TODO list.
(6) By Richard Hipp (drh) on 2021-12-29 03:06:49 in reply to 1 [link] [source]
Update:
All 5 of the "Planned" improvements have been completed. The code now works for the "fossil http" command, and it works on Windows. Use the --acme command-line option to enable access to the ".well-known" directory in order to facilitate acquiring a certificate from Let's Encrypt. Key management is available with the "fossil ssl" command. In addition, a built-in self-signed cert is used if no other cert is specified, so just running "fossil ui --ssl" is sufficient to get an HTTPS connection (with Firefox - other browsers are a bit more fussy about self-signed certs).
You Can Help!
Please try out the new code and report problems.
Consider updating the How To Set Up A Server documentation to describe the new capabilities.
(7) By sean (jungleboogie) on 2021-12-29 17:36:30 in reply to 6 [link] [source]
Just so I understand, you have Fossil creating the TLS connection on port 8080, so that it doesn't require root/admin?
> .\fossil.exe ui -ssl myrepo.fossil
Launch webbrowser: start "" "https://localhost:8080/" &
Type Ctrl-C to stop the HTTP server
(8) By Richard Hipp (drh) on 2021-12-29 18:11:12 in reply to 7 [link] [source]
Correct.
I'm not sure what the rule is on Windows. Maybe an ordinary user can create a listening socket on port 443 on Windows. On Unix you have to be root to do that. Who can set me straight on this? (DuckDuckGo was not helpful in answering the question.)
(9) By sean (jungleboogie) on 2021-12-29 19:04:14 in reply to 8 [link] [source]
Maybe an ordinary user can create a listening socket on port 443 on Windows.
My user account without admin rights:
fossil server -P 440 .\repos\
Temporary files: C:\Users\SEAN\AppData\Local\Temp\fossil_server_P440*
Listening for HTTP requests on TCP port 440
Type Ctrl-C to stop the HTTP server
So looks like Windows doesn't have the same < 1024 port restriction unix does.
(10) By sean (jungleboogie) on 2021-12-29 20:22:52 in reply to 6 [link] [source]
As for the documentation on this page: https://fossil-scm.org/home/doc/trunk/www/ssl-server.md
from:
Beginning in late December 2021, this has been fixed. Commands like
to:
Beginning in late December 2021, this has been implemented for these commands:
Maybe in the usage section, explain the TLS connection will occur on port 8080, so that root access is not required.
The certbot link is broken and should be https://certbot.eff.org/
(16) By Stephan Beal (stephan) on 2022-01-04 17:44:44 in reply to 1 [link] [source]
cat private-key.pem cert.pem > mycert.pem
i'm currently setting up a VPS, just got my first-ever certificate via certbot, and now have a very slight concern about that bit.
Certbot places the private key and cert files in separate files and the certbot process on Ubuntu sets up auto-renewal of those certs. The implications of that are:
Ideally, fossil could be told the name of the private key and public cert separately, in order to avoid having to make copies of those files (which may change out from under us).
For a standalone fossil server, fossil should arguably check now and then whether those files have been modified since it started, and reload them if needed. This might be a moot point: if the certs are loaded anew in each forked copy then this is irrelevant. If they're loaded before the first fork, though, it is relevant.
Opinions? If those sound relevant/desired, i'll do the patching.
(17) By sean (jungleboogie) on 2022-01-04 18:43:17 in reply to 16 [link] [source]
It's been some years since I've setup and played with TLS certs that I've had to purchase so I am a bit fuzzy with these details...
For point one, are you saying Fossil could be patched to virtually cat the two files together at run time? That may not be a nice improvement. Do you think changing the file permissions would be a good idea?
For the second point, i think people setup certbot as a cronjob and will run with the time comes. It would be pretty neat to have Fossil autocheck if the TLS cert changes and use it, better than having an expired TLS cert for the repo.
(20) By Chris (crustyoz) on 2022-01-04 18:59:29 in reply to 17 [link] [source]
This is exactly the problem I faced with the Hiawatha web server requiring a single PEM file containing both private key and public key chain.
The server (fossil or hiawatha) needs to be restarted to recognise the PEM file change. Certbot has a hook capability that handles this. Any script located in /etc/letsencrypt/renewal-hooks/deploy will be executed for each successful certificate renewal. There is an environment variable that defines the directory with the updated certificate files: RENEWED_LINEAGE that can be used to ensure the cat'ed file is correctly placed:
cat $RENEWED_LINEAGE/privkey.pem $RENEWED_LINEAGE/fullchain.pem > $RENEWED_LINEAGE/everything.pem
systemctl restart hiawatha
The server still needs to know where to find the cat'ed file.
(23) By Stephan Beal (stephan) on 2022-01-04 19:06:15 in reply to 20 [link] [source]
Certbot has a hook capability that handles this.
Great, thank you for these details. That looks like everything i need for this purpose :).
(22) By Stephan Beal (stephan) on 2022-01-04 19:02:59 in reply to 17 [link] [source]
For point one, are you saying Fossil could be patched to virtually cat the two files together at run time?
Correct.
That may not be a nice improvement. Do you think changing the file permissions would be a good idea?
Why would permissions need to change? It has to be able to read the certs in order to apply them, so it could just as easily concat them into a buffer and... Aha, i'm assuming that libssl can take the cert/key combo in the form of a memory blob instead of a file, and i have no idea if that's really the case. If it can't then my request is fundamentally broken.
Aha... that can't work, can it. When fossil starts up as root, it can of course read those, but it drops root permissions at some point, so loses access to them.
It would be pretty neat to have Fossil autocheck if the TLS cert changes and use it, better than having an expired TLS cert for the repo.
A "poor man's" variant is simply to record the cert's timestamp at startup and check it timestamp before each request. However, auto-certbot-updates won't know that they need to concat two files, so any update process would require scripting on the user's part.
(19) By Warren Young (wyoung) on 2022-01-04 18:55:52 in reply to 16 [link] [source]
Certbot places the private key and cert files in separate files
On purpose: it allows each half of the key-pair have different permissions. It's good practice to give the private half more stringent protection than the public half.
All one should about for the public half is that randos can't overwrite or change the file, but read it, sure, go ahead.
The private half should only be readable by the two processes that must do so: certbot and the service process it minted the cert for. Indeed, private certs are often placed into a directory others can't even ls
or cd
into.
those files…may change out from under us
On about a once every two months schedule for LE, yes. That's a pretty tiny time window to hit, especially considering POSIX file semantics, where someone reading an overwritten file keeps reading the old file until they close it, then re-opening it causes them to see the new content.
(I'm assuming certbot doesn't open the output files and rewrite them in place, because why would it?)
You have one reader (Fossil), and one writer (certbot), so all the hoops SQLite has to jump through to make its read-write I/O work safely don't apply here.
(21) By Richard Hipp (drh) on 2022-01-04 19:00:00 in reply to 16 [link] [source]
Ideally, fossil could be told the name of the private key and public cert separately
The "fossil ssl-config load-cert --filename PRIVATEKEY CERT" should do that for you. It isn't well-documented. Documentation needs work.
if the certs are loaded anew in each forked copy then this is irrelevant
IIRC the certs are loaded before the fork() with "fossil server". However if you configure xinetd or systemd, then the certs are loaded after the fork() (obviously, since the fork happens inside of xinetd or systemd) and then your problem should be solved.