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:
36
src/config.c
36
src/config.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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\
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user