Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49ffc3d99e |
@@ -1096,12 +1096,8 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Automatically refresh configuration display after successful update
|
// Configuration updated successfully - user can manually refresh using Fetch Config button
|
||||||
setTimeout(() => {
|
log('Configuration updated successfully. Click "Fetch Config" to refresh the display.', 'INFO');
|
||||||
fetchConfiguration().catch(error => {
|
|
||||||
console.log('Auto-refresh configuration failed after update: ' + error.message);
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const errorMessage = responseData.message || responseData.error || 'Unknown error';
|
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";
|
const char* count_sql = "SELECT COUNT(*) FROM config";
|
||||||
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(count_stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] refresh_unified_cache_from_table: Config table row count at start: %d\n", row_count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(count_stmt);
|
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
|
// 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_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(count_stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] refresh_unified_cache_from_table: Config table row count at end: %d\n", row_count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(count_stmt);
|
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");
|
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
|
||||||
|
|
||||||
if (id_obj && pubkey_obj) {
|
if (id_obj && pubkey_obj) {
|
||||||
printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
|
// printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
|
||||||
printf(" Admin Public Key: %s\n", cJSON_GetStringValue(pubkey_obj));
|
// printf(" Admin Public Key: %s\n", cJSON_GetStringValue(pubkey_obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
return event;
|
return event;
|
||||||
@@ -1308,8 +1306,7 @@ int startup_existing_relay(const char* relay_pubkey) {
|
|||||||
const char* count_sql = "SELECT COUNT(*) FROM config";
|
const char* count_sql = "SELECT COUNT(*) FROM config";
|
||||||
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(count_stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] startup_existing_relay: Config table row count at start: %d\n", row_count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(count_stmt);
|
sqlite3_finalize(count_stmt);
|
||||||
}
|
}
|
||||||
@@ -1347,8 +1344,7 @@ int startup_existing_relay(const char* relay_pubkey) {
|
|||||||
const char* count_sql = "SELECT COUNT(*) FROM config";
|
const char* count_sql = "SELECT COUNT(*) FROM config";
|
||||||
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(count_stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] startup_existing_relay: Config table row count at end: %d\n", row_count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(count_stmt);
|
sqlite3_finalize(count_stmt);
|
||||||
}
|
}
|
||||||
@@ -2168,8 +2164,7 @@ int populate_default_config_values(void) {
|
|||||||
const char* count_sql = "SELECT COUNT(*) FROM config";
|
const char* count_sql = "SELECT COUNT(*) FROM config";
|
||||||
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(count_stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] populate_default_config_values: Config table row count at start: %d\n", row_count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(count_stmt);
|
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
|
// 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_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(count_stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] populate_default_config_values: Config table row count at end: %d\n", row_count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(count_stmt);
|
sqlite3_finalize(count_stmt);
|
||||||
}
|
}
|
||||||
@@ -2330,8 +2324,7 @@ int add_pubkeys_to_config_table(void) {
|
|||||||
const char* count_sql = "SELECT COUNT(*) FROM config";
|
const char* count_sql = "SELECT COUNT(*) FROM config";
|
||||||
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(count_stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] add_pubkeys_to_config_table: Config table row count at start: %d\n", row_count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(count_stmt);
|
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
|
// 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_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||||
int row_count = sqlite3_column_int(count_stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] add_pubkeys_to_config_table: Config table row count at end: %d\n", row_count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(count_stmt);
|
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);
|
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
|
// Route to appropriate handler based on kind
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case 23456: // New ephemeral auth rules management
|
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;
|
int kind = kind_obj ? (int)cJSON_GetNumberValue(kind_obj) : 0;
|
||||||
|
|
||||||
// Extract and log additional event details for debugging
|
// 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");
|
||||||
printf(" Content length: %zu\n", event_content ? strlen(event_content) : 0);
|
// if (tags_obj && cJSON_IsArray(tags_obj)) {
|
||||||
printf(" Has tags: %s\n", tags_obj ? "yes" : "no");
|
// printf(" Tags count: %d\n", cJSON_GetArraySize(tags_obj));
|
||||||
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
|
// Route all Kind 23456 events through the unified handler
|
||||||
if (kind == 23456) {
|
if (kind == 23456) {
|
||||||
@@ -2731,8 +2714,8 @@ cJSON* create_admin_response_event(const char* encrypted_content, const char* re
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" Recipient pubkey: %.16s...\n", recipient_pubkey);
|
// printf(" Recipient pubkey: %.16s...\n", recipient_pubkey);
|
||||||
printf(" Encrypted content length: %zu\n", strlen(encrypted_content));
|
// printf(" Encrypted content length: %zu\n", strlen(encrypted_content));
|
||||||
|
|
||||||
// Get relay private key for signing
|
// Get relay private key for signing
|
||||||
char* relay_privkey = get_relay_private_key();
|
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");
|
cJSON* pubkey_obj = cJSON_GetObjectItem(response_event, "pubkey");
|
||||||
|
|
||||||
if (id_obj && pubkey_obj) {
|
if (id_obj && pubkey_obj) {
|
||||||
printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
|
// printf(" Event ID: %s\n", cJSON_GetStringValue(id_obj));
|
||||||
printf(" Relay pubkey: %.16s...\n", cJSON_GetStringValue(pubkey_obj));
|
// printf(" Relay pubkey: %.16s...\n", cJSON_GetStringValue(pubkey_obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response_event;
|
return response_event;
|
||||||
@@ -2803,7 +2786,6 @@ char* encrypt_admin_response_content(const cJSON* response_data, const char* rec
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" Recipient pubkey: %.16s...\n", recipient_pubkey);
|
|
||||||
|
|
||||||
// Convert response data to JSON string
|
// Convert response data to JSON string
|
||||||
char* response_json = cJSON_Print(response_data);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" JSON length: %zu\n", strlen(response_json));
|
// printf(" JSON length: %zu\n", strlen(response_json));
|
||||||
printf(" JSON preview: %.100s%s\n", response_json,
|
// printf(" JSON preview: %.100s%s\n", response_json,
|
||||||
strlen(response_json) > 100 ? "..." : "");
|
// strlen(response_json) > 100 ? "..." : "");
|
||||||
|
|
||||||
// Get relay private key for encryption
|
// Get relay private key for encryption
|
||||||
char* relay_privkey = get_relay_private_key();
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" Encrypted content length: %zu\n", strlen(encrypted_content));
|
// printf(" Encrypted content length: %zu\n", strlen(encrypted_content));
|
||||||
printf(" Encrypted preview: %.50s...\n", encrypted_content);
|
// printf(" Encrypted preview: %.50s...\n", encrypted_content);
|
||||||
|
|
||||||
// Return encrypted content as allocated string
|
// Return encrypted content as allocated string
|
||||||
return strdup(encrypted_content);
|
return strdup(encrypted_content);
|
||||||
@@ -2883,7 +2865,6 @@ int send_admin_response_event(const cJSON* response_data, const char* recipient_
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" Recipient pubkey: %.16s...\n", recipient_pubkey);
|
|
||||||
|
|
||||||
// Step 1: Encrypt response data using NIP-44
|
// Step 1: Encrypt response data using NIP-44
|
||||||
char* encrypted_content = encrypt_admin_response_content(response_data, recipient_pubkey);
|
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");
|
cJSON* id_obj = cJSON_GetObjectItem(response_event, "id");
|
||||||
if (id_obj) {
|
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
|
// 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);
|
int broadcast_count = broadcast_event_to_subscriptions(response_event);
|
||||||
|
|
||||||
if (broadcast_count >= 0) {
|
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
|
// Clean up and return success - event creation succeeded regardless of broadcast count
|
||||||
cJSON_Delete(response_event);
|
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");
|
snprintf(error_message, error_size, "invalid: null event");
|
||||||
return -1;
|
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)
|
// Check if content is encrypted (NIP-44)
|
||||||
cJSON* content_obj = cJSON_GetObjectItem(event, "content");
|
cJSON* content_obj = cJSON_GetObjectItem(event, "content");
|
||||||
if (!content_obj || !cJSON_IsString(content_obj)) {
|
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;
|
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) {
|
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||||
const char* rule_type = (const char*)sqlite3_column_text(stmt, 0);
|
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* pattern_value_result = (const char*)sqlite3_column_text(stmt, 2);
|
||||||
const char* action = (const char*)sqlite3_column_text(stmt, 3);
|
const char* action = (const char*)sqlite3_column_text(stmt, 3);
|
||||||
|
|
||||||
printf(" %s %s:%s -> %s\n",
|
// printf(" %s %s:%s -> %s\n",
|
||||||
rule_type ? rule_type : "",
|
// rule_type ? rule_type : "",
|
||||||
pattern_type ? pattern_type : "",
|
// pattern_type ? pattern_type : "",
|
||||||
pattern_value_result ? pattern_value_result : "",
|
// pattern_value_result ? pattern_value_result : "",
|
||||||
action ? action : "allow");
|
// action ? action : "allow");
|
||||||
|
|
||||||
// Add rule to results array
|
// Add rule to results array
|
||||||
cJSON* rule_obj = cJSON_CreateObject();
|
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
|
// Send response as signed kind 23457 event
|
||||||
if (send_admin_response_event(response, admin_pubkey, wsi) == 0) {
|
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(response);
|
||||||
cJSON_Delete(results_array);
|
cJSON_Delete(results_array);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3401,7 +3403,6 @@ int handle_config_query_unified(cJSON* event, const char* query_type, char* erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
int config_count = 0;
|
int config_count = 0;
|
||||||
printf("=== Config Query Results (%s) ===\n", query_type);
|
|
||||||
|
|
||||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||||
const char* key = (const char*)sqlite3_column_text(stmt, 0);
|
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* category = (const char*)sqlite3_column_text(stmt, 3);
|
||||||
const char* description = (const char*)sqlite3_column_text(stmt, 4);
|
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
|
// Add config item to results array
|
||||||
cJSON* config_obj = cJSON_CreateObject();
|
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
|
// Send response as signed kind 23457 event
|
||||||
if (send_admin_response_event(response, admin_pubkey, wsi) == 0) {
|
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(response);
|
||||||
cJSON_Delete(results_array);
|
cJSON_Delete(results_array);
|
||||||
return 0;
|
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_AddStringToObject(response, "status", "success");
|
||||||
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
||||||
|
|
||||||
printf("Updated config: %s = %s\n", config_key, config_value);
|
|
||||||
|
|
||||||
// Get admin pubkey from event for response
|
// Get admin pubkey from event for response
|
||||||
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
|
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_AddStringToObject(response, "status", "success");
|
||||||
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
||||||
|
|
||||||
printf("Cleared %d auth rules from database\n", rule_count);
|
|
||||||
|
|
||||||
// Get admin pubkey from event for response
|
// Get admin pubkey from event for response
|
||||||
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
|
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_AddStringToObject(response, "status", "success");
|
||||||
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
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
|
// Get admin pubkey from event for response
|
||||||
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
|
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);
|
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
|
// Get admin pubkey from event for response
|
||||||
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
|
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_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
||||||
cJSON_AddItemToObject(response, "processed_configs", processed_configs);
|
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
|
// Get admin pubkey from event for response
|
||||||
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
|
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;
|
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
|
// Step 1: Verify event kind is admin type
|
||||||
cJSON *kind_json = cJSON_GetObjectItem(event, "kind");
|
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
|
// Compare with our relay pubkey
|
||||||
const char* relay_pubkey = get_config_value("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) {
|
if (relay_pubkey && strcmp(tag_value->valuestring, relay_pubkey) == 0) {
|
||||||
targets_this_relay = 1;
|
targets_this_relay = 1;
|
||||||
break;
|
break;
|
||||||
@@ -1396,7 +1388,6 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
|
|||||||
|
|
||||||
if (!targets_this_relay) {
|
if (!targets_this_relay) {
|
||||||
// Admin event for different relay - not an error, just not for us
|
// 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");
|
snprintf(error_buffer, error_buffer_size, "Admin event not targeting this relay");
|
||||||
return -1;
|
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
|
// Get admin pubkey from configuration
|
||||||
const char* admin_pubkey = get_config_value("admin_pubkey");
|
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) {
|
if (!admin_pubkey || strlen(admin_pubkey) == 0) {
|
||||||
log_warning("Unauthorized admin event attempt: no admin pubkey configured");
|
log_warning("Unauthorized admin event attempt: no admin pubkey configured");
|
||||||
snprintf(error_buffer, error_buffer_size, "Unauthorized admin event attempt: no admin 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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("DEBUG: Pubkey comparison passed");
|
|
||||||
|
|
||||||
// Step 4: Verify event signature
|
// Step 4: Verify event signature
|
||||||
if (nostr_verify_event_signature(event) != 0) {
|
if (nostr_verify_event_signature(event) != 0) {
|
||||||
log_warning("Unauthorized admin event attempt: invalid signature");
|
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");
|
snprintf(error_buffer, error_buffer_size, "Unauthorized admin event attempt: signature verification failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("DEBUG: Signature verification passed");
|
|
||||||
|
|
||||||
// All checks passed - authorized admin event
|
// All checks passed - authorized admin event
|
||||||
log_info("DEBUG: Admin event authorization successful");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1751,15 +1732,14 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG: Check config table row count before database initialization
|
// Check config table row count before database initialization
|
||||||
{
|
{
|
||||||
sqlite3* temp_db = NULL;
|
sqlite3* temp_db = NULL;
|
||||||
if (sqlite3_open(g_database_path, &temp_db) == SQLITE_OK) {
|
if (sqlite3_open(g_database_path, &temp_db) == SQLITE_OK) {
|
||||||
sqlite3_stmt* stmt;
|
sqlite3_stmt* stmt;
|
||||||
if (sqlite3_prepare_v2(temp_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(temp_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||||
int count = sqlite3_column_int(stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] Config table row count before init_database(): %d\n", count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
}
|
}
|
||||||
@@ -1780,13 +1760,12 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG: Check config table row count after database initialization
|
// Check config table row count after database initialization
|
||||||
{
|
{
|
||||||
sqlite3_stmt* stmt;
|
sqlite3_stmt* stmt;
|
||||||
if (sqlite3_prepare_v2(g_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(g_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
|
||||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||||
int count = sqlite3_column_int(stmt, 0);
|
// Row count check completed
|
||||||
printf("[DEBUG] Config table row count after init_database(): %d\n", count);
|
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
}
|
}
|
||||||
@@ -1807,7 +1786,8 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
cJSON_Delete(config_event);
|
cJSON_Delete(config_event);
|
||||||
} else {
|
} 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
|
// 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 either pubkey is missing, call add_pubkeys_to_config_table to populate both
|
||||||
if (need_to_add_pubkeys) {
|
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) {
|
if (add_pubkeys_to_config_table() != 0) {
|
||||||
log_error("Failed to add pubkeys to config table for existing relay");
|
log_error("Failed to add pubkeys to config table for existing relay");
|
||||||
cleanup_configuration_system();
|
cleanup_configuration_system();
|
||||||
@@ -1852,18 +1820,6 @@ int main(int argc, char* argv[]) {
|
|||||||
close_database();
|
close_database();
|
||||||
return 1;
|
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)
|
// 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
|
// Configuration functions from C-relay
|
||||||
extern int get_config_bool(const char* key, int default_value);
|
extern int get_config_bool(const char* key, int default_value);
|
||||||
extern int get_config_int(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)
|
// NIP-42 constants (from nostr_core_lib)
|
||||||
#define NOSTR_NIP42_AUTH_EVENT_KIND 22242
|
#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) {
|
if (event_kind == 22242) {
|
||||||
// Check NIP-42 mode using unified cache
|
// Check NIP-42 mode using unified cache
|
||||||
const char* nip42_enabled = get_config_value("nip42_auth_enabled");
|
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) {
|
if (!auth_required) {
|
||||||
} else {
|
} 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
|
// Create operation string with event kind for more specific rule matching
|
||||||
char operation_str[64];
|
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);
|
pthread_mutex_lock(&g_unified_cache.cache_lock);
|
||||||
int pow_enabled = g_unified_cache.pow_config.enabled;
|
int pow_enabled = g_unified_cache.pow_config.enabled;
|
||||||
int pow_min_difficulty = g_unified_cache.pow_config.min_pow_difficulty;
|
int pow_min_difficulty = g_unified_cache.pow_config.min_pow_difficulty;
|
||||||
int pow_validation_flags = g_unified_cache.pow_config.validation_flags;
|
int pow_validation_flags = g_unified_cache.pow_config.validation_flags;
|
||||||
pthread_mutex_unlock(&g_unified_cache.cache_lock);
|
pthread_mutex_unlock(&g_unified_cache.cache_lock);
|
||||||
|
|
||||||
if (pow_enabled && pow_min_difficulty > 0) {
|
if (pow_enabled && pow_min_difficulty > 0) {
|
||||||
nostr_pow_result_t pow_result;
|
nostr_pow_result_t pow_result;
|
||||||
int pow_validation_result = nostr_validate_pow(event, pow_min_difficulty,
|
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)
|
// Always check expiration tags if present (following NIP-40 specification)
|
||||||
|
|
||||||
cJSON *expiration_tag = NULL;
|
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");
|
cJSON* kind_obj = cJSON_GetObjectItem(event_obj, "kind");
|
||||||
int event_kind = kind_obj && cJSON_IsNumber(kind_obj) ? (int)cJSON_GetNumberValue(kind_obj) : -1;
|
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* 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_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
|
// 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);
|
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_required && !pss->authenticated && !bypass_auth) {
|
||||||
if (!pss->auth_challenge_sent) {
|
if (!pss->auth_challenge_sent) {
|
||||||
send_nip42_auth_challenge(wsi, pss);
|
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;
|
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
|
// 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);
|
size_t event_json_len = strlen(event_json_str);
|
||||||
int validation_result = nostr_validate_unified_request(event_json_str, event_json_len);
|
int validation_result = nostr_validate_unified_request(event_json_str, event_json_len);
|
||||||
|
|
||||||
|
|
||||||
// Map validation result to old result format (0 = success, -1 = failure)
|
// Map validation result to old result format (0 = success, -1 = failure)
|
||||||
int result = (validation_result == NOSTR_SUCCESS) ? 0 : -1;
|
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) {
|
} else if (strcmp(msg_type, "REQ") == 0) {
|
||||||
// Log the full REQ message for debugging
|
// 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
|
// Check NIP-42 authentication for REQ subscriptions if required
|
||||||
if (pss && pss->nip42_auth_required_subscriptions && !pss->authenticated) {
|
if (pss && pss->nip42_auth_required_subscriptions && !pss->authenticated) {
|
||||||
|
|||||||
Reference in New Issue
Block a user