summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2021-09-08WIP debugbind-to-device-21.02Mikael Magnusson
2021-09-08WIPMikael Magnusson
2021-09-08WIPMikael Magnusson
2021-09-08uhttpd: add SO_BINDTODEVICE supportMikael Magnusson
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. Signed-off-by: Mikael Magnusson <mikma@users.sourceforge.net>
2021-03-21client: Always close connection with request body in case of errorHEADmasterHauke Mehrtens
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>
2020-11-23ubus: fix uhttpd crashWojciech Jowsa
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>
2020-10-04ubus: fix legacy empty reply formatJo-Philipp Wich
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>
2020-10-04client: fix spurious keepalive connection timeoutsJo-Philipp Wich
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>
2020-10-01client: really close connection on timeoutRafał Miłecki
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>
2020-09-23ubus: support GET method with CORS requestsRafał Miłecki
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>
2020-09-18ubus: add ACL support for "subscribe" requestRafał Miłecki
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>
2020-09-15ubus: add new RESTful APIRafał Miłecki
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>
2020-09-15ubus: fix blob_buf initializationRafał Miłecki
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>
2020-08-05ubus: rename JSON-RPC format related functionsRafał Miłecki
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>
2020-08-05ubus: use local "blob_buf" in uh_ubus_handle_request_object()Rafał Miłecki
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>
2020-08-05ubus: use BLOBMSG_TYPE_UNSPEC for "params" JSON attributeRafał Miłecki
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>
2020-08-05ubus: drop unused "obj" argumentsRafał Miłecki
Both: uh_ubus_send_request() and uh_ubus_send_list() don't use it. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
2020-07-25ubus: parse "call" method params only for relevant callRafał Miłecki
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>
2020-06-03proc: do not cancel script killing after writing headersSantiago Piccinini
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>
2020-03-13client: allow keep-alive for POST requestsJo-Philipp Wich
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>
2020-02-15tls: support specifying accepted TLS ciphersJo-Philipp Wich
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>
2020-02-11file: poke ustream after starting deferred programJo-Philipp Wich
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>
2019-12-22client: fix invalid data access through invalid content-length valuesJo-Philipp Wich
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>
2019-08-17ubus: increase maximum ubus request size to 64KBJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2019-06-16uhttpd: Fix multiple format string problemsHauke Mehrtens
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>
2018-11-28cgi: escape url in 403 error outputJo-Philipp Wich
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>
2018-11-26uhttpd: fix building without TLS and Lua supportPaul Willoughby
Adds ifdefs to fix building without TLS and Lua support Signed-off-by: Paul Willoughby <paulw@spacemonkey.com>
2018-11-01help: document -A optionKarl Pálsson
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>
2018-09-24file: fix CPP syntax errorJo-Philipp Wich
Fixes: 77b774b ("build: avoid redefining _DEFAULT_SOURCE") Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-08-23build: avoid redefining _DEFAULT_SOURCEJo-Philipp Wich
Work around further glibc toolchain annoyances. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-08-23lua: support multiple Lua prefixesJo-Philipp Wich
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>
2018-08-21build: use _DEFAULT_SOURCEJo-Philipp Wich
Add _DEFAULT_SOURCE FTM in order to avoid warnings with recent glibc. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-08-21uhttpd: recognize PATCH, PUT and DELETE HTTP methodsJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-06-26client: flush buffered SSL output when tearing down client ustreamJo-Philipp Wich
When the outer SSL ustream triggers a change notification due to encountering EOF, the inner connection ustream might still have pending data buffered. Previously, such a condition led to truncated files delivered by uhttpd via HTTPS and could be triggered by requesting large resources via slow network links. Mitigate the problem by propagating the EOF status indicator from the outer ustream to the inner one and by deferring the client connection shutdown until the inner ustream output buffer has been completely drained. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-04-24proc: expose HTTP Origin header in process environmentJo-Philipp Wich
Map the "Origin:" header as $HTTP_ORIGIN environment variable for use by request handling processes. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-04-04file: escape strings in HTML outputJo-Philipp Wich
Escape untrusted input like the request URL or filesystem paths in HTML outputs such as the directory listing or 404 error messages. This fixes certain XSS vulnerabilities which can be leveraged to further exploit the system. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-04-04utils: add uh_htmlescape() helperJo-Philipp Wich
The uh_htmlescape() function returns a copy of the given string with the HTML special characters `<`, `>`, `"` and `'` replaced by HTML entities in hexadecimal notation. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-04-04Revert "proc: avoid stdio deadlocks"Jo-Philipp Wich
This reverts commit ccd9717ba5d501b45fda957f0ea41c4660ef414c.
2018-01-25proc: avoid stdio deadlocksJo-Philipp Wich
When a request handler accepting post data is too slow in consuming stdin, uhttpd might deadlock with the master process stuck in a blocking write() to the child and the child stuck with a blocking write() to the master. Avoid this issue by putting the master side write end of the child pipe into nonblocking mode right away and by raising the data_blocked flag when attempts to write to the child yield EAGAIN. Setting the flag ensures that client_poll_post_data() does not immediately trigger a write attempt again, which effectively yields the master write cycle so that the relay ustream has a chance to consume output of the client process, thus solving the deadlock. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2018-01-24lua: honour size argument in recv() functionJo-Philipp Wich
The existing implementation incorrectly attempted to read the entire stdin instead of fetching at most the given amount of bytes. While we're at it, also make the size argument optional and let it default to Luas internal buffer size. Suggested-by: Bryan Mayland <bmayland+lede@capnbry.net> Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2017-11-04file: fix query string handlingJo-Philipp Wich
Instead of storing a pointer to the beginning of the query string within the request url, store a copy in a static buffer instead. This aligns handling the query string portion of the url with other elements like physical path or path info information. Since the URL is usually kept in the per-client blob buffer which might change its memory location due to reallocations triggered by blobmsg_add_*, it is not safe to point to it early in the request life cycle. This fixes invalid memory access usually manifesting itself as corrupted query string data in CGI scripts. Reported-by: P. Wassi <p.wassi@gmx.at> Suggested-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2017-08-19uhttpd: add manifest supportAdrian Panella
Add "text/cache-manifest" mimetype support to enable the possibility of using Application Cache. Signed-off-by: Adrian Panella <ianchi74@outlook.com>
2017-07-09file: fix basic auth regressionJo-Philipp Wich
Previous refactoring of the basic auth handling code broke the logic in such a way that basic auth was only performed if a client sent an Authorization header in its request, but it was never prompted for by the server. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2017-07-02file: remove unused "auth" member from struct path_infoJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2017-07-02proc: expose HTTP_AUTH_USER and HTTP_AUTH_PASSJo-Philipp Wich
Mimic other web servers like Nginx or Apache and expose the parsed basic auth information as HTTP_AUTH_USER and HTTP_AUTH_PASS environment variables to CGI processes. This also restores login-from-basic-auth functionality in LuCI. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2017-07-02auth: store parsed username and passwordJo-Philipp Wich
Store the parsed username and password information as HTTP headers in the clients header blob buffer for later use by proc.c Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2017-07-02proc: do not declare empty process variablesJo-Philipp Wich
If a HTTP header variable has no corresponding value, then do not set it to the empty string but to NULL, so that cgi.c will later skip it when setting up the process environment. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2017-01-26uhttpd: Add TCP_FASTOPEN supportRosen Penev
Provides a small speedup when resuming the connection. Signed-off by: Rosen Penev <rosenp@gmail.com>
2016-10-25lua: ensure that PATH_INFO starts with a slashJo-Philipp Wich
When calculating the matching prefix length, make sure to not take the trailing slash into account in order to ensure that the resulting PATH_INFO string always starts with a slash. This ensures that an url like "/foo" against the matching prefix "/" or "/foo/bar" against "/foo/" result in "/foo" and "/bar" respectively. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2016-10-25utils: add proper handling of "/" special case in uh_path_match()Jo-Philipp Wich
The special prefix of "/" should match any url by definition but the final assertion which ensures that the matched prefix ends in '\0' or '/' is causing matches against the "/" prefix to fail. Add some extra code to handle this special case to implemented the expected behaviour. Signed-off-by: Jo-Philipp Wich <jo@mein.io>