It's unnecessary and can confuse some servers.
I think this was initially done because I didn't fully understand how
sockets work and figured the information was necessary.
Per [1], it has moved to listening only on HTTPS. No other change to the
code was necessary, since we already knew how to deal with HTTPS
servers.
[1] https://github.com/PurritoBin/PurritoBin/pull/7
So we look for them using strcasestr instead fo strstr.
If this ever becomes a bottleneck, it can probably be optimized by only
trying to match the words right after "\r\n".
It still opens certs in ~/.config/gemi, but instead of doing a big fd
dance, simply uses an openat(dirfd(), readdir()->d_name) equivalent.
This way we even save on the extra fd and fcntl() call.
Use fnmatch() to filter for file names that end with ".pem". This can be
done with string manipulation, but fnmatch is easy to extend.
It's pretty small and won't be used outside this function, so it's ok to
allocate it on the stack. This also has the advantage of simplifying the
error checking, since it's one less allocation that can fail.
There was a misconception about how the ALPN API worked. It was actually
necessary to force a handshake so ALPN could be negotiated and
br_ssl_engine_get_selected_protocol() could possibly return any
information.
send_and_receive() now has a small diagnostics output for ALPN
and purr itself now forces the handshake before assembling the HTTP
requests, so it can use the ALPN results for that. The requests were
also reworked a bit.
Move base64 decoding to BearSSL's PEM decoder/encoder, using some simple
hacks for inserting and removing the PEM headers as well as the added
newlines.
Also added some fixes around the usage of mmap_file objects in purr.c,
and checked that the object size passed to cbcdec is actually the right
size.
This allows the client to connect to and get content from servers whose
certificates aren't accepted by the client's trust anchors. It isn't
exactly TOFU, since the cert isn't stored locally, but it's a start.
Also update README.
This change lead to completely overhauling the bearssl_read_certs()
function, which now deals directly with FILES, instead of depending on
mmap_file. There is some slight added complexity for dealing with the
file reads.
The idea for this came from the idea of implementing path resolution
using openat() instead of path concatenation, so there was a need to
pass either fds or file streams to functions instead of specific paths.
Allow it to read files in ~/.config/gemi/ to pick up certs, instead of
being limited to the ones in CA_CERT_SSL_FILE.
Also uses the new bearssl_read_certs() "API", and was in fact the
motivation for the changes there.
The previous impl clobbered most of the ta array if it was reutilized.
Add proper bookkeeping to solve this and enable reading from multiple
files.
The necessary changes in gemi.c are in the next commit, due to being
more involved and adding unrelated features.
It should be duplicated by who's going to use it, otherwise the
duplicated string will simply leak. Add function to free it, because why
not.
This also fixes a compiler warning about losing the const qualifier.
connect() can fail due to server side issues, so printing error messages
when the next attempt (in the same loop) might work leads to weird user
experience.
- Add close-on-exec flags where applicable, either with arguments when
opening the file or with fcntl calls. The possibility of applying the
flags atomically, when opening the file, is tested by the configure
script.
- Close the duplicated socket_write fd if fdopen in comm.c fails.