Compare commits

..

1 Commits

Author SHA1 Message Date
Your Name
49ffc3d99e v0.7.11 - Got api back working after switching to static build 2025-10-12 14:54:02 -04:00
7 changed files with 106 additions and 189 deletions

View File

@@ -1096,12 +1096,8 @@
});
}
// Automatically refresh configuration display after successful update
setTimeout(() => {
fetchConfiguration().catch(error => {
console.log('Auto-refresh configuration failed after update: ' + error.message);
});
}, 1000);
// Configuration updated successfully - user can manually refresh using Fetch Config button
log('Configuration updated successfully. Click "Fetch Config" to refresh the display.', 'INFO');
} else {
const errorMessage = responseData.message || responseData.error || 'Unknown error';

View File

@@ -1 +1 @@
1425176
1478877

View File

@@ -227,8 +227,7 @@ static int refresh_unified_cache_from_table(void) {
const char* count_sql = "SELECT COUNT(*) FROM config";
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
int row_count = sqlite3_column_int(count_stmt, 0);
printf("[DEBUG] refresh_unified_cache_from_table: Config table row count at start: %d\n", row_count);
// Row count check completed
}
sqlite3_finalize(count_stmt);
}
@@ -372,8 +371,7 @@ static int refresh_unified_cache_from_table(void) {
// Log config table row count at end of refresh_unified_cache_from_table
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
int row_count = sqlite3_column_int(count_stmt, 0);
printf("[DEBUG] refresh_unified_cache_from_table: Config table row count at end: %d\n", row_count);
// Row count check completed
}
sqlite3_finalize(count_stmt);
}
@@ -1141,8 +1139,8 @@ cJSON* create_default_config_event(const unsigned char* admin_privkey_bytes,
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
if (id_obj && pubkey_obj) {
printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
printf(" Admin Public Key: %s\n", cJSON_GetStringValue(pubkey_obj));
// printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
// printf(" Admin Public Key: %s\n", cJSON_GetStringValue(pubkey_obj));
}
return event;
@@ -1308,8 +1306,7 @@ int startup_existing_relay(const char* relay_pubkey) {
const char* count_sql = "SELECT COUNT(*) FROM config";
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
int row_count = sqlite3_column_int(count_stmt, 0);
printf("[DEBUG] startup_existing_relay: Config table row count at start: %d\n", row_count);
// Row count check completed
}
sqlite3_finalize(count_stmt);
}
@@ -1347,8 +1344,7 @@ int startup_existing_relay(const char* relay_pubkey) {
const char* count_sql = "SELECT COUNT(*) FROM config";
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
int row_count = sqlite3_column_int(count_stmt, 0);
printf("[DEBUG] startup_existing_relay: Config table row count at end: %d\n", row_count);
// Row count check completed
}
sqlite3_finalize(count_stmt);
}
@@ -2168,8 +2164,7 @@ int populate_default_config_values(void) {
const char* count_sql = "SELECT COUNT(*) FROM config";
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
int row_count = sqlite3_column_int(count_stmt, 0);
printf("[DEBUG] populate_default_config_values: Config table row count at start: %d\n", row_count);
// Row count check completed
}
sqlite3_finalize(count_stmt);
}
@@ -2309,8 +2304,7 @@ int populate_default_config_values(void) {
// Log config table row count at end of populate_default_config_values
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
int row_count = sqlite3_column_int(count_stmt, 0);
printf("[DEBUG] populate_default_config_values: Config table row count at end: %d\n", row_count);
// Row count check completed
}
sqlite3_finalize(count_stmt);
}
@@ -2330,8 +2324,7 @@ int add_pubkeys_to_config_table(void) {
const char* count_sql = "SELECT COUNT(*) FROM config";
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
int row_count = sqlite3_column_int(count_stmt, 0);
printf("[DEBUG] add_pubkeys_to_config_table: Config table row count at start: %d\n", row_count);
// Row count check completed
}
sqlite3_finalize(count_stmt);
}
@@ -2428,8 +2421,7 @@ int add_pubkeys_to_config_table(void) {
// Log config table row count at end of add_pubkeys_to_config_table
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
int row_count = sqlite3_column_int(count_stmt, 0);
printf("[DEBUG] add_pubkeys_to_config_table: Config table row count at end: %d\n", row_count);
// Row count check completed
}
sqlite3_finalize(count_stmt);
}
@@ -2455,11 +2447,6 @@ int process_admin_event_in_config(cJSON* event, char* error_message, size_t erro
int kind = (int)cJSON_GetNumberValue(kind_obj);
// Get event pubkey for authorization logging
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
const char* event_pubkey = pubkey_obj ? cJSON_GetStringValue(pubkey_obj) : NULL;
// Route to appropriate handler based on kind
switch (kind) {
case 23456: // New ephemeral auth rules management
@@ -2571,16 +2558,12 @@ int process_admin_auth_event(cJSON* event, char* error_message, size_t error_siz
int kind = kind_obj ? (int)cJSON_GetNumberValue(kind_obj) : 0;
// Extract and log additional event details for debugging
cJSON* content_obj = cJSON_GetObjectItem(event, "content");
cJSON* tags_obj = cJSON_GetObjectItem(event, "tags");
const char* event_content = content_obj ? cJSON_GetStringValue(content_obj) : "unknown";
printf(" Content length: %zu\n", event_content ? strlen(event_content) : 0);
printf(" Has tags: %s\n", tags_obj ? "yes" : "no");
if (tags_obj && cJSON_IsArray(tags_obj)) {
printf(" Tags count: %d\n", cJSON_GetArraySize(tags_obj));
}
// printf(" Content length: %zu\n", event_content ? strlen(event_content) : 0);
// printf(" Has tags: %s\n", tags_obj ? "yes" : "no");
// if (tags_obj && cJSON_IsArray(tags_obj)) {
// printf(" Tags count: %d\n", cJSON_GetArraySize(tags_obj));
// }
// Route all Kind 23456 events through the unified handler
if (kind == 23456) {
@@ -2731,8 +2714,8 @@ cJSON* create_admin_response_event(const char* encrypted_content, const char* re
return NULL;
}
printf(" Recipient pubkey: %.16s...\n", recipient_pubkey);
printf(" Encrypted content length: %zu\n", strlen(encrypted_content));
// printf(" Recipient pubkey: %.16s...\n", recipient_pubkey);
// printf(" Encrypted content length: %zu\n", strlen(encrypted_content));
// Get relay private key for signing
char* relay_privkey = get_relay_private_key();
@@ -2789,8 +2772,8 @@ cJSON* create_admin_response_event(const char* encrypted_content, const char* re
cJSON* pubkey_obj = cJSON_GetObjectItem(response_event, "pubkey");
if (id_obj && pubkey_obj) {
printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
printf(" Relay pubkey: %.16s...\n", cJSON_GetStringValue(pubkey_obj));
// printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
// printf(" Relay pubkey: %.16s...\n", cJSON_GetStringValue(pubkey_obj));
}
return response_event;
@@ -2803,7 +2786,6 @@ char* encrypt_admin_response_content(const cJSON* response_data, const char* rec
return NULL;
}
printf(" Recipient pubkey: %.16s...\n", recipient_pubkey);
// Convert response data to JSON string
char* response_json = cJSON_Print(response_data);
@@ -2812,9 +2794,9 @@ char* encrypt_admin_response_content(const cJSON* response_data, const char* rec
return NULL;
}
printf(" JSON length: %zu\n", strlen(response_json));
printf(" JSON preview: %.100s%s\n", response_json,
strlen(response_json) > 100 ? "..." : "");
// printf(" JSON length: %zu\n", strlen(response_json));
// printf(" JSON preview: %.100s%s\n", response_json,
// strlen(response_json) > 100 ? "..." : "");
// Get relay private key for encryption
char* relay_privkey = get_relay_private_key();
@@ -2867,8 +2849,8 @@ char* encrypt_admin_response_content(const cJSON* response_data, const char* rec
return NULL;
}
printf(" Encrypted content length: %zu\n", strlen(encrypted_content));
printf(" Encrypted preview: %.50s...\n", encrypted_content);
// printf(" Encrypted content length: %zu\n", strlen(encrypted_content));
// printf(" Encrypted preview: %.50s...\n", encrypted_content);
// Return encrypted content as allocated string
return strdup(encrypted_content);
@@ -2883,7 +2865,6 @@ int send_admin_response_event(const cJSON* response_data, const char* recipient_
return -1;
}
printf(" Recipient pubkey: %.16s...\n", recipient_pubkey);
// Step 1: Encrypt response data using NIP-44
char* encrypted_content = encrypt_admin_response_content(response_data, recipient_pubkey);
@@ -2903,7 +2884,7 @@ int send_admin_response_event(const cJSON* response_data, const char* recipient_
cJSON* id_obj = cJSON_GetObjectItem(response_event, "id");
if (id_obj) {
printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
// printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
}
// Step 3: Store event in database for persistence
@@ -2917,8 +2898,6 @@ int send_admin_response_event(const cJSON* response_data, const char* recipient_
int broadcast_count = broadcast_event_to_subscriptions(response_event);
if (broadcast_count >= 0) {
printf(" Event kind: 23457 (admin response)\n");
printf(" Subscriptions notified: %d\n", broadcast_count);
// Clean up and return success - event creation succeeded regardless of broadcast count
cJSON_Delete(response_event);
@@ -2995,7 +2974,32 @@ int handle_kind_23456_unified(cJSON* event, char* error_message, size_t error_si
snprintf(error_message, error_size, "invalid: null event");
return -1;
}
// Verify the event sender is the authorized admin
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
if (!pubkey_obj || !cJSON_IsString(pubkey_obj)) {
log_error("invalid: missing sender pubkey in event");
snprintf(error_message, error_size, "invalid: missing sender pubkey in event");
return -1;
}
const char* sender_pubkey = cJSON_GetStringValue(pubkey_obj);
const char* admin_pubkey = get_admin_pubkey_cached();
if (!admin_pubkey) {
log_error("error: admin pubkey not available for authorization check");
snprintf(error_message, error_size, "error: admin pubkey not available for authorization check");
return -1;
}
if (strcmp(sender_pubkey, admin_pubkey) != 0) {
log_error("invalid: unauthorized admin event - sender pubkey does not match admin pubkey");
printf(" Sender pubkey: %.16s...\n", sender_pubkey);
printf(" Admin pubkey: %.16s...\n", admin_pubkey);
snprintf(error_message, error_size, "invalid: unauthorized admin event");
return -1;
}
// Check if content is encrypted (NIP-44)
cJSON* content_obj = cJSON_GetObjectItem(event, "content");
if (!content_obj || !cJSON_IsString(content_obj)) {
@@ -3280,7 +3284,7 @@ int handle_auth_query_unified(cJSON* event, const char* query_type, char* error_
}
int rule_count = 0;
printf("=== Auth Query Results (%s) ===\n", query_type);
// printf("=== Auth Query Results (%s) ===\n", query_type);
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char* rule_type = (const char*)sqlite3_column_text(stmt, 0);
@@ -3288,11 +3292,11 @@ int handle_auth_query_unified(cJSON* event, const char* query_type, char* error_
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 : "",
pattern_type ? pattern_type : "",
pattern_value_result ? pattern_value_result : "",
action ? action : "allow");
// printf(" %s %s:%s -> %s\n",
// rule_type ? rule_type : "",
// pattern_type ? pattern_type : "",
// pattern_value_result ? pattern_value_result : "",
// action ? action : "allow");
// Add rule to results array
cJSON* rule_obj = cJSON_CreateObject();
@@ -3324,8 +3328,6 @@ int handle_auth_query_unified(cJSON* event, const char* query_type, char* error_
// Send response as signed kind 23457 event
if (send_admin_response_event(response, admin_pubkey, wsi) == 0) {
printf("Total results: %d\n", rule_count);
printf(" Response query_type: %s (mapped from %s)\n", mapped_query_type, query_type);
cJSON_Delete(response);
cJSON_Delete(results_array);
return 0;
@@ -3401,7 +3403,6 @@ int handle_config_query_unified(cJSON* event, const char* query_type, char* erro
}
int config_count = 0;
printf("=== Config Query Results (%s) ===\n", query_type);
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char* key = (const char*)sqlite3_column_text(stmt, 0);
@@ -3410,11 +3411,6 @@ int handle_config_query_unified(cJSON* event, const char* query_type, char* erro
const char* category = (const char*)sqlite3_column_text(stmt, 3);
const char* description = (const char*)sqlite3_column_text(stmt, 4);
printf(" %s = %s [%s] (%s)\n",
key ? key : "",
value ? value : "",
data_type ? data_type : "string",
category ? category : "general");
// Add config item to results array
cJSON* config_obj = cJSON_CreateObject();
@@ -3447,8 +3443,6 @@ int handle_config_query_unified(cJSON* event, const char* query_type, char* erro
// Send response as signed kind 23457 event
if (send_admin_response_event(response, admin_pubkey, wsi) == 0) {
printf("Total results: %d\n", config_count);
printf(" Response query_type: %s (mapped from %s)\n", mapped_query_type, query_type);
cJSON_Delete(response);
cJSON_Delete(results_array);
return 0;
@@ -3519,7 +3513,6 @@ int handle_config_set_unified(cJSON* event, const char* config_key, const char*
cJSON_AddStringToObject(response, "status", "success");
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
printf("Updated config: %s = %s\n", config_key, config_value);
// Get admin pubkey from event for response
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
@@ -3584,7 +3577,6 @@ int handle_system_command_unified(cJSON* event, const char* command, char* error
cJSON_AddStringToObject(response, "status", "success");
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
printf("Cleared %d auth rules from database\n", rule_count);
// Get admin pubkey from event for response
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
@@ -3662,7 +3654,6 @@ int handle_system_command_unified(cJSON* event, const char* command, char* error
cJSON_AddStringToObject(response, "status", "success");
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
printf("Deleted auth rule: %s %s:%s\n", rule_type, pattern_type, pattern_value);
// Get admin pubkey from event for response
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
@@ -4001,10 +3992,6 @@ int handle_stats_query_unified(cJSON* event, char* error_message, size_t error_s
sqlite3_finalize(stmt);
}
printf("=== Database Statistics ===\n");
printf("Database size: %lld bytes\n", db_size);
printf("Event kinds: %d\n", cJSON_GetArraySize(event_kinds));
printf("Top pubkeys: %d\n", cJSON_GetArraySize(top_pubkeys));
// Get admin pubkey from event for response
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
@@ -4381,7 +4368,6 @@ int handle_config_update_unified(cJSON* event, char* error_message, size_t error
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
cJSON_AddItemToObject(response, "processed_configs", processed_configs);
printf("Config update completed: %d/%d configs updated successfully\n", updates_applied, config_count);
// Get admin pubkey from event for response
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");

File diff suppressed because one or more lines are too long

View File

@@ -1343,8 +1343,6 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
return -1;
}
// DEBUG: Log that we're checking admin authorization
log_info("DEBUG: Checking admin event authorization");
// Step 1: Verify event kind is admin type
cJSON *kind_json = cJSON_GetObjectItem(event, "kind");
@@ -1380,12 +1378,6 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
// Compare with our relay pubkey
const char* relay_pubkey = get_config_value("relay_pubkey");
char debug_msg1[256];
snprintf(debug_msg1, sizeof(debug_msg1), "DEBUG: Relay pubkey from config: %.64s", relay_pubkey ? relay_pubkey : "NULL");
log_info(debug_msg1);
char debug_msg2[256];
snprintf(debug_msg2, sizeof(debug_msg2), "DEBUG: Event p tag value: %.64s", tag_value->valuestring);
log_info(debug_msg2);
if (relay_pubkey && strcmp(tag_value->valuestring, relay_pubkey) == 0) {
targets_this_relay = 1;
break;
@@ -1396,7 +1388,6 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
if (!targets_this_relay) {
// Admin event for different relay - not an error, just not for us
log_info("DEBUG: Admin event not targeting this relay");
snprintf(error_buffer, error_buffer_size, "Admin event not targeting this relay");
return -1;
}
@@ -1411,12 +1402,6 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
// Get admin pubkey from configuration
const char* admin_pubkey = get_config_value("admin_pubkey");
char debug_msg3[256];
snprintf(debug_msg3, sizeof(debug_msg3), "DEBUG: Admin pubkey from config: %.64s", admin_pubkey ? admin_pubkey : "NULL");
log_info(debug_msg3);
char debug_msg4[256];
snprintf(debug_msg4, sizeof(debug_msg4), "DEBUG: Event pubkey: %.64s", pubkey_json->valuestring);
log_info(debug_msg4);
if (!admin_pubkey || strlen(admin_pubkey) == 0) {
log_warning("Unauthorized admin event attempt: no admin pubkey configured");
snprintf(error_buffer, error_buffer_size, "Unauthorized admin event attempt: no admin configured");
@@ -1435,20 +1420,16 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
return -1;
}
log_info("DEBUG: Pubkey comparison passed");
// Step 4: Verify event signature
if (nostr_verify_event_signature(event) != 0) {
log_warning("Unauthorized admin event attempt: invalid signature");
log_info("DEBUG: Signature verification failed");
snprintf(error_buffer, error_buffer_size, "Unauthorized admin event attempt: signature verification failed");
return -1;
}
log_info("DEBUG: Signature verification passed");
// All checks passed - authorized admin event
log_info("DEBUG: Admin event authorization successful");
return 0;
}
@@ -1751,15 +1732,14 @@ int main(int argc, char* argv[]) {
return 1;
}
// DEBUG: Check config table row count before database initialization
// Check config table row count before database initialization
{
sqlite3* temp_db = NULL;
if (sqlite3_open(g_database_path, &temp_db) == SQLITE_OK) {
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(temp_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
int count = sqlite3_column_int(stmt, 0);
printf("[DEBUG] Config table row count before init_database(): %d\n", count);
// Row count check completed
}
sqlite3_finalize(stmt);
}
@@ -1780,13 +1760,12 @@ int main(int argc, char* argv[]) {
return 1;
}
// DEBUG: Check config table row count after database initialization
// Check config table row count after database initialization
{
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(g_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
int count = sqlite3_column_int(stmt, 0);
printf("[DEBUG] Config table row count after init_database(): %d\n", count);
// Row count check completed
}
sqlite3_finalize(stmt);
}
@@ -1807,7 +1786,8 @@ int main(int argc, char* argv[]) {
}
cJSON_Delete(config_event);
} else {
log_warning("No configuration event found in existing database");
// This is expected for relays using table-based configuration
// No longer a warning - just informational
}
// Ensure pubkeys are in config table for existing relay
@@ -1833,18 +1813,6 @@ int main(int argc, char* argv[]) {
// If either pubkey is missing, call add_pubkeys_to_config_table to populate both
if (need_to_add_pubkeys) {
// DEBUG: Check config table row count before add_pubkeys_to_config_table()
{
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(g_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
int count = sqlite3_column_int(stmt, 0);
printf("[DEBUG] Config table row count before add_pubkeys_to_config_table(): %d\n", count);
}
sqlite3_finalize(stmt);
}
}
if (add_pubkeys_to_config_table() != 0) {
log_error("Failed to add pubkeys to config table for existing relay");
cleanup_configuration_system();
@@ -1852,18 +1820,6 @@ int main(int argc, char* argv[]) {
close_database();
return 1;
}
// DEBUG: Check config table row count after add_pubkeys_to_config_table()
{
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(g_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
int count = sqlite3_column_int(stmt, 0);
printf("[DEBUG] Config table row count after add_pubkeys_to_config_table(): %d\n", count);
}
sqlite3_finalize(stmt);
}
}
}
// Apply CLI overrides for existing relay (port override should work even for existing relays)

View File

@@ -53,6 +53,7 @@ extern struct expiration_config {
// Configuration functions from C-relay
extern int get_config_bool(const char* key, int default_value);
extern int get_config_int(const char* key, int default_value);
extern const char* get_admin_pubkey_cached(void);
// NIP-42 constants (from nostr_core_lib)
#define NOSTR_NIP42_AUTH_EVENT_KIND 22242
@@ -294,10 +295,26 @@ int nostr_validate_unified_request(const char* json_string, size_t json_length)
}
/////////////////////////////////////////////////////////////////////
// PHASE 3: EVENT KIND SPECIFIC VALIDATION
// PHASE 3: ADMIN EVENT BYPASS CHECK
/////////////////////////////////////////////////////////////////////
// 8. Handle NIP-42 authentication challenge events (kind 22242)
// 8. Check if this is a kind 23456 admin event from authorized admin
// This must happen AFTER signature validation but BEFORE auth rules
if (event_kind == 23456) {
const char* admin_pubkey = get_admin_pubkey_cached();
if (admin_pubkey && strcmp(event_pubkey, admin_pubkey) == 0) {
// Valid admin event - bypass remaining validation
cJSON_Delete(event);
return NOSTR_SUCCESS;
}
// Not from admin - continue with normal validation
}
/////////////////////////////////////////////////////////////////////
// PHASE 4: EVENT KIND SPECIFIC VALIDATION
/////////////////////////////////////////////////////////////////////
// 9. Handle NIP-42 authentication challenge events (kind 22242)
if (event_kind == 22242) {
// Check NIP-42 mode using unified cache
const char* nip42_enabled = get_config_value("nip42_auth_enabled");
@@ -315,13 +332,13 @@ int nostr_validate_unified_request(const char* json_string, size_t json_length)
}
/////////////////////////////////////////////////////////////////////
// PHASE 4: AUTHENTICATION RULES (Database Queries)
// PHASE 5: AUTHENTICATION RULES (Database Queries)
/////////////////////////////////////////////////////////////////////
// 9. Check if authentication rules are enabled
// 10. Check if authentication rules are enabled
if (!auth_required) {
} else {
// 10. Check database authentication rules (only if auth enabled)
// 11. Check database authentication rules (only if auth enabled)
// Create operation string with event kind for more specific rule matching
char operation_str[64];
@@ -340,16 +357,16 @@ int nostr_validate_unified_request(const char* json_string, size_t json_length)
}
/////////////////////////////////////////////////////////////////////
// PHASE 5: ADDITIONAL VALIDATIONS (C-relay specific)
// PHASE 6: ADDITIONAL VALIDATIONS (C-relay specific)
/////////////////////////////////////////////////////////////////////
// 11. NIP-13 Proof of Work validation
// 12. NIP-13 Proof of Work validation
pthread_mutex_lock(&g_unified_cache.cache_lock);
int pow_enabled = g_unified_cache.pow_config.enabled;
int pow_min_difficulty = g_unified_cache.pow_config.min_pow_difficulty;
int pow_validation_flags = g_unified_cache.pow_config.validation_flags;
pthread_mutex_unlock(&g_unified_cache.cache_lock);
if (pow_enabled && pow_min_difficulty > 0) {
nostr_pow_result_t pow_result;
int pow_validation_result = nostr_validate_pow(event, pow_min_difficulty,
@@ -361,7 +378,7 @@ int nostr_validate_unified_request(const char* json_string, size_t json_length)
}
}
// 12. NIP-40 Expiration validation
// 13. NIP-40 Expiration validation
// Always check expiration tags if present (following NIP-40 specification)
cJSON *expiration_tag = NULL;

View File

@@ -298,11 +298,9 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
cJSON* kind_obj = cJSON_GetObjectItem(event_obj, "kind");
int event_kind = kind_obj && cJSON_IsNumber(kind_obj) ? (int)cJSON_GetNumberValue(kind_obj) : -1;
// Extract pubkey and event ID for debugging
// Extract pubkey for debugging
cJSON* pubkey_obj = cJSON_GetObjectItem(event_obj, "pubkey");
cJSON* id_obj = cJSON_GetObjectItem(event_obj, "id");
const char* event_pubkey = pubkey_obj ? cJSON_GetStringValue(pubkey_obj) : "unknown";
const char* event_id = id_obj ? cJSON_GetStringValue(id_obj) : "unknown";
// Check if NIP-42 authentication is required for this event kind or globally
int auth_required = is_nip42_auth_globally_required() || is_nip42_auth_required_for_kind(event_kind);
@@ -332,6 +330,16 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
}
}
// Special case: allow kind 23456 admin events from authorized admin to bypass auth
if (event_kind == 23456 && event_pubkey) {
const char* admin_pubkey = get_admin_pubkey_cached();
if (admin_pubkey && strcmp(event_pubkey, admin_pubkey) == 0) {
bypass_auth = 1;
} else {
log_info("DEBUG: Kind 23456 event but pubkey mismatch or no admin pubkey");
}
}
if (pss && auth_required && !pss->authenticated && !bypass_auth) {
if (!pss->auth_challenge_sent) {
send_nip42_auth_challenge(wsi, pss);
@@ -352,50 +360,6 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
return 0;
}
// Check blacklist/whitelist rules regardless of NIP-42 auth settings
// Blacklist should always be enforced
if (event_pubkey) {
// Forward declaration for auth rules checking function
extern int check_database_auth_rules(const char *pubkey, const char *operation, const char *resource_hash);
int auth_rules_result = check_database_auth_rules(event_pubkey, "event", NULL);
if (auth_rules_result != 0) { // 0 = NOSTR_SUCCESS, non-zero = blocked
char auth_rules_msg[256];
if (auth_rules_result == -101) { // NOSTR_ERROR_AUTH_REQUIRED
snprintf(auth_rules_msg, sizeof(auth_rules_msg),
"blocked: pubkey not authorized (blacklist/whitelist violation)");
} else {
snprintf(auth_rules_msg, sizeof(auth_rules_msg),
"blocked: authorization check failed (error %d)", auth_rules_result);
}
send_notice_message(wsi, auth_rules_msg);
log_warning("Event rejected: blacklist/whitelist violation");
// Send OK response with false status
cJSON* response = cJSON_CreateArray();
cJSON_AddItemToArray(response, cJSON_CreateString("OK"));
cJSON_AddItemToArray(response, cJSON_CreateString(event_id));
cJSON_AddItemToArray(response, cJSON_CreateBool(0)); // false = rejected
cJSON_AddItemToArray(response, cJSON_CreateString(auth_rules_msg));
char *response_str = cJSON_Print(response);
if (response_str) {
size_t response_len = strlen(response_str);
unsigned char *buf = malloc(LWS_PRE + response_len);
if (buf) {
memcpy(buf + LWS_PRE, response_str, response_len);
lws_write(wsi, buf + LWS_PRE, response_len, LWS_WRITE_TEXT);
free(buf);
}
free(response_str);
}
cJSON_Delete(response);
cJSON_Delete(json);
free(message);
return 0;
}
}
}
// Handle EVENT message
@@ -430,6 +394,7 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
size_t event_json_len = strlen(event_json_str);
int validation_result = nostr_validate_unified_request(event_json_str, event_json_len);
// Map validation result to old result format (0 = success, -1 = failure)
int result = (validation_result == NOSTR_SUCCESS) ? 0 : -1;
@@ -679,9 +644,6 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
}
} else if (strcmp(msg_type, "REQ") == 0) {
// Log the full REQ message for debugging
char debug_msg[2048];
snprintf(debug_msg, sizeof(debug_msg), "Received REQ message: %s", message);
log_info(debug_msg);
// Check NIP-42 authentication for REQ subscriptions if required
if (pss && pss->nip42_auth_required_subscriptions && !pss->authenticated) {