Add HTTPS identity rotation support
This commit is contained in:
@@ -19,6 +19,9 @@ void esp_restart(void) { assert(false); }
|
||||
esp_err_t web_server_stop(void) { assert(false); return ESP_FAIL; }
|
||||
esp_err_t web_server_start(void) { assert(false); return ESP_FAIL; }
|
||||
esp_err_t web_security_rotate_certificate(void) { assert(false); return ESP_FAIL; }
|
||||
esp_err_t web_server_replace_identity(uint32_t service, uint32_t identity, bool reset, bool *committed) {
|
||||
(void)service; (void)identity; (void)reset; (void)committed; assert(false); return ESP_FAIL;
|
||||
}
|
||||
void *heap_caps_calloc(size_t n, size_t size, unsigned caps) {
|
||||
assert(caps == (MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); return calloc(n, size);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,13 @@ static esp_err_t owner_action(unsigned action, uint32_t generation) {
|
||||
esp_err_t web_server_stop_current(uint32_t generation) { return owner_action(0, generation); }
|
||||
esp_err_t web_server_restart_current(uint32_t generation) { return owner_action(1, generation); }
|
||||
esp_err_t web_server_reboot_current(uint32_t generation) { return owner_action(2, generation); }
|
||||
esp_err_t web_server_replace_identity(uint32_t generation, uint32_t identity, bool reset, bool *committed) {
|
||||
assert(identity == 11 && !reset); *committed = owner_error == ESP_OK; return owner_action(3, generation);
|
||||
}
|
||||
esp_err_t web_security_get_identity_snapshot(web_security_identity_snapshot_t *out) {
|
||||
assert(on_handler && !host_lock_depth); *out = (web_security_identity_snapshot_t){.generation=11};
|
||||
memset(out->fingerprint, 0xab, 32); return ESP_OK;
|
||||
}
|
||||
esp_err_t httpd_queue_work(httpd_handle_t handle, void (*callback)(void *), void *argument) {
|
||||
assert(on_handler && !on_dispatcher && !on_callback && !host_lock_depth && handle == &server);
|
||||
assert(!strcmp(response_status, "202 Accepted") && !send_fail && !aux.remaining_len && sends);
|
||||
@@ -53,7 +60,7 @@ static void expect_lifecycle(const char *status, bool snapshot_read) {
|
||||
on_handler = false;
|
||||
assert(error == (send_fail || aux.remaining_len ? ESP_FAIL : ESP_OK));
|
||||
assert(!strcmp(response_status, status) && mutations == before && submit_calls == submitted);
|
||||
assert(strlen(output) < (snapshot_read ? 128 : 96)); zero(scratch, sizeof(scratch));
|
||||
assert(strlen(output) < (snapshot_read ? 320 : 96)); zero(scratch, sizeof(scratch));
|
||||
assert(!strstr(output, "principal") && !strstr(output, "csrf") && !strstr(output, "password"));
|
||||
}
|
||||
static const char *stop_body = "{\"action\":\"stop\",\"generation\":7}";
|
||||
@@ -109,7 +116,23 @@ static void lifecycle_tests(void) {
|
||||
for (unsigned i = 0; i < sizeof(invalid)/sizeof(*invalid); ++i) {
|
||||
lifecycle_begin(&admin, invalid[i], false); expect_lifecycle("400 Bad Request", false);
|
||||
}
|
||||
const char *invalid_rotation[] = {
|
||||
"{\"action\":\"rotate\",\"generation\":7}",
|
||||
"{\"action\":\"rotate\",\"identity_generation\":11}",
|
||||
"{\"action\":\"rotate\",\"generation\":7,\"identity_generation\":0}",
|
||||
"{\"action\":\"rotate\",\"generation\":7,\"identity_generation\":4294967295}",
|
||||
"{\"action\":\"rotate\",\"generation\":7,\"identity_generation\":4294967296}",
|
||||
"{\"action\":\"rotate\",\"generation\":7,\"identity_generation\":\"11\"}",
|
||||
"{\"action\":\"rotate\",\"generation\":7,\"identity_generation\":11,\"reset\":true}",
|
||||
"{\"action\":\"stop\",\"generation\":7,\"identity_generation\":11}"
|
||||
};
|
||||
for (unsigned i = 0; i < sizeof(invalid_rotation)/sizeof(*invalid_rotation); ++i) {
|
||||
lifecycle_begin(&admin, invalid_rotation[i], false); expect_lifecycle("400 Bad Request", false);
|
||||
}
|
||||
lifecycle_operation_t parsed = {0};
|
||||
const char *rotation = "{\"identity_generation\":11,\"generation\":7,\"action\":\"rotate\"}";
|
||||
assert(parse(rotation, strlen(rotation), &parsed) && parsed.identity_generation == 11 && parsed.action == 3);
|
||||
for (size_t n = 0; n < strlen(rotation); ++n) assert(!parse(rotation, n, &parsed));
|
||||
for (size_t n = 0; n < strlen(stop_body); ++n) assert(!parse(stop_body, n, &parsed));
|
||||
assert(parse(stop_body, strlen(stop_body), &parsed)); assert(!parse(stop_body, strlen(stop_body) + 1, &parsed));
|
||||
const char *reordered = " { \"generation\":4294967294, \"action\":\"restart\" } ";
|
||||
@@ -129,7 +152,11 @@ static void lifecycle_tests(void) {
|
||||
for (unsigned mode = 0; mode < 2; ++mode) {
|
||||
owner_error = mode ? ESP_FAIL : ESP_OK;
|
||||
lifecycle_begin(&admin, NULL, true); expect_lifecycle(mode ? "503 Service Unavailable" : "200 OK", true);
|
||||
if (!mode) assert(!strcmp(output, "{\"generation\":7,\"running\":true,\"transitioning\":false,\"controllable\":true}"));
|
||||
if (!mode) {
|
||||
assert(strstr(output, "\"identity_generation\":11") && strstr(output, "\"rotatable\":true"));
|
||||
assert(strstr(output, "abababababababababababababababababababababababababababababababab"));
|
||||
assert(!strstr(output, "private") && !strstr(output, "certificate_der"));
|
||||
}
|
||||
}
|
||||
owner_error = ESP_OK;
|
||||
puts("PASS lifecycle bounded scalar snapshot and optional owner failure isolation");
|
||||
@@ -165,9 +192,10 @@ static void lifecycle_tests(void) {
|
||||
lifecycle_submit(&admin, stop_body); on_callback = true; ack_handoff((void *)(uintptr_t)late); on_callback = false;
|
||||
assert(s_ack_id == s_operation.id); owner_callback(); dispatch(); assert(s_operation.state == OK);
|
||||
puts("PASS lifecycle original-login expiry/revocation/validation races and shutdown/restart same-owner ABA");
|
||||
for (unsigned action = 0; action < 3; ++action) {
|
||||
for (unsigned action = 0; action < 4; ++action) {
|
||||
auth_reset(); admin = mint(&alice); char body[80];
|
||||
snprintf(body, sizeof(body), "{\"action\":\"%s\",\"generation\":7}", s_actions[action]);
|
||||
snprintf(body, sizeof(body), "{\"action\":\"%s\",\"generation\":7%s}", s_actions[action],
|
||||
action == 3 ? ",\"identity_generation\":11" : "");
|
||||
invalidate_during_owner = true; lifecycle_submit(&admin, body); owner_callback(); before = mutations; dispatch();
|
||||
invalidate_during_owner = false;
|
||||
assert(s_operation.state == OK && mutations == before + 1);
|
||||
|
||||
Reference in New Issue
Block a user