Age | Commit message (Collapse) | Author |
|
|
|
Since the VM initialization copies the search path into a runtime array,
we must prepare the path beforehand.
Fixes: 8cb3f85 ("ucode: initialize default library search path")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Recent ucode versions require us to explicitly initialize the search path
structure in the parser config.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When matching prefixes against the request URL, we should accept '?' as
valid terminator, similar to '/' and '\0' since logically the query string
is not part of the requested path.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Rework the current request handler code to not require an error page path
to be an actual file system entity.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
In case a relay process exits without printing at least one newline,
relay_close_if_done() will not close the relay context because there's
still pending data in the ustream.
Extend the relevant condition to only consider pending data if the relay
context is not in the header parsing state anymore.
Without this fix, requests triggering such a behaviour will never conclude.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
A request handler might legitimately call `exit()`, don't raise a server
error in this case.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
A request handler might legitimately call `exit()`, don't raise a server
error in this case.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Tested-by: Stijn Tintel <stijn@linux-ipv6.be>
|
|
Use FIND_LIBRARY to search the dependency and use variables to reference
them in the CMakeLists file.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
[ improve commit description ]
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
|
Using GCC 12 on an aarch64 target the following compilation error is
printed.
ninja: Entering directory `/home/ansuel/openwrt/build_dir/target-aarch64_cortex-a53_musl/uhttpd-2022-02-07-2f8b1360'
[1/2] Building C object CMakeFiles/uhttpd.dir/client.c.o
FAILED: CMakeFiles/uhttpd.dir/client.c.o
/home/ansuel/openwrt/staging_dir/host/bin/ccache /home/ansuel/openwrt/staging_dir/toolchain-aarch64_cortex-a53_gcc-12.1.0_musl/bin/aarch64-openwrt-linux-musl-gcc -DHAVE_LUA -DHAVE_SHADOW -DHAVE_TLS -DHAVE_UBUS -DHAVE_UCODE -D_FILE_OFFSET_BITS=64 -Os -pipe -mcpu=cortex-a53 -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -fmacro-prefix-map=/home/ansuel/openwrt/build_dir/target-aarch64_cortex-a53_musl/uhttpd-2022-02-07-2f8b1360=uhttpd-2022-02-07-2f8b1360 -Wformat -Werror=format-security -DPIC -fPIC -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -DNDEBUG -Os -Wall -Werror -Wmissing-declarations --std=gnu99 -g3 -MD -MT CMakeFiles/uhttpd.dir/client.c.o -MF CMakeFiles/uhttpd.dir/client.c.o.d -o CMakeFiles/uhttpd.dir/client.c.o -c /home/ansuel/openwrt/build_dir/target-aarch64_cortex-a53_musl/uhttpd-2022-02-07-2f8b1360/client.c
In function 'tls_redirect_check',
inlined from 'client_header_complete' at client.c:306:7,
inlined from 'client_parse_header' at client.c:338:3,
inlined from 'client_header_cb' at client.c:502:2:
client.c:269:22: error: 'strcmp' reading 1 or more bytes from a region of size 0 [-Werror=stringop-overread]
269 | if (!strcmp(blobmsg_name(cur), "URL"))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
ninja: build stopped: subcommand failed.
Fix this by using the strncmp variant.
Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
|
|
|
|
|
|
Add command line option "-b <interface>" which binds the ports
(and addresses) in the following "-p" and "-s" options to the specified
network interface with SO_BINDTODEVICE.
Using SO_BINDTODEVICE means uhttpd will only accept incoming traffic from
the specified network interface. Or in case a VRF interface is used,
from the interfaces associated with the VRF.
Signed-off-by: Mikael Magnusson <mikma@users.sourceforge.net>
|
|
In file included from ubus.c:20:
ubus.c: In function 'uh_ubus_list_cb':
libubox/blobmsg.h:256:9: error: 'o' may be used uninitialized in this function [-Werror=maybe-uninitialized]
256 | blob_nest_end(buf, cookie);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
ubus.c:591:19: note: 'o' was declared here
591 | void *t, *o;
| ^
cc1: all warnings being treated as errors
Signed-off-by: Thomas Huehn <thomas.huehn@hs-nordhausen.de>
Acked-by: Alexander Couzens <lynxis@fe80.eu>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The public libucode api has been revised to return and expect an
uc_program_t pointer instead of a main function reference.
The program (former main function) is also not implicitly released
by uc_vm_execute() anymore.
Adjust the ucode plugin accordingly to match the new requirements.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Also clarify existing Lua option descriptions while we're at it.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The ucode plugin mirrors the functionality of the Lua module, but using
the ucode script interpreter instead.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Fixes the following memory access error spotted by valgrind:
Invalid read of size 4
at 0x10D6D3: uh_socket_bind (listen.c:192)
by 0x10C830: add_listener_arg (main.c:128)
by 0x10C830: main (main.c:325)
Address 0x4aa1160 is 0 bytes after a block of size 64 alloc'd
at 0x483877F: malloc (vg_replace_malloc.c:307)
by 0x49ACAC5: gaih_inet.constprop.0 (getaddrinfo.c:1058)
by 0x49AE224: getaddrinfo (getaddrinfo.c:2256)
by 0x10D590: uh_socket_bind (listen.c:145)
by 0x10C830: add_listener_arg (main.c:128)
by 0x10C830: main (main.c:325)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When we run into an error like a 404 Not Found the request body is not
read and will be parsed as part of the next request. The next Request
will then fail because there is unexpected data in it.
When we run into such a problem with a request body close return an
error and close the connection. This should be easier than trying to
recover the state.
We saw this problem when /ubus/ was not installed, but the browser tried
to access it. Then uhttpd returned a 404, but the next request done in
this connection also failed with a HTTP 400, bad request.
Fixes: FS#3378
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|
Unregister ubus subscriber in notification remove callback.
Without this call, uhttpd crashes when client tries to subscribe to
the ubus object after the object was unregistred and registered again.
It is bacuse the reference to ubus subscriber is not freed but
the memory is cleared in the uh_request_done function.
Signed-off-by: Wojciech Jowsa <wojciech.jowsa@gmail.com>
|
|
The legacy ubus protocol must not include an empty object in the result
array if the invoked ubus procedure yielded no response.
This fixes compatibility with existing legacy ubus api clients that expect
this behaviour, LuCI's fs.js in particular.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When an uhttpd dispatch_handler provides a data_done callback which is
synchroneously finishing the request through ops->request_done(), the
calling client_poll_post_data() procedure incorrectly resets the resulting
client state from CLIENT_STATE_INIT to CLIENT_STATE_DONE which causes the
next uh_client_read_cb() invocation to bail out since no callback is
available for the CLIENT_STATE_DONE state, effectively discarding the
just received inbound request and sending the persistent connection state
into a deadlock sitation where the http client waits for a response to
its just sent request and uhttpd for further data to read.
Fix this issue by only setting CLIENT_STATE_DONE if the data_done callback
has not modified the state in the meanwhile.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
After specified time of network inactivity uhttpd is meant to close
connection. It doesn't seem to work thought. After timeout client
doesn't receive any more data but connection it still opened.
This change fixes that.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
Complex GET requests (e.g. those with custom headers) require browsers
to send preflight OPTIONS request with:
Access-Control-Request-Method: GET
It's important to reply to such requests with the header
Access-Control-Allow-Origin (and optionally others) to allow CORS
requests.
Adding GET to the Access-Control-Allow-Methods is cosmetical as
according to the Fetch standard:
> If request’s method is not in methods, request’s method is not a
> CORS-safelisted method, and request’s credentials mode is "include" or
> methods does not contain `*`, then return a network error.
It basically means that Access-Control-Allow-Methods value is ignored
for GET, HEAD and POST methods.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
With this change ubus will allow users with access to the object pseudo
method ":subscribe" to subscribe for notifications.
1. Move uh_ubus_allowed() up in the code
2. Export "Authorization" parsing code to the uh_ubus_get_auth()
3. Check for ":subscribe" method access
Right now this depends on "Authorization" HTTP header which browsers
don't allow setting for the EventSource. An alternative method of
submitting session token remains to be implemented.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
Initial uhttpd ubus API was fully based on JSON-RPC. That restricted it
from supporting ubus notifications that don't fit its model.
Notifications require protocol that allows server to send data without
being polled. There are two candidates for that:
1. Server-sent events
2. WebSocket
The later one is overcomplex for this simple task so ideally uhttps ubus
should support text-based server-sent events. It's not possible with
JSON-RPC without violating it. Specification requires server to reply
with Response object. Replying with text/event-stream is not allowed.
All above led to designing new API that:
1. Uses GET and POST requests
2. Makes use of RESTful URLs
3. Uses JSON-RPC in cleaner form and only for calling ubus methods
This new API allows:
1. Listing all ubus objects and their methods using GET <prefix>/list
2. Listing object methods using GET <prefix>/list/<path>
3. Listening to object notifications with GET <prefix>/subscribe/<path>
4. Calling ubus methods using POST <prefix>/call/<path>
JSON-RPC custom protocol was also simplified to:
1. Use "method" member for ubus object method name
It was possible thanks to using RESTful URLs. Previously "method"
had to be "list" or "call".
2. Reply with Error object on ubus method call error
This simplified "result" member format as it doesn't need to contain
ubus result code anymore.
This patch doesn't break or change the old API. The biggest downside of
the new API is no support for batch requests. It's cost of using RESTful
URLs. It should not matter much as uhttpd supports keep alive.
Example usages:
1. Getting all objects and their methods:
$ curl http://192.168.1.1/ubus/list
{
"dhcp": {
"ipv4leases": {
},
"ipv6leases": {
}
},
"log": {
"read": {
"lines": "number",
"stream": "boolean",
"oneshot": "boolean"
},
"write": {
"event": "string"
}
}
}
2. Getting object methods:
$ curl http://192.168.1.1/ubus/list/log
{
"read": {
"lines": "number",
"stream": "boolean",
"oneshot": "boolean"
},
"write": {
"event": "string"
}
}
3. Subscribing to notifications:
$ curl http://192.168.1.1/ubus/subscribe/foo
event: status
data: {"count":5}
4. Calling ubus object method:
$ curl -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "login",
"params": {"username": "root", "password": "password" }
}' http://192.168.1.1/ubus/call/session
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"ubus_rpc_session": "01234567890123456789012345678901",
(...)
}
}
$ curl -H 'Authorization: Bearer 01234567890123456789012345678901' -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "write",
"params": {"event": "Hello world" }
}' http://192.168.1.1/ubus/call/log
{
"jsonrpc": "2.0",
"id": 1,
"result": null
}
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
Initializing buffer in the uh_ubus_handle_request() didn't handle
batched requests correctly. It resulted in reusing buffer and generating
malformed replies.
Call blob_buf_init() before every usage of the global buf variable.
While at it make two functions take blob_buf pointer as argument:
1. uh_ubus_send_response()
2. uh_ubus_init_json_rpc_response()
This helps following global "buf" variable usage and will help avoiding
similar bugs in the future.
Fixes: 628341fae412 ("ubus: use local "blob_buf" in uh_ubus_handle_request_object()")
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
Use "_json_rpc_" in their names so it's clear they are related to the
JSON-RPC format. This cleans up code a bit and will allow adding more
formats in the future.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
This follows two other functions logic: uh_ubus_send_request() and
uh_ubus_allowed(). Thanks to this change global "buf" variable is used
only for replies and doesn't require state tracking & reinitialization.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
According to the JSON-RPC 2.0 specification "params" value can be either
an Array or Object. This change makes parse_json_rpc() accept both.
Type validation should be handled by a function that actually reads
"params" depending on expected format. This doesn't change existing
behaviour but allows adding more methods (that expect Object) in the
future.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
Both: uh_ubus_send_request() and uh_ubus_send_list() don't use it.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
There is no point in parsing "call" specific params for other ("list")
method calls. This is a minor cleanup that doesn't change uhttpd ubus
behaviour.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Acked-by: Jo-Philipp Wich <jo@mein.io>
|
|
Before this change if the cgi script hangs after writing headers
then the process will never be killed. Let's only cancel the timeout
if the process ends.
Signed-off-by: Santiago Piccinini <spiccinini@altermundi.net>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|
Allow POST requests via persistent connections to improve performance
especially when using HTTPS on older devices.
After this change, average page load times in LuCI improve significantly
once the TLS connections are initiated.
When testing an ar71xx 19.07.2 build on an ethernet connected TL-WR1043nd
using luci-ssl-openssl and the ustream-openssl backend, the average page
load time for the main status page decreased to 1.3s compared to 4.7s
before, the interface and wireless configuration pages loaded in 1.2s
seconds each compared to the 4.2s and 4.9s respectively before.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Introduce a new `-P` option which allows specifying a colon separated list
of accepted TLS ciphers.
Depending on the underlying ustream-ssl provider, the list either follows
OpenSSL's cipher string format or, in case of mbedTLS, is a simple colon
separated cipher whitelist.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When we're starting a deferred request, the related input ustream might
have gone into read_blocked mode because incoming client request data
exhausted the ustreams internal buffer space. When this happens, edge
triggered uloop read events are "lost" and never re-triggered causing
the script input to never complete.
In order to avoid that deadlock situation, manually poke the input
ustream using ustream_poll() after invoking client_poll_post_data()
which should have drained (some) of the buffered input ustream contents.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
An invalid data access can be triggered with an HTTP POST request to a CGI
script specifying both `Transfer-Encoding: chunked` and a large negative
`Content-Length`.
The negative content length is assigned to `r->content_length` in
`client_parse_header` and passed as a negative read length to
`ustream_consume` in `client_poll_post_data` which will set the internal
ustream buffer pointer to an invalid address, causing out of bounds memory
reads later on in the code flow.
A similar implicit unsigned to signed conversion happens when parsing
chunk sizes emitted by a CGI program.
Address these issues by rejecting negative values in `r->content_length`
after assigning the `strtoul()` result.
Reported-by: Jan-Niklas Sohn <jan-niklas.sohn@gmx.de>
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
After format string checks were activated in libubox the compiler
started to complain about multiple missuses in uhttpd. This fixes the
format strings without changing the behavior.
blobmsg_get_string() just checks if the parameter is not NULL and then
calls blobmsg_data() and casts the result.
I think non of these problem is security relevant.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|
Escape the untrusted request URL input in the permission denied HTML output.
This fixes certain XSS vulnerabilities which can be leveraged to further
exploit the system.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Adds ifdefs to fix building without TLS and Lua support
Signed-off-by: Paul Willoughby <paulw@spacemonkey.com>
|
|
It's one of the parameters used by default in LuCI, so it should be
included in the help output.
Signed-off-by: Karl Palsson <karlp@etactica.com>
|
|
Fixes: 77b774b ("build: avoid redefining _DEFAULT_SOURCE")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Work around further glibc toolchain annoyances.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Allow -l / -L arguments to be repeated to register multiple Lua prefix
handlers in the same process.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Add _DEFAULT_SOURCE FTM in order to avoid warnings with recent glibc.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|