v0.1.20 - Fixed auth white and black lists
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
#include <strings.h>
|
||||
#include <time.h>
|
||||
|
||||
#define MAX_MIME_TYPE_LEN 128 // Define here for direct use
|
||||
|
||||
// Additional error codes for ginxsom-specific functionality
|
||||
#define NOSTR_ERROR_CRYPTO_INIT -100
|
||||
#define NOSTR_ERROR_AUTH_REQUIRED -101
|
||||
@@ -671,8 +673,8 @@ int nostr_validate_unified_request(const nostr_unified_request_t *request,
|
||||
"VALIDATOR_DEBUG: STEP 10 PASSED - Blossom authentication succeeded\n");
|
||||
strcpy(result->reason, "Blossom authentication passed");
|
||||
|
||||
} else if (event_kind == 33335) {
|
||||
// 10. Admin/Configuration Event Validation (Kind 33335)
|
||||
} else if (event_kind == 33335 || event_kind == 23459 || event_kind == 23458) {
|
||||
// 10. Admin/Configuration Event Validation (Kind 33335, 23459, 23458)
|
||||
// Verify admin authorization, check required tags, validate expiration
|
||||
validator_debug_log("VALIDATOR_DEBUG: STEP 10 - Processing Admin/Configuration "
|
||||
"authentication (kind 33335)\n");
|
||||
@@ -775,6 +777,16 @@ int nostr_validate_unified_request(const nostr_unified_request_t *request,
|
||||
|
||||
cJSON_Delete(event);
|
||||
|
||||
// Skip rule evaluation for admin events
|
||||
if (event_kind == 33335 || event_kind == 23459 || event_kind == 23458) {
|
||||
char admin_skip_msg[256];
|
||||
snprintf(admin_skip_msg, sizeof(admin_skip_msg),
|
||||
"VALIDATOR_DEBUG: Admin event (kind %d) - skipping rule evaluation\n", event_kind);
|
||||
validator_debug_log(admin_skip_msg);
|
||||
strcpy(result->reason, "Admin event validated - rules bypassed");
|
||||
return NOSTR_SUCCESS;
|
||||
}
|
||||
|
||||
// STEP 12 PASSED: Protocol validation complete - continue to database rule
|
||||
// evaluation
|
||||
validator_debug_log("VALIDATOR_DEBUG: STEP 12 PASSED - Protocol validation "
|
||||
@@ -1321,6 +1333,13 @@ static int check_database_auth_rules(const char *pubkey, const char *operation,
|
||||
sqlite3 *db = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int rc;
|
||||
int pubkey_whitelisted = 0;
|
||||
int pubkey_whitelist_exists = 0;
|
||||
int mime_whitelisted = 0;
|
||||
int mime_whitelist_exists = 0;
|
||||
int mime_whitelist_count = 0;
|
||||
int pubkey_whitelist_count = 0;
|
||||
char rules_msg[256];
|
||||
|
||||
if (!pubkey) {
|
||||
validator_debug_log(
|
||||
@@ -1328,7 +1347,12 @@ static int check_database_auth_rules(const char *pubkey, const char *operation,
|
||||
return NOSTR_ERROR_INVALID_INPUT;
|
||||
}
|
||||
|
||||
char rules_msg[256];
|
||||
if (operation && (strcmp(operation, "admin_event") == 0 ||
|
||||
strcmp(operation, "admin") == 0)) {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - Admin management request, skipping auth rules\n");
|
||||
return NOSTR_SUCCESS;
|
||||
}
|
||||
|
||||
sprintf(rules_msg,
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - Checking rules for pubkey=%.32s..., "
|
||||
"operation=%s, mime_type=%s\n",
|
||||
@@ -1344,18 +1368,14 @@ static int check_database_auth_rules(const char *pubkey, const char *operation,
|
||||
}
|
||||
|
||||
// Step 1: Check pubkey blacklist (highest priority)
|
||||
// Match both exact operation and wildcard '*'
|
||||
const char *blacklist_sql =
|
||||
"SELECT rule_type, description FROM auth_rules WHERE rule_type = "
|
||||
"'pubkey_blacklist' AND rule_target = ? AND (operation = ? OR operation = '*') AND enabled = "
|
||||
"1 ORDER BY priority LIMIT 1";
|
||||
"SELECT rule_type FROM auth_rules WHERE rule_type LIKE 'blacklist_pubkey' AND pattern_type = 'pubkey' AND pattern_value = ? AND active = 1 LIMIT 1";
|
||||
rc = sqlite3_prepare_v2(db, blacklist_sql, -1, &stmt, NULL);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_bind_text(stmt, 1, pubkey, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, operation ? operation : "", -1, SQLITE_STATIC);
|
||||
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char *description = (const char *)sqlite3_column_text(stmt, 1);
|
||||
const char *description = "Pubkey blacklisted";
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 1 FAILED - "
|
||||
"Pubkey blacklisted\n");
|
||||
char blacklist_msg[256];
|
||||
@@ -1380,18 +1400,14 @@ static int check_database_auth_rules(const char *pubkey, const char *operation,
|
||||
|
||||
// Step 2: Check hash blacklist
|
||||
if (resource_hash) {
|
||||
// Match both exact operation and wildcard '*'
|
||||
const char *hash_blacklist_sql =
|
||||
"SELECT rule_type, description FROM auth_rules WHERE rule_type = "
|
||||
"'hash_blacklist' AND rule_target = ? AND (operation = ? OR operation = '*') AND enabled = "
|
||||
"1 ORDER BY priority LIMIT 1";
|
||||
"SELECT rule_type FROM auth_rules WHERE rule_type LIKE 'blacklist_hash' AND pattern_type = 'hash' AND pattern_value = ? AND active = 1 LIMIT 1";
|
||||
rc = sqlite3_prepare_v2(db, hash_blacklist_sql, -1, &stmt, NULL);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_bind_text(stmt, 1, resource_hash, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, operation ? operation : "", -1, SQLITE_STATIC);
|
||||
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char *description = (const char *)sqlite3_column_text(stmt, 1);
|
||||
const char *description = "Hash blacklisted";
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 2 FAILED - "
|
||||
"Hash blacklisted\n");
|
||||
char hash_blacklist_msg[256];
|
||||
@@ -1423,17 +1439,14 @@ static int check_database_auth_rules(const char *pubkey, const char *operation,
|
||||
if (mime_type) {
|
||||
// Match both exact MIME type and wildcard patterns (e.g., 'image/*')
|
||||
const char *mime_blacklist_sql =
|
||||
"SELECT rule_type, description FROM auth_rules WHERE rule_type = "
|
||||
"'mime_blacklist' AND (rule_target = ? OR rule_target LIKE '%/*' AND ? LIKE REPLACE(rule_target, '*', '%')) AND (operation = ? OR operation = '*') AND enabled = "
|
||||
"1 ORDER BY priority LIMIT 1";
|
||||
"SELECT rule_type FROM auth_rules WHERE rule_type LIKE 'blacklist_mime' AND pattern_type = 'mime' AND (pattern_value = ? OR pattern_value LIKE '%/*' AND ? LIKE REPLACE(pattern_value, '*', '%')) AND active = 1 LIMIT 1";
|
||||
rc = sqlite3_prepare_v2(db, mime_blacklist_sql, -1, &stmt, NULL);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_bind_text(stmt, 1, mime_type, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, mime_type, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 3, operation ? operation : "", -1, SQLITE_STATIC);
|
||||
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char *description = (const char *)sqlite3_column_text(stmt, 1);
|
||||
const char *description = "MIME type blacklisted";
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 3 FAILED - "
|
||||
"MIME type blacklisted\n");
|
||||
char mime_blacklist_msg[256];
|
||||
@@ -1462,133 +1475,151 @@ static int check_database_auth_rules(const char *pubkey, const char *operation,
|
||||
}
|
||||
|
||||
// Step 4: Check pubkey whitelist
|
||||
// Match both exact operation and wildcard '*'
|
||||
const char *whitelist_sql =
|
||||
"SELECT rule_type, description FROM auth_rules WHERE rule_type = "
|
||||
"'pubkey_whitelist' AND rule_target = ? AND (operation = ? OR operation = '*') AND enabled = "
|
||||
"1 ORDER BY priority LIMIT 1";
|
||||
"SELECT rule_type FROM auth_rules WHERE rule_type LIKE 'whitelist_pubkey' AND pattern_type = 'pubkey' AND pattern_value = ? AND active = 1 LIMIT 1";
|
||||
rc = sqlite3_prepare_v2(db, whitelist_sql, -1, &stmt, NULL);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_bind_text(stmt, 1, pubkey, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, operation ? operation : "", -1, SQLITE_STATIC);
|
||||
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char *description = (const char *)sqlite3_column_text(stmt, 1);
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 3 PASSED - "
|
||||
const char *description = "Pubkey whitelisted";
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 4 PASSED - "
|
||||
"Pubkey whitelisted\n");
|
||||
char whitelist_msg[256];
|
||||
sprintf(whitelist_msg,
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - Whitelist rule matched: %s\n",
|
||||
description ? description : "Unknown");
|
||||
snprintf(whitelist_msg,
|
||||
sizeof(whitelist_msg),
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - Whitelist rule matched: %s\n",
|
||||
description ? description : "Unknown");
|
||||
validator_debug_log(whitelist_msg);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return NOSTR_SUCCESS; // Allow whitelisted pubkey
|
||||
pubkey_whitelisted = 1;
|
||||
} else {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 4 - Pubkey not whitelisted\n");
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
} else {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 4 FAILED - Pubkey whitelist query failed\n");
|
||||
}
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 3 FAILED - Pubkey "
|
||||
"not whitelisted\n");
|
||||
|
||||
// Step 5: Check MIME type whitelist (only if not already denied)
|
||||
// Step 5: Check MIME type whitelist
|
||||
if (mime_type) {
|
||||
// Match both exact MIME type and wildcard patterns (e.g., 'image/*')
|
||||
char mime_pattern_wildcard[MAX_MIME_TYPE_LEN + 2];
|
||||
const char *mime_whitelist_sql =
|
||||
"SELECT rule_type, description FROM auth_rules WHERE rule_type = "
|
||||
"'mime_whitelist' AND (rule_target = ? OR rule_target LIKE '%/*' AND ? LIKE REPLACE(rule_target, '*', '%')) AND (operation = ? OR operation = '*') AND enabled = "
|
||||
"1 ORDER BY priority LIMIT 1";
|
||||
"SELECT rule_type FROM auth_rules WHERE rule_type LIKE 'whitelist_mime' AND pattern_type = 'mime' AND (pattern_value = ? OR pattern_value LIKE ? ) AND active = 1 LIMIT 1";
|
||||
rc = sqlite3_prepare_v2(db, mime_whitelist_sql, -1, &stmt, NULL);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_bind_text(stmt, 1, mime_type, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, mime_type, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 3, operation ? operation : "", -1, SQLITE_STATIC);
|
||||
const char *slash_pos = strchr(mime_type, '/');
|
||||
if (slash_pos != NULL) {
|
||||
size_t prefix_len = slash_pos - mime_type;
|
||||
if (prefix_len < MAX_MIME_TYPE_LEN) {
|
||||
snprintf(mime_pattern_wildcard, sizeof(mime_pattern_wildcard), "%.*s/%%", (int)prefix_len, mime_type);
|
||||
} else {
|
||||
snprintf(mime_pattern_wildcard, sizeof(mime_pattern_wildcard), "%%/%%");
|
||||
}
|
||||
} else {
|
||||
snprintf(mime_pattern_wildcard, sizeof(mime_pattern_wildcard), "%s/%%", mime_type);
|
||||
}
|
||||
sqlite3_bind_text(stmt, 2, mime_pattern_wildcard, -1, SQLITE_TRANSIENT);
|
||||
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char *description = (const char *)sqlite3_column_text(stmt, 1);
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 5 PASSED - "
|
||||
"MIME type whitelisted\n");
|
||||
const char *description = "MIME type whitelisted";
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 5 PASSED - MIME type whitelisted\n");
|
||||
char mime_whitelist_msg[256];
|
||||
sprintf(mime_whitelist_msg,
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - MIME whitelist rule matched: %s\n",
|
||||
description ? description : "Unknown");
|
||||
snprintf(mime_whitelist_msg,
|
||||
sizeof(mime_whitelist_msg),
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - MIME whitelist rule matched: %s (pattern=%s)\n",
|
||||
description ? description : "Unknown",
|
||||
mime_pattern_wildcard);
|
||||
validator_debug_log(mime_whitelist_msg);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return NOSTR_SUCCESS; // Allow whitelisted MIME type
|
||||
mime_whitelisted = 1;
|
||||
} else {
|
||||
char mime_not_msg[256];
|
||||
snprintf(mime_not_msg,
|
||||
sizeof(mime_not_msg),
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - STEP 5 - MIME type not whitelisted (pattern=%s)\n",
|
||||
mime_pattern_wildcard);
|
||||
validator_debug_log(mime_not_msg);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
} else {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 5 FAILED - Failed to prepare MIME whitelist query\n");
|
||||
}
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 5 FAILED - MIME "
|
||||
"type not whitelisted\n");
|
||||
} else {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 5 SKIPPED - No "
|
||||
"MIME type provided\n");
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 5 SKIPPED - No MIME type provided\n");
|
||||
}
|
||||
|
||||
// Step 6: Check if any MIME whitelist rules exist - if yes, deny by default
|
||||
// Match both exact operation and wildcard '*'
|
||||
// Step 6: Count MIME whitelist rules
|
||||
const char *mime_whitelist_exists_sql =
|
||||
"SELECT COUNT(*) FROM auth_rules WHERE rule_type = 'mime_whitelist' "
|
||||
"AND (operation = ? OR operation = '*') AND enabled = 1 LIMIT 1";
|
||||
"SELECT COUNT(*) FROM auth_rules WHERE rule_type LIKE 'whitelist_mime' "
|
||||
"AND pattern_type = 'mime' AND active = 1";
|
||||
rc = sqlite3_prepare_v2(db, mime_whitelist_exists_sql, -1, &stmt, NULL);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_bind_text(stmt, 1, operation ? operation : "", -1, SQLITE_STATIC);
|
||||
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
int mime_whitelist_count = sqlite3_column_int(stmt, 0);
|
||||
if (mime_whitelist_count > 0) {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 6 FAILED - "
|
||||
"MIME whitelist exists but type not in it\n");
|
||||
|
||||
// Set specific violation details for status code mapping
|
||||
strcpy(g_last_rule_violation.violation_type, "mime_whitelist_violation");
|
||||
strcpy(g_last_rule_violation.reason,
|
||||
"MIME type not whitelisted for this operation");
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return NOSTR_ERROR_AUTH_REQUIRED;
|
||||
}
|
||||
mime_whitelist_count = sqlite3_column_int(stmt, 0);
|
||||
char mime_cnt_msg[256];
|
||||
snprintf(mime_cnt_msg, sizeof(mime_cnt_msg),
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - MIME whitelist count: %d\n",
|
||||
mime_whitelist_count);
|
||||
validator_debug_log(mime_cnt_msg);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
} else {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 6 FAILED - Failed to prepare MIME whitelist count query\n");
|
||||
}
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 6 PASSED - No "
|
||||
"MIME whitelist restrictions apply\n");
|
||||
|
||||
// Step 7: Check if any whitelist rules exist - if yes, deny by default
|
||||
// Match both exact operation and wildcard '*'
|
||||
if (mime_whitelist_count > 0 && !mime_whitelisted) {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - MIME whitelist exists but MIME type not allowed\n");
|
||||
strcpy(g_last_rule_violation.violation_type, "mime_whitelist_violation");
|
||||
strcpy(g_last_rule_violation.reason, "MIME type not whitelisted for this operation");
|
||||
sqlite3_close(db);
|
||||
return NOSTR_ERROR_AUTH_REQUIRED;
|
||||
}
|
||||
|
||||
// Step 7: Count pubkey whitelist rules
|
||||
const char *whitelist_exists_sql =
|
||||
"SELECT COUNT(*) FROM auth_rules WHERE rule_type = 'pubkey_whitelist' "
|
||||
"AND (operation = ? OR operation = '*') AND enabled = 1 LIMIT 1";
|
||||
"SELECT COUNT(*) FROM auth_rules WHERE (rule_type LIKE 'whitelist_pubkey' OR rule_type LIKE 'pubkey_whitelist') "
|
||||
"AND pattern_type = 'pubkey' AND active = 1";
|
||||
rc = sqlite3_prepare_v2(db, whitelist_exists_sql, -1, &stmt, NULL);
|
||||
if (rc == SQLITE_OK) {
|
||||
sqlite3_bind_text(stmt, 1, operation ? operation : "", -1, SQLITE_STATIC);
|
||||
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
int whitelist_count = sqlite3_column_int(stmt, 0);
|
||||
if (whitelist_count > 0) {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 4 FAILED - "
|
||||
"Whitelist exists but pubkey not in it\n");
|
||||
|
||||
// Set specific violation details for status code mapping
|
||||
strcpy(g_last_rule_violation.violation_type, "whitelist_violation");
|
||||
strcpy(g_last_rule_violation.reason,
|
||||
"Public key not whitelisted for this operation");
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return NOSTR_ERROR_AUTH_REQUIRED;
|
||||
}
|
||||
pubkey_whitelist_count = sqlite3_column_int(stmt, 0);
|
||||
char pubkey_cnt_msg[256];
|
||||
snprintf(pubkey_cnt_msg, sizeof(pubkey_cnt_msg),
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - Pubkey whitelist count: %d\n",
|
||||
pubkey_whitelist_count);
|
||||
validator_debug_log(pubkey_cnt_msg);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
} else {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 7 FAILED - Failed to prepare pubkey whitelist count query\n");
|
||||
}
|
||||
|
||||
if (pubkey_whitelist_count > 0) {
|
||||
char pubkey_whitelist_msg[256];
|
||||
snprintf(pubkey_whitelist_msg, sizeof(pubkey_whitelist_msg),
|
||||
"VALIDATOR_DEBUG: RULES ENGINE - Pubkey whitelist exists (%d entries)\n",
|
||||
pubkey_whitelist_count);
|
||||
validator_debug_log(pubkey_whitelist_msg);
|
||||
}
|
||||
|
||||
if (pubkey_whitelist_count > 0 && !pubkey_whitelisted) {
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - Pubkey whitelist exists but pubkey not allowed\n");
|
||||
strcpy(g_last_rule_violation.violation_type, "whitelist_violation");
|
||||
strcpy(g_last_rule_violation.reason, "Public key not whitelisted for this operation");
|
||||
sqlite3_close(db);
|
||||
return NOSTR_ERROR_AUTH_REQUIRED;
|
||||
}
|
||||
|
||||
if ((mime_whitelist_count > 0 && !mime_whitelisted) ||
|
||||
(pubkey_whitelist_count > 0 && !pubkey_whitelisted)) {
|
||||
// Already handled above but include fallback
|
||||
sqlite3_close(db);
|
||||
return NOSTR_ERROR_AUTH_REQUIRED;
|
||||
}
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 4 PASSED - No "
|
||||
"whitelist restrictions apply\n");
|
||||
|
||||
sqlite3_close(db);
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - STEP 7 PASSED - All "
|
||||
"rule checks completed, default ALLOW\n");
|
||||
return NOSTR_SUCCESS; // Default allow if no restrictive rules matched
|
||||
validator_debug_log("VALIDATOR_DEBUG: RULES ENGINE - Completed whitelist checks\n");
|
||||
return NOSTR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user