diff options
Diffstat (limited to 'web/api/web_api.c')
-rw-r--r-- | web/api/web_api.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/web/api/web_api.c b/web/api/web_api.c index 4372bb8cb..7a4704bd5 100644 --- a/web/api/web_api.c +++ b/web/api/web_api.c @@ -6,7 +6,7 @@ bool netdata_is_protected_by_bearer = false; // this is controlled by cloud, at DICTIONARY *netdata_authorized_bearers = NULL; static bool web_client_check_acl_and_bearer(struct web_client *w, WEB_CLIENT_ACL endpoint_acl) { - if(endpoint_acl == WEB_CLIENT_ACL_NOCHECK) + if(endpoint_acl == WEB_CLIENT_ACL_NONE || (endpoint_acl & WEB_CLIENT_ACL_NOCHECK)) // the endpoint is totally public return true; @@ -23,27 +23,58 @@ static bool web_client_check_acl_and_bearer(struct web_client *w, WEB_CLIENT_ACL // endpoint does not require a bearer return true; - if((w->acl & (WEB_CLIENT_ACL_ACLK|WEB_CLIENT_ACL_WEBRTC)) || api_check_bearer_token(w)) + if((w->acl & (WEB_CLIENT_ACL_ACLK|WEB_CLIENT_ACL_WEBRTC))) // the request is coming from ACLK or WEBRTC (authorized already), - // or we have a valid bearer on the request return true; + // at this point we need a bearer to serve the request + // either because: + // + // 1. WEB_CLIENT_ACL_BEARER_REQUIRED, or + // 2. netdata_is_protected_by_bearer == true + // + + BEARER_STATUS t = api_check_bearer_token(w); + if(t == BEARER_STATUS_AVAILABLE_AND_VALIDATED) + // we have a valid bearer on the request + return true; + + netdata_log_info("BEARER: bearer is required for request: code %d", t); + return false; } int web_client_api_request_vX(RRDHOST *host, struct web_client *w, char *url_path_endpoint, struct web_api_command *api_commands) { + buffer_no_cacheable(w->response.data); + if(unlikely(!url_path_endpoint || !*url_path_endpoint)) { buffer_flush(w->response.data); buffer_sprintf(w->response.data, "Which API command?"); return HTTP_RESP_BAD_REQUEST; } - uint32_t hash = simple_hash(url_path_endpoint); + char *api_command = strchr(url_path_endpoint, '/'); + if (likely(api_command == NULL)) // only config command supports subpaths for now + api_command = url_path_endpoint; + else { + size_t api_command_len = api_command - url_path_endpoint; + api_command = callocz(1, api_command_len + 1); + memcpy(api_command, url_path_endpoint, api_command_len); + } + + uint32_t hash = simple_hash(api_command); for(int i = 0; api_commands[i].command ; i++) { - if(unlikely(hash == api_commands[i].hash && !strcmp(url_path_endpoint, api_commands[i].command))) { + if(unlikely(hash == api_commands[i].hash && !strcmp(api_command, api_commands[i].command))) { + if(unlikely(!api_commands[i].allow_subpaths && api_command != url_path_endpoint)) { + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "API command '%s' does not support subpaths.", api_command); + freez(api_command); + return HTTP_RESP_BAD_REQUEST; + } + if(unlikely(!web_client_check_acl_and_bearer(w, api_commands[i].acl))) - return web_client_bearer_required(w); + return web_client_permission_denied(w); char *query_string = (char *)buffer_tostring(w->url_query_string_decoded); @@ -54,6 +85,9 @@ int web_client_api_request_vX(RRDHOST *host, struct web_client *w, char *url_pat } } + if (api_command != url_path_endpoint) + freez(api_command); + buffer_flush(w->response.data); buffer_strcat(w->response.data, "Unsupported API command: "); buffer_strcat_htmlescape(w->response.data, url_path_endpoint); |