Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49ffc3d99e |
@@ -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';
|
||||
|
||||
128
src/config.c
128
src/config.c
@@ -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
56
src/main.c
56
src/main.c
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user