v0.0.57 - Migrated to unified nostr_ prefixed verb names; removed legacy verb aliases (sign_data, ssh_sign, verify_signature, kem_encapsulate, kem_decapsulate, otp_encrypt, otp_decrypt); split get_public_key into algorithm-based get_public_key and role-based nostr_get_public_key; OTP now selected via algorithm:otp instead of curve:otp; consolidated API docs from api.md into README.md
This commit is contained in:
@@ -220,19 +220,20 @@ const char *selector_strerror(int err);
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
#define VERB_SIGN_EVENT "sign_event"
|
||||
#define VERB_GET_PUBLIC_KEY "get_public_key"
|
||||
#define VERB_NIP44_ENCRYPT "nip44_encrypt"
|
||||
#define VERB_NIP44_DECRYPT "nip44_decrypt"
|
||||
#define VERB_NIP04_ENCRYPT "nip04_encrypt"
|
||||
#define VERB_NIP04_DECRYPT "nip04_decrypt"
|
||||
#define VERB_GET_PUBLIC_KEY "get_public_key"
|
||||
#define VERB_NOSTR_GET_PUBLIC_KEY "nostr_get_public_key"
|
||||
#define VERB_NOSTR_SIGN_EVENT "nostr_sign_event"
|
||||
#define VERB_NOSTR_NIP44_ENCRYPT "nostr_nip44_encrypt"
|
||||
#define VERB_NOSTR_NIP44_DECRYPT "nostr_nip44_decrypt"
|
||||
#define VERB_NOSTR_NIP04_ENCRYPT "nostr_nip04_encrypt"
|
||||
#define VERB_NOSTR_NIP04_DECRYPT "nostr_nip04_decrypt"
|
||||
|
||||
/*
|
||||
* Check whether `verb` is allowed to execute against `role`.
|
||||
* Returns ENFORCE_OK if allowed, or an ENFORCE_ERR_* code.
|
||||
*
|
||||
* The enforcement rules are:
|
||||
* - All nostr verbs (sign_event, get_public_key, nip44_*, nip04_*) require:
|
||||
* - All nostr verbs (nostr_sign_event, nostr_get_public_key, nostr_nip44_*, nostr_nip04_*) require:
|
||||
* purpose == PURPOSE_NOSTR and curve == CURVE_SECP256K1
|
||||
* - Unknown verbs return ENFORCE_ERR_UNKNOWN_VERB (fail-closed).
|
||||
*/
|
||||
@@ -801,10 +802,10 @@ int main(void) {
|
||||
check_condition("parse_preapprove_spec rejects non-numeric nostr_index", rc == -1);
|
||||
|
||||
policy_init_default(&table, uid);
|
||||
rc = policy_check(&table, same_uid, "sign_event", "main", "nostr", NULL);
|
||||
rc = policy_check(&table, same_uid, "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("policy_init_default prompts same uid", rc == POLICY_PROMPT);
|
||||
|
||||
rc = policy_check(&table, other_uid, "sign_event", "main", "nostr", NULL);
|
||||
rc = policy_check(&table, other_uid, "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("policy_init_default prompts different uid", rc == POLICY_PROMPT);
|
||||
|
||||
/* Insert before catch-all: matching caller allowed, non-matching still prompted */
|
||||
@@ -820,9 +821,9 @@ int main(void) {
|
||||
rc = policy_table_insert_before_last(&table, &grant);
|
||||
check_condition("policy_table_insert_before_last succeeds", rc == 0);
|
||||
}
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("insert_before_last matching caller returns POLICY_ALLOW", rc == POLICY_ALLOW);
|
||||
rc = policy_check(&table, "uid:2000", "sign_event", "main", "nostr", NULL);
|
||||
rc = policy_check(&table, "uid:2000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("insert_before_last non-matching caller returns POLICY_PROMPT", rc == POLICY_PROMPT);
|
||||
|
||||
/* Preapprove parse + insert: matching caller allowed, non-matching prompted */
|
||||
@@ -831,70 +832,70 @@ int main(void) {
|
||||
check_condition("preapprove parse for policy insert succeeds", rc == 0);
|
||||
rc = policy_table_insert_before_last(&table, &parsed);
|
||||
check_condition("preapprove insert_before_last succeeds", rc == 0);
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("preapprove allows matching caller+role", rc == POLICY_ALLOW);
|
||||
rc = policy_check(&table, "uid:2000", "sign_event", "main", "nostr", NULL);
|
||||
rc = policy_check(&table, "uid:2000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("preapprove leaves non-matching caller at POLICY_PROMPT", rc == POLICY_PROMPT);
|
||||
|
||||
/* Exact caller, verb, role, purpose + never => allow */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", "sign_event", "main", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
add_single_entry(&table, "uid:1000", "nostr_sign_event", "main", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("exact match returns POLICY_ALLOW", rc == POLICY_ALLOW);
|
||||
|
||||
/* Wildcard caller + deny => deny */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "*", "sign_event", "main", "nostr", PROMPT_DENY);
|
||||
rc = policy_check(&table, "uid:2000", "sign_event", "main", "nostr", NULL);
|
||||
add_single_entry(&table, "*", "nostr_sign_event", "main", "nostr", PROMPT_DENY);
|
||||
rc = policy_check(&table, "uid:2000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("wildcard caller with deny returns POLICY_DENY", rc == POLICY_DENY);
|
||||
|
||||
/* Caller no match => POLICY_NO_MATCH */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", "sign_event", "main", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:9999", "sign_event", "main", "nostr", NULL);
|
||||
add_single_entry(&table, "uid:1000", "nostr_sign_event", "main", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:9999", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("caller mismatch returns POLICY_NO_MATCH", rc == POLICY_NO_MATCH);
|
||||
|
||||
/* Verb not in list => no match */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", "get_public_key", "main", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("verb mismatch returns POLICY_NO_MATCH", rc == POLICY_NO_MATCH);
|
||||
|
||||
/* Role not in list => no match */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", "sign_event", "throwaway", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
add_single_entry(&table, "uid:1000", "nostr_sign_event", "throwaway", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("role mismatch returns POLICY_NO_MATCH", rc == POLICY_NO_MATCH);
|
||||
|
||||
/* Purpose not in list => no match */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", "sign_event", "main", "bitcoin", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
add_single_entry(&table, "uid:1000", "nostr_sign_event", "main", "bitcoin", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("purpose mismatch returns POLICY_NO_MATCH", rc == POLICY_NO_MATCH);
|
||||
|
||||
/* Empty verbs list means all verbs */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", NULL, "main", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "nip44_encrypt", "main", "nostr", NULL);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_nip44_encrypt", "main", "nostr", NULL);
|
||||
check_condition("empty verbs list matches any verb", rc == POLICY_ALLOW);
|
||||
|
||||
/* prompt=first_per_boot => POLICY_PROMPT */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", "sign_event", "main", "nostr", PROMPT_FIRST_PER_BOOT);
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
add_single_entry(&table, "uid:1000", "nostr_sign_event", "main", "nostr", PROMPT_FIRST_PER_BOOT);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("first_per_boot returns POLICY_PROMPT", rc == POLICY_PROMPT);
|
||||
|
||||
/* prompt=every_request => POLICY_PROMPT */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", "sign_event", "main", "nostr", PROMPT_EVERY_REQUEST);
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
add_single_entry(&table, "uid:1000", "nostr_sign_event", "main", "nostr", PROMPT_EVERY_REQUEST);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("every_request returns POLICY_PROMPT", rc == POLICY_PROMPT);
|
||||
|
||||
/* First matching entry wins */
|
||||
policy_table_init(&table);
|
||||
add_single_entry(&table, "uid:1000", "sign_event", "main", "nostr", PROMPT_DENY);
|
||||
add_single_entry(&table, "uid:1000", "sign_event", "main", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", NULL);
|
||||
add_single_entry(&table, "uid:1000", "nostr_sign_event", "main", "nostr", PROMPT_DENY);
|
||||
add_single_entry(&table, "uid:1000", "nostr_sign_event", "main", "nostr", PROMPT_NEVER);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", NULL);
|
||||
check_condition("first matching entry wins", rc == POLICY_DENY);
|
||||
|
||||
/* Verify out_source for preapprove, session-grant, and default catch-all */
|
||||
@@ -931,15 +932,15 @@ int main(void) {
|
||||
check_condition("source test default catch-all add", rc == 0);
|
||||
|
||||
src = POLICY_SOURCE_DEFAULT;
|
||||
rc = policy_check(&table, "uid:1000", "sign_event", "main", "nostr", &src);
|
||||
rc = policy_check(&table, "uid:1000", "nostr_sign_event", "main", "nostr", &src);
|
||||
check_condition("policy_check reports preapprove source", rc == POLICY_ALLOW && src == POLICY_SOURCE_PREAPPROVE);
|
||||
|
||||
src = POLICY_SOURCE_DEFAULT;
|
||||
rc = policy_check(&table, "uid:1001", "sign_event", "main", "nostr", &src);
|
||||
rc = policy_check(&table, "uid:1001", "nostr_sign_event", "main", "nostr", &src);
|
||||
check_condition("policy_check reports session-grant source", rc == POLICY_ALLOW && src == POLICY_SOURCE_SESSION_GRANT);
|
||||
|
||||
src = POLICY_SOURCE_PREAPPROVE;
|
||||
rc = policy_check(&table, "uid:9999", "sign_event", "main", "nostr", &src);
|
||||
rc = policy_check(&table, "uid:9999", "nostr_sign_event", "main", "nostr", &src);
|
||||
check_condition("policy_check resets source for prompt/default", rc == POLICY_PROMPT && src == POLICY_SOURCE_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user