Enable bounded browser account administration for Phase 8D.7
Allow other-account add/password and forced delete/role commands through shared dispatcher and handler policy. Keep self-target, generated-secret, key, bootstrap, and recovery workflows blocked. Revalidate currentness after password prompts and before database API admission. Document that admitted mutations may finish after disconnect, while subsequent stale operations must reject. Add policy, transaction-failure, cleanup, and targeted-revocation regressions. Record completed review, passing host tests and firmware build, with target validation and M2 acceptance still pending.
This commit is contained in:
+36
-4
@@ -183,6 +183,12 @@ static bool session_is_current(const admin_ssh_console_token_t *token,
|
||||
return matched && current;
|
||||
}
|
||||
|
||||
bool admin_ssh_console_dispatch_is_current(void)
|
||||
{
|
||||
return xTaskGetCurrentTaskHandle() == s_task &&
|
||||
(!s_dispatch_remote || session_is_current(&s_dispatch_token, &s_dispatch_principal));
|
||||
}
|
||||
|
||||
static bool append_output_locked(admin_session_t *session,
|
||||
const uint8_t *data, size_t length)
|
||||
{
|
||||
@@ -488,6 +494,34 @@ static int ssh_output_write(void *cookie, const char *buffer, int length)
|
||||
return length;
|
||||
}
|
||||
|
||||
bool admin_ssh_console_web_user_command_allowed(
|
||||
size_t argc, char **argv, const user_principal_t *principal)
|
||||
{
|
||||
if (argc == 0U || strcmp(argv[0], "user") != 0) return false;
|
||||
if (argc == 1U ||
|
||||
(argc == 2U && (strcmp(argv[1], "status") == 0 ||
|
||||
strcmp(argv[1], "list") == 0)) ||
|
||||
(argc == 3U && strcmp(argv[1], "show") == 0)) return true;
|
||||
|
||||
bool role_valid = argc >= 4U &&
|
||||
(strcmp(argv[3], "user") == 0 || strcmp(argv[3], "admin") == 0);
|
||||
bool mutation =
|
||||
(argc == 4U && strcmp(argv[1], "add") == 0 && role_valid) ||
|
||||
(argc == 3U && strcmp(argv[1], "password") == 0) ||
|
||||
(argc == 4U && strcmp(argv[1], "delete") == 0 &&
|
||||
strcmp(argv[3], "--force") == 0) ||
|
||||
(argc == 5U && strcmp(argv[1], "role") == 0 && role_valid &&
|
||||
strcmp(argv[4], "--force") == 0);
|
||||
/* Parsed names use the database's exact, case-sensitive identity. Reject
|
||||
* self even for no-op role changes; their handler still requests revocation.
|
||||
* Generation/output and key workflows remain outside this bounded slice. */
|
||||
return mutation && principal != NULL && principal->role == USER_ROLE_ADMIN &&
|
||||
principal->username_length > 0U &&
|
||||
principal->username_length <= USER_DATABASE_USERNAME_CAPACITY &&
|
||||
!(strlen(argv[2]) == principal->username_length &&
|
||||
memcmp(argv[2], principal->username, principal->username_length) == 0);
|
||||
}
|
||||
|
||||
static bool remote_command_allowed(const admin_request_t *request)
|
||||
{
|
||||
char copy[ADMIN_SSH_CONSOLE_COMMAND_LINE_CAPACITY + 1U];
|
||||
@@ -514,10 +548,8 @@ static bool remote_command_allowed(const admin_request_t *request)
|
||||
} else if (strcmp(argv[0], "wifi") == 0 || strcmp(argv[0], "mdns") == 0) {
|
||||
allowed = argc == 2U && strcmp(argv[1], "status") == 0;
|
||||
} else if (strcmp(argv[0], "user") == 0) {
|
||||
allowed = argc == 1U ||
|
||||
(argc == 2U && (strcmp(argv[1], "status") == 0 ||
|
||||
strcmp(argv[1], "list") == 0)) ||
|
||||
(argc == 3U && strcmp(argv[1], "show") == 0);
|
||||
allowed = admin_ssh_console_web_user_command_allowed(
|
||||
argc, argv, &request->principal);
|
||||
} else if (strcmp(argv[0], "reboot") == 0) {
|
||||
allowed = argc == 1U;
|
||||
} else if (strcmp(argv[0], "ssh") == 0 && argc >= 2U) {
|
||||
|
||||
Reference in New Issue
Block a user