/* Included by accounts.py after extracted production functions. */ static void reset(void) { memset(&s_database, 0, sizeof(s_database)); memset(&candidate_storage, 0, sizeof(candidate_storage)); s_candidate=&candidate_storage; s_mutex=(void *)1; s_initialized=true; s_database.version=USER_DATABASE_SCHEMA_VERSION; s_database.size=sizeof(s_database); s_database.generation=1; s_database.admin_bootstrapped=1; fail_stage=0; invalidate_during_derivation=false; derivation_invalidations=0; assert(initialize_user(&s_database.users[0], (const uint8_t *)"admin", 5, USER_ROLE_ADMIN, (const uint8_t *)"test-password", 13)==ESP_OK); assert(initialize_user(&s_database.users[1], (const uint8_t *)"other", 5, USER_ROLE_USER, (const uint8_t *)"test-password", 13)==ESP_OK); assert(initialize_user(&s_database.users[2], (const uint8_t *)"observer", 8, USER_ROLE_USER, (const uint8_t *)"test-password", 13)==ESP_OK); recount(&s_database); assert(validate_database(&s_database)==ESP_OK); actor=(user_principal_t){.role=USER_ROLE_ADMIN, .username_length=5, .username="admin", .user_id=s_database.users[0].user_id, .auth_generation=s_database.users[0].auth_generation}; writes=commits=prompts=checks=web_revokes=ssh_revokes=0; revoke_prompt=revoke_check=0; owner_current=true; remote=web=true; mismatch=cancel_prompt=stale_prompt=false; notify_error=ESP_OK; memset(revoked_name,0,sizeof(revoked_name)); } static int run(const char *line) { char copy[257]; char *argv[10]={0}; assert(strlen(line)=0 && s_database.users[fresh].role==(i==0 ? USER_ROLE_USER : USER_ROLE_ADMIN)); } else if (i==3) { assert(find_user(&s_database,(const uint8_t *)"other",5)<0); } else if (i!=6) { assert(s_database.users[1].auth_generation==before.users[1].auth_generation+1); } else { assert(!writes && !commits); /* Existing no-op role still revokes target. */ } assert(all_zero(s_candidate,sizeof(*s_candidate))); assert(!locks); } const char *denied[]={ "user password admin", "\"user\" \"password\" \"admin\"", "user delete admin --force", "user role admin user --force", "user role admin admin --force", "user add admin admin", "user password admin --generate", "user password other --generate", "user add fresh user --generate", "user key add other", "user key add other ssh-ed25519 AAAA", "user key delete other 0 --force", "user key clear other --force", "user bootstrap", "user bootstrap --generate", "user recover --force", "user password other extra", "user role other admin --force extra", "user delete other --force extra", "user add fresh invalid", "user add fresh user extra", "user delete other", "user role other user", "user role \"admin\" user --force", "user add \"admin\" user", }; for (size_t i=0;i=0 && s_database.users[fresh].role==USER_ROLE_ADMIN); assert(s_database.user_count==before.user_count+1); assert(!memcmp(&before.users[1],&s_database.users[1],sizeof(stored_user_t))); } else { assert(s_database.users[1].auth_generation==before.users[1].auth_generation+1); assert(memcmp(before.users[1].password_salt,s_database.users[1].password_salt, sizeof(before.users[1].password_salt))!=0); } assert(web_revokes==1 && ssh_revokes==1); assert(!strcmp(revoked_name,i==0 ? "fresh" : "other")); assert(!memcmp(&before.users[0],&s_database.users[0],sizeof(stored_user_t))); assert(!memcmp(&before.users[2],&s_database.users[2],sizeof(stored_user_t))); assert(validate_database(&s_database)==ESP_OK); assert(all_zero(s_candidate,sizeof(*s_candidate))); } else { assert(result!=0); unchanged(&before); assert(commits==(stage==3 ? 1U : 0U)); } /* Loss of liveness cannot authorize a subsequent operation. */ stored_database_t after=s_database; unsigned prior_writes=writes, prior_commits=commits; unsigned prior_web=web_revokes, prior_ssh=ssh_revokes; assert(run("user password observer")!=0); assert(!memcmp(&after,&s_database,sizeof(after))); assert(prompts==2 && writes==prior_writes && commits==prior_commits); assert(web_revokes==prior_web && ssh_revokes==prior_ssh); } } /* Every enabled mutation fails closed when the originating session or copied * account is stale BEFORE operation admission, including forced mutations. */ for (size_t i=0;i