v0.7.16 - Fixed blacklist authentication system - removed redundant action/parameters columns, added active=1 filtering, added comprehensive debug tracing, and identified that auth must be enabled for blacklist to work

This commit is contained in:
Your Name
2025-10-14 13:07:19 -04:00
parent 29680f0ee8
commit e833dcefd4
12 changed files with 245 additions and 156 deletions

View File

@@ -64,7 +64,7 @@ int process_admin_config_event(cJSON* event, char* error_message, size_t error_s
// Forward declaration for relay info initialization
void init_relay_info(void);
int add_auth_rule_from_config(const char* rule_type, const char* pattern_type,
const char* pattern_value, const char* action);
const char* pattern_value);
int remove_auth_rule_from_config(const char* rule_type, const char* pattern_type,
const char* pattern_value);
int is_config_table_ready(void);
@@ -2067,28 +2067,27 @@ int process_admin_auth_event(cJSON* event, char* error_message, size_t error_siz
// Add auth rule from configuration
int add_auth_rule_from_config(const char* rule_type, const char* pattern_type,
const char* pattern_value, const char* action) {
if (!g_db || !rule_type || !pattern_type || !pattern_value || !action) {
const char* pattern_value) {
if (!g_db || !rule_type || !pattern_type || !pattern_value) {
return -1;
}
const char* sql = "INSERT INTO auth_rules (rule_type, pattern_type, pattern_value, action) "
"VALUES (?, ?, ?, ?)";
const char* sql = "INSERT INTO auth_rules (rule_type, pattern_type, pattern_value) "
"VALUES (?, ?, ?)";
sqlite3_stmt* stmt;
int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
return -1;
}
sqlite3_bind_text(stmt, 1, rule_type, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, pattern_type, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, pattern_value, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 4, action, -1, SQLITE_STATIC);
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
return (rc == SQLITE_DONE) ? 0 : -1;
}
@@ -2725,13 +2724,13 @@ int handle_auth_query_unified(cJSON* event, const char* query_type, char* error_
// Build appropriate SQL query based on query type
if (strcmp(query_type, "all") == 0) {
sql = "SELECT rule_type, pattern_type, pattern_value, action FROM auth_rules ORDER BY rule_type, pattern_type";
sql = "SELECT rule_type, pattern_type, pattern_value FROM auth_rules WHERE active = 1 ORDER BY rule_type, pattern_type";
}
else if (strcmp(query_type, "whitelist") == 0) {
sql = "SELECT rule_type, pattern_type, pattern_value, action FROM auth_rules WHERE rule_type LIKE '%whitelist%' ORDER BY pattern_type";
sql = "SELECT rule_type, pattern_type, pattern_value FROM auth_rules WHERE rule_type LIKE '%whitelist%' AND active = 1 ORDER BY pattern_type";
}
else if (strcmp(query_type, "blacklist") == 0) {
sql = "SELECT rule_type, pattern_type, pattern_value, action FROM auth_rules WHERE rule_type LIKE '%blacklist%' ORDER BY pattern_type";
sql = "SELECT rule_type, pattern_type, pattern_value FROM auth_rules WHERE rule_type LIKE '%blacklist%' AND active = 1 ORDER BY pattern_type";
}
else if (strcmp(query_type, "pattern") == 0) {
// Get pattern value from tags
@@ -2740,7 +2739,7 @@ int handle_auth_query_unified(cJSON* event, const char* query_type, char* error_
snprintf(error_message, error_size, "invalid: pattern query requires pattern value");
return -1;
}
sql = "SELECT rule_type, pattern_type, pattern_value, action FROM auth_rules WHERE pattern_value = ? ORDER BY rule_type, pattern_type";
sql = "SELECT rule_type, pattern_type, pattern_value FROM auth_rules WHERE pattern_value = ? AND active = 1 ORDER BY rule_type, pattern_type";
use_pattern_param = 1;
}
else {
@@ -2775,7 +2774,6 @@ int handle_auth_query_unified(cJSON* event, const char* query_type, char* error_
const char* rule_type = (const char*)sqlite3_column_text(stmt, 0);
const char* pattern_type = (const char*)sqlite3_column_text(stmt, 1);
const char* pattern_value_result = (const char*)sqlite3_column_text(stmt, 2);
const char* action = (const char*)sqlite3_column_text(stmt, 3);
// printf(" %s %s:%s -> %s\n",
// rule_type ? rule_type : "",
@@ -2788,7 +2786,7 @@ int handle_auth_query_unified(cJSON* event, const char* query_type, char* error_
cJSON_AddStringToObject(rule_obj, "rule_type", rule_type ? rule_type : "");
cJSON_AddStringToObject(rule_obj, "pattern_type", pattern_type ? pattern_type : "");
cJSON_AddStringToObject(rule_obj, "pattern_value", pattern_value_result ? pattern_value_result : "");
cJSON_AddStringToObject(rule_obj, "action", action ? action : "allow");
cJSON_AddStringToObject(rule_obj, "action", "allow"); // Simplified: rule_type determines behavior
cJSON_AddItemToArray(results_array, rule_obj);
rule_count++;
@@ -3314,7 +3312,7 @@ int handle_auth_rule_modification_unified(cJSON* event, char* error_message, siz
// Process auth rule: ["blacklist"|"whitelist", "pubkey"|"hash", "value"]
if (strcmp(rule_type, "blacklist") == 0 || strcmp(rule_type, "whitelist") == 0) {
if (add_auth_rule_from_config(rule_type, pattern_type, pattern_value, "allow") == 0) {
if (add_auth_rule_from_config(rule_type, pattern_type, pattern_value) == 0) {
rules_processed++;
// Add processed rule to response array
@@ -3322,7 +3320,7 @@ int handle_auth_rule_modification_unified(cJSON* event, char* error_message, siz
cJSON_AddStringToObject(rule_obj, "rule_type", rule_type);
cJSON_AddStringToObject(rule_obj, "pattern_type", pattern_type);
cJSON_AddStringToObject(rule_obj, "pattern_value", pattern_value);
cJSON_AddStringToObject(rule_obj, "action", "allow");
cJSON_AddStringToObject(rule_obj, "action", "allow"); // Simplified: rule_type determines behavior
cJSON_AddStringToObject(rule_obj, "status", "added");
cJSON_AddItemToArray(processed_rules, rule_obj);
}

View File

@@ -114,7 +114,7 @@ cJSON* build_query_response(const char* query_type, cJSON* results_array, int to
// Auth rules management functions
int add_auth_rule_from_config(const char* rule_type, const char* pattern_type,
const char* pattern_value, const char* action);
const char* pattern_value);
int remove_auth_rule_from_config(const char* rule_type, const char* pattern_type,
const char* pattern_value);

File diff suppressed because one or more lines are too long

View File

@@ -15,6 +15,7 @@
#include "../nostr_core_lib/nostr_core/nip013.h" // NIP-13: Proof of Work
#include "../nostr_core_lib/nostr_core/nostr_common.h"
#include "../nostr_core_lib/nostr_core/utils.h"
#include "debug.h" // C-relay debug system
#include "config.h" // C-relay configuration system
#include <sqlite3.h>
#include <stdio.h>
@@ -531,6 +532,8 @@ int check_database_auth_rules(const char *pubkey, const char *operation __attrib
sqlite3_stmt *stmt = NULL;
int rc;
DEBUG_TRACE("Checking auth rules for pubkey: %s", pubkey);
if (!pubkey) {
return NOSTR_ERROR_INVALID_INPUT;
}
@@ -547,19 +550,21 @@ int check_database_auth_rules(const char *pubkey, const char *operation __attrib
// Step 1: Check pubkey blacklist (highest priority)
const char *blacklist_sql =
"SELECT rule_type, action FROM auth_rules WHERE rule_type = "
"'blacklist' AND pattern_type = 'pubkey' AND pattern_value = ? LIMIT 1";
"SELECT rule_type FROM auth_rules WHERE rule_type = "
"'blacklist' AND pattern_type = 'pubkey' AND pattern_value = ? AND active = 1 LIMIT 1";
DEBUG_TRACE("Blacklist SQL: %s", blacklist_sql);
rc = sqlite3_prepare_v2(db, blacklist_sql, -1, &stmt, NULL);
if (rc == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, pubkey, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) == SQLITE_ROW) {
const char *action = (const char *)sqlite3_column_text(stmt, 1);
int step_result = sqlite3_step(stmt);
DEBUG_TRACE("Blacklist query result: %s", step_result == SQLITE_ROW ? "FOUND" : "NOT_FOUND");
if (step_result == SQLITE_ROW) {
DEBUG_TRACE("BLACKLIST HIT: Denying access for pubkey: %s", pubkey);
// Set specific violation details for status code mapping
strcpy(g_last_rule_violation.violation_type, "pubkey_blacklist");
sprintf(g_last_rule_violation.reason, "Public key blacklisted: %s",
action ? action : "PUBKEY_BLACKLIST");
sprintf(g_last_rule_violation.reason, "Public key blacklisted");
sqlite3_finalize(stmt);
sqlite3_close(db);
@@ -571,19 +576,16 @@ int check_database_auth_rules(const char *pubkey, const char *operation __attrib
// Step 2: Check hash blacklist
if (resource_hash) {
const char *hash_blacklist_sql =
"SELECT rule_type, action FROM auth_rules WHERE rule_type = "
"'blacklist' AND pattern_type = 'hash' AND pattern_value = ? LIMIT 1";
"SELECT rule_type FROM auth_rules WHERE rule_type = "
"'blacklist' 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);
if (sqlite3_step(stmt) == SQLITE_ROW) {
const char *action = (const char *)sqlite3_column_text(stmt, 1);
// Set specific violation details for status code mapping
strcpy(g_last_rule_violation.violation_type, "hash_blacklist");
sprintf(g_last_rule_violation.reason, "File hash blacklisted: %s",
action ? action : "HASH_BLACKLIST");
sprintf(g_last_rule_violation.reason, "File hash blacklisted");
sqlite3_finalize(stmt);
sqlite3_close(db);
@@ -595,8 +597,8 @@ int check_database_auth_rules(const char *pubkey, const char *operation __attrib
// Step 3: Check pubkey whitelist
const char *whitelist_sql =
"SELECT rule_type, action FROM auth_rules WHERE rule_type = "
"'whitelist' AND pattern_type = 'pubkey' AND pattern_value = ? LIMIT 1";
"SELECT rule_type FROM auth_rules WHERE rule_type = "
"'whitelist' 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);
@@ -612,7 +614,7 @@ int check_database_auth_rules(const char *pubkey, const char *operation __attrib
// Step 4: Check if any whitelist rules exist - if yes, deny by default
const char *whitelist_exists_sql =
"SELECT COUNT(*) FROM auth_rules WHERE rule_type = 'whitelist' "
"AND pattern_type = 'pubkey' LIMIT 1";
"AND pattern_type = 'pubkey' AND active = 1 LIMIT 1";
rc = sqlite3_prepare_v2(db, whitelist_exists_sql, -1, &stmt, NULL);
if (rc == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {

View File

@@ -142,8 +142,6 @@ CREATE TABLE auth_rules (\n\
rule_type TEXT NOT NULL CHECK (rule_type IN ('whitelist', 'blacklist', 'rate_limit', 'auth_required')),\n\
pattern_type TEXT NOT NULL CHECK (pattern_type IN ('pubkey', 'kind', 'ip', 'global')),\n\
pattern_value TEXT,\n\
action TEXT NOT NULL CHECK (action IN ('allow', 'deny', 'require_auth', 'rate_limit')),\n\
parameters TEXT, -- JSON parameters for rate limiting, etc.\n\
active INTEGER NOT NULL DEFAULT 1,\n\
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n\
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n\

View File

@@ -516,7 +516,7 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
if (event_kind == 23456) {
if (admin_result != 0) {
char error_result_msg[512];
if (admin_error && strlen(admin_error) > 0) {
if (strlen(admin_error) > 0) {
// Safely truncate admin_error if too long
size_t max_error_len = sizeof(error_result_msg) - 50; // Leave room for prefix
size_t error_len = strlen(admin_error);
@@ -532,7 +532,12 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
"ERROR: Kind %d event processing failed: ", event_kind);
if (prefix_len < sizeof(error_result_msg)) {
size_t remaining = sizeof(error_result_msg) - prefix_len;
strncat(error_result_msg, truncated_error, remaining - 1);
size_t copy_len = strlen(truncated_error);
if (copy_len >= remaining) {
copy_len = remaining - 1;
}
memcpy(error_result_msg + prefix_len, truncated_error, copy_len);
error_result_msg[prefix_len + copy_len] = '\0';
}
} else {
snprintf(error_result_msg, sizeof(error_result_msg),