In case of root, res->path returns '.' which does not mix well with
concatenating the entry name. For example this may result in `.bin` for a folder
`bin` in root.
Not stat'ing the full path (just entry->d_name) strangely works on glibc/fedora
but fails on musl/alpine. Stat'ing the full path is the right thing to do,
anyways.
There was a heap corruption in `dirl_find_templ_dir` due not allocating enough
space for the terminating NULL in `path_buf`. This again only showed up in
musl/alpine.
Also use compound literals for immediate pointers we don't use later
(same as with setsockopt() in 32223c96bd).
Signed-off-by: Laslo Hunhold <dev@frign.de>
This turns the data-functions into the only functions "allowed"
to send body-data (called with http_send_body()). The previous (hacky)
approach of doing this in http_send_header() is not only out of place,
it's an easy source of bugs given, for instance, the sending of body
data is not expected with HEAD-requests.
Given html_escape() is now only used in data.c, we move it there from
util.c and make it a static method again.
Signed-off-by: Laslo Hunhold <dev@frign.de>
The methods in data.h only deal with the actual response data, not
the request handling itself, which has been formalized a bit more
in http.h. To avoid confusion, we rename it to data.h.
Signed-off-by: Laslo Hunhold <dev@frign.de>
Explicitly show that we set the status of the response struct to the
returned error status. This makes it clear that we are beyond the point
where the "form" of the response struct matters and it's now only about
the log-output.
Signed-off-by: Laslo Hunhold <dev@frign.de>
I don't like the juggling with status-values in serve. It makes
sense for http_recv_header() and http_parse_header(), because we
don't have a response-struct yet that we can "fill". We could pass
it to them, but that would make the usage a bit messy.
However, in http_prepare_response(), we are already entrusted with
a pointer to a response-struct, and just failing here (by returning
an error value) leaves the response-struct in an invalid state. Instead,
we make it a void function and reflect the status using the status field
in the passed response struct.
This way, there is no case where the response struct is in an
invalid state after calling a http_prepare_*()-method.
Signed-off-by: Laslo Hunhold <dev@frign.de>
This approach fits better in line of first initializing the response
struct and then sending the header with http_send_header() later.
Signed-off-by: Laslo Hunhold <dev@frign.de>
This improves readability a bit and helps iron out confusions with
status-variables called s in other methods.
Signed-off-by: Laslo Hunhold <dev@frign.de>
Of course URIs point at "targets", but the URIs themselves should
be called what they are, not only in the interest of clarity in terms
of nomenclature.
Signed-off-by: Laslo Hunhold <dev@frign.de>
The function http_send_response() did too much. It not only took
the request fields and built them together into a response, it
delegated too little and many functions were "hacked" into it, for
instance shady directory-changes for vhosts and hand-construction
of response structs.
The preparations for a rework were already made in previous commits,
including a tighter focus on the response-struct itself. Instead of
doing everything locally in the http_send_response() function, the
new http_prepare_response() only really takes the request-struct and
builds a response-struct. The response-struct is expanded such that
it's possible to do the data-sending simply with the response-struct
itself and not any other magic parameters that just drop out of the
function.
Another matter are the http_send_status()-calls. Because the
aforementioned function is so central, this refactoring has included
many areas. Instead of calling http_send_status() in every error-case,
which makes little sense now given we first delegate everything through
a response struct, errors are just sent as a return value and caught
centrally (in serve() in main.c), which centralizes the error handling
a bit.
It might look a bit strange now and it might not be clear in which
direction this is going, but subsequent commits will hopefully give
clarity in this regard.
Signed-off-by: Laslo Hunhold <dev@frign.de>
The function has become too long and basically did two things: Receiving
the header and parsing it. To better reflect this, we split it up into
the two functions http_recv_header() and http_parse_header(). This way,
we also obtain a better separation of concerns and can further reduce
the scope of each parameter-list.
http_recv_header() has been written in such a way that it can be
reentered and fill up the header-buffer bit by bit using a pointer to
an offset value.
The error handling was improved by only returning the immediate error
status codes and letting the caller do the error-handling with
http_send_status().
Signed-off-by: Laslo Hunhold <dev@frign.de>
The server-struct variable s was global, which made it readable and
modifiable from any point in the code. Making it a local variable in
main() instead and passing it as a pointer to constant memory to each
function needing it makes much more sense and allows the compiler to
warn us if we do try to modify it, which it wouldn't have before.
Signed-off-by: Laslo Hunhold <dev@frign.de>
We generally rejected any URI that had a path component beginning
with a '.', i.e. a hidden file. RFC 8615 specifies the well-known URI,
which is used, for instance, with the "http-01" challenge type in
acme-client(1) and will probably see more usage in the future.
To support it, we move the hidden target check after the stat(), so we
don't have to worry about canonicalization of dir-URIs (i.e. missing
trailing '/'). This changes the behaviour a bit, as now quark won't
only send out a 403 whenever a hidden target is requested, but only
if it actually exists, and a 404 otherwise.
Given the earlier call to normabspath() ensures that our path begins
with a '/', we don't need the first check "realtarget[0] == '.'"
anymore, so it can be removed.
Thanks to Robert Russell <robertrussell.72001@gmail.com> for reporting
the lack of support of the RFC 8615 in quark.
Signed-off-by: Laslo Hunhold <dev@frign.de>
As is there is no security issue, but _if_ we end up with a user
or group set to NULL after e.g. ARGEND, we would've hit a null-pointer-
dereference of grp in which is now line 311.
What we want to check instead is if user or group are NULL respectively
and throw an error. Consequently, we can remove the later checks in the
drop root section, as we now guarantee that grp and pwd are not NULL.
Signed-off-by: Laslo Hunhold <dev@frign.de>