| 2278 | } |
| 2279 | |
| 2280 | static cbm_daemon_runtime_application_status_t application_set_context( |
| 2281 | cbm_daemon_application_session_t *session, const uint8_t *request, uint32_t request_length) { |
| 2282 | if (session->context_set || request_length < APPLICATION_CONTEXT_HEADER_SIZE) { |
| 2283 | return CBM_DAEMON_RUNTIME_APPLICATION_REJECTED; |
| 2284 | } |
| 2285 | uint32_t root_length = application_get_u32(request + 1); |
| 2286 | bool allowed_present = request[5] == 1; |
| 2287 | uint32_t allowed_length = application_get_u32(request + 6); |
| 2288 | uint8_t profile_value = request[10]; |
| 2289 | uint32_t event_length = application_get_u32(request + 11); |
| 2290 | uint32_t dialect_length = application_get_u32(request + 15); |
| 2291 | uint64_t expected = (uint64_t)APPLICATION_CONTEXT_HEADER_SIZE + root_length + allowed_length + |
| 2292 | event_length + dialect_length; |
| 2293 | if (request[5] > 1 || root_length == 0 || expected != request_length || |
| 2294 | (!allowed_present && allowed_length != 0) || |
| 2295 | profile_value > (uint8_t)CBM_MCP_TOOL_PROFILE_SCOUT || |
| 2296 | (profile_value != (uint8_t)CBM_MCP_TOOL_PROFILE_ALL && |
| 2297 | (event_length != 0 || dialect_length != 0))) { |
| 2298 | return CBM_DAEMON_RUNTIME_APPLICATION_REJECTED; |
| 2299 | } |
| 2300 | cbm_mcp_tool_profile_t tool_profile = (cbm_mcp_tool_profile_t)profile_value; |
| 2301 | const uint8_t *payload = request + APPLICATION_CONTEXT_HEADER_SIZE; |
| 2302 | char *root = application_text_copy(request + APPLICATION_CONTEXT_HEADER_SIZE, root_length); |
| 2303 | char *allowed = |
| 2304 | allowed_present ? application_text_copy(payload + root_length, allowed_length) : NULL; |
| 2305 | char *hook_event = |
| 2306 | event_length ? application_text_copy(payload + root_length + allowed_length, event_length) |
| 2307 | : NULL; |
| 2308 | char *hook_dialect = |
| 2309 | dialect_length ? application_text_copy( |
| 2310 | payload + root_length + allowed_length + event_length, dialect_length) |
| 2311 | : NULL; |
| 2312 | if (!root || (allowed_present && !allowed) || (event_length && !hook_event) || |
| 2313 | (dialect_length && !hook_dialect) || |
| 2314 | !cbm_hook_augment_invocation_supported(hook_event, hook_dialect)) { |
| 2315 | free(root); |
| 2316 | free(allowed); |
| 2317 | free(hook_event); |
| 2318 | free(hook_dialect); |
| 2319 | return CBM_DAEMON_RUNTIME_APPLICATION_REJECTED; |
| 2320 | } |
| 2321 | char canonical_root[APPLICATION_PATH_CAP] = {0}; |
| 2322 | char canonical_allowed[APPLICATION_PATH_CAP] = {0}; |
| 2323 | bool canonical = cbm_canonical_path(root, canonical_root, sizeof(canonical_root)); |
| 2324 | if (canonical && allowed_present) { |
| 2325 | canonical = cbm_canonical_path(allowed, canonical_allowed, sizeof(canonical_allowed)); |
| 2326 | } |
| 2327 | struct stat root_status; |
| 2328 | canonical = |
| 2329 | canonical && stat(canonical_root, &root_status) == 0 && S_ISDIR(root_status.st_mode); |
| 2330 | bool set = |
| 2331 | canonical && cbm_mcp_server_set_session_context(session->mcp, canonical_root, |
| 2332 | allowed_present ? canonical_allowed : NULL); |
| 2333 | free(root); |
| 2334 | free(allowed); |
| 2335 | if (!set) { |
| 2336 | free(hook_event); |
| 2337 | free(hook_dialect); |
no test coverage detected