128 lines
5.1 KiB
C
128 lines
5.1 KiB
C
#include "../src/policy.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
static int g_passes = 0;
|
|
static int g_total = 0;
|
|
|
|
static void check_condition(const char *name, int condition) {
|
|
g_total++;
|
|
if (condition) {
|
|
printf("PASS: %s\n", name);
|
|
g_passes++;
|
|
} else {
|
|
printf("FAIL: %s\n", name);
|
|
}
|
|
}
|
|
|
|
static void add_single_entry(policy_table_t *table,
|
|
const char *caller,
|
|
const char *verb,
|
|
const char *role,
|
|
const char *purpose,
|
|
prompt_mode_t prompt) {
|
|
policy_entry_t e;
|
|
|
|
memset(&e, 0, sizeof(e));
|
|
strncpy(e.caller, caller, sizeof(e.caller) - 1);
|
|
if (verb != NULL) {
|
|
strncpy(e.verbs[0], verb, sizeof(e.verbs[0]) - 1);
|
|
e.verb_count = 1;
|
|
}
|
|
if (role != NULL) {
|
|
strncpy(e.roles[0], role, sizeof(e.roles[0]) - 1);
|
|
e.role_count = 1;
|
|
}
|
|
if (purpose != NULL) {
|
|
strncpy(e.purposes[0], purpose, sizeof(e.purposes[0]) - 1);
|
|
e.purpose_count = 1;
|
|
}
|
|
e.prompt = prompt;
|
|
|
|
policy_table_add(table, &e);
|
|
}
|
|
|
|
int main(void) {
|
|
policy_table_t table;
|
|
int rc;
|
|
uid_t uid = getuid();
|
|
char same_uid[64];
|
|
char other_uid[64];
|
|
|
|
(void)snprintf(same_uid, sizeof(same_uid), "uid:%u", (unsigned int)uid);
|
|
(void)snprintf(other_uid, sizeof(other_uid), "uid:%u", (unsigned int)(uid + 1U));
|
|
|
|
policy_init_default(&table, uid);
|
|
rc = policy_check(&table, same_uid, "sign_event", "main", "nostr");
|
|
check_condition("policy_init_default allows same uid", rc == POLICY_ALLOW);
|
|
|
|
rc = policy_check(&table, other_uid, "sign_event", "main", "nostr");
|
|
check_condition("policy_init_default denies different uid", rc == POLICY_DENY);
|
|
|
|
/* 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");
|
|
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");
|
|
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");
|
|
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");
|
|
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");
|
|
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");
|
|
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");
|
|
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");
|
|
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");
|
|
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");
|
|
check_condition("first matching entry wins", rc == POLICY_DENY);
|
|
|
|
printf("%d/%d tests passed\n", g_passes, g_total);
|
|
return (g_passes == g_total) ? 0 : 1;
|
|
}
|