v0.3.8 - safety push

This commit is contained in:
Your Name
2025-09-18 10:18:15 -04:00
parent 3210b9e752
commit 9f3b3dd773
7 changed files with 6385 additions and 1318 deletions

View File

@@ -132,24 +132,11 @@ typedef struct {
int time_tolerance_seconds;
} nip42_challenge_manager_t;
// Cached configuration structure
typedef struct {
int auth_required; // Whether authentication is required
long max_file_size; // Maximum file size in bytes
int admin_enabled; // Whether admin interface is enabled
char admin_pubkey[65]; // Admin public key
int nip42_mode; // NIP-42 authentication mode
int nip42_challenge_timeout; // NIP-42 challenge timeout in seconds
int nip42_time_tolerance; // NIP-42 time tolerance in seconds
time_t cache_expires; // When cache expires
int cache_valid; // Whether cache is valid
} auth_config_cache_t;
//=============================================================================
// GLOBAL STATE
//=============================================================================
static auth_config_cache_t g_auth_cache = {0};
// No longer using local auth cache - using unified cache from config.c
static nip42_challenge_manager_t g_challenge_manager = {0};
static int g_validator_initialized = 0;
@@ -222,15 +209,15 @@ int ginxsom_request_validator_init(const char *db_path, const char *app_name) {
return result;
}
// Initialize NIP-42 challenge manager
// Initialize NIP-42 challenge manager using unified config
memset(&g_challenge_manager, 0, sizeof(g_challenge_manager));
g_challenge_manager.timeout_seconds =
g_auth_cache.nip42_challenge_timeout > 0
? g_auth_cache.nip42_challenge_timeout
: 600;
g_challenge_manager.time_tolerance_seconds =
g_auth_cache.nip42_time_tolerance > 0 ? g_auth_cache.nip42_time_tolerance
: 300;
const char* nip42_timeout = get_config_value("nip42_challenge_timeout");
g_challenge_manager.timeout_seconds = nip42_timeout ? atoi(nip42_timeout) : 600;
const char* nip42_tolerance = get_config_value("nip42_time_tolerance");
g_challenge_manager.time_tolerance_seconds = nip42_tolerance ? atoi(nip42_tolerance) : 300;
g_challenge_manager.last_cleanup = time(NULL);
g_validator_initialized = 1;
@@ -243,12 +230,15 @@ int ginxsom_request_validator_init(const char *db_path, const char *app_name) {
* Check if authentication rules are enabled
*/
int nostr_auth_rules_enabled(void) {
// Reload config if cache expired
if (!g_auth_cache.cache_valid || time(NULL) > g_auth_cache.cache_expires) {
reload_auth_config();
// Use unified cache from config.c
const char* auth_enabled = get_config_value("auth_enabled");
if (auth_enabled && strcmp(auth_enabled, "true") == 0) {
return 1;
}
return g_auth_cache.auth_required;
// Also check legacy key
const char* auth_rules_enabled = get_config_value("auth_rules_enabled");
return (auth_rules_enabled && strcmp(auth_rules_enabled, "true") == 0) ? 1 : 0;
}
///////////////////////////////////////////////////////////////////////////////////////
@@ -306,14 +296,12 @@ int nostr_validate_unified_request(const char* json_string, size_t json_length)
int event_kind = (int)cJSON_GetNumberValue(kind);
// 5. Reload config if needed
if (!g_auth_cache.cache_valid || time(NULL) > g_auth_cache.cache_expires) {
reload_auth_config();
}
// 5. Check configuration using unified cache
int auth_required = nostr_auth_rules_enabled();
char config_msg[256];
sprintf(config_msg, "VALIDATOR_DEBUG: STEP 5 PASSED - Event kind: %d, auth_required: %d\n",
event_kind, g_auth_cache.auth_required);
event_kind, auth_required);
validator_debug_log(config_msg);
/////////////////////////////////////////////////////////////////////
@@ -352,7 +340,9 @@ int nostr_validate_unified_request(const char* json_string, size_t json_length)
if (event_kind == 22242) {
validator_debug_log("VALIDATOR_DEBUG: STEP 8 - Processing NIP-42 challenge response\n");
if (g_auth_cache.nip42_mode == 0) {
// Check NIP-42 mode using unified cache
const char* nip42_enabled = get_config_value("nip42_auth_enabled");
if (nip42_enabled && strcmp(nip42_enabled, "false") == 0) {
validator_debug_log("VALIDATOR_DEBUG: STEP 8 FAILED - NIP-42 is disabled\n");
cJSON_Delete(event);
return NOSTR_ERROR_NIP42_DISABLED;
@@ -370,7 +360,7 @@ int nostr_validate_unified_request(const char* json_string, size_t json_length)
/////////////////////////////////////////////////////////////////////
// 9. Check if authentication rules are enabled
if (!g_auth_cache.auth_required) {
if (!auth_required) {
validator_debug_log("VALIDATOR_DEBUG: STEP 9 - Authentication disabled, skipping database auth rules\n");
} else {
// 10. Check database authentication rules (only if auth enabled)
@@ -404,17 +394,23 @@ int nostr_validate_unified_request(const char* json_string, size_t json_length)
/////////////////////////////////////////////////////////////////////
// 11. NIP-13 Proof of Work validation
if (g_pow_config.enabled && g_pow_config.min_pow_difficulty > 0) {
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) {
validator_debug_log("VALIDATOR_DEBUG: STEP 11 - Validating NIP-13 Proof of Work\n");
nostr_pow_result_t pow_result;
int pow_validation_result = nostr_validate_pow(event, g_pow_config.min_pow_difficulty,
g_pow_config.validation_flags, &pow_result);
int pow_validation_result = nostr_validate_pow(event, pow_min_difficulty,
pow_validation_flags, &pow_result);
if (pow_validation_result != NOSTR_SUCCESS) {
char pow_msg[256];
sprintf(pow_msg, "VALIDATOR_DEBUG: STEP 11 FAILED - PoW validation failed (error=%d, difficulty=%d/%d)\n",
pow_validation_result, pow_result.actual_difficulty, g_pow_config.min_pow_difficulty);
pow_validation_result, pow_result.actual_difficulty, pow_min_difficulty);
validator_debug_log(pow_msg);
cJSON_Delete(event);
return pow_validation_result;
@@ -553,7 +549,6 @@ void nostr_request_validator_clear_violation(void) {
*/
void ginxsom_request_validator_cleanup(void) {
g_validator_initialized = 0;
memset(&g_auth_cache, 0, sizeof(g_auth_cache));
nostr_request_validator_clear_violation();
}
@@ -573,145 +568,22 @@ void nostr_request_result_free_file_data(nostr_request_result_t *result) {
// HELPER FUNCTIONS
//=============================================================================
/**
* Get cache timeout from environment variable or default
*/
static int get_cache_timeout(void) {
char *no_cache = getenv("GINX_NO_CACHE");
char *cache_timeout = getenv("GINX_CACHE_TIMEOUT");
if (no_cache && strcmp(no_cache, "1") == 0) {
return 0; // No caching
}
if (cache_timeout) {
int timeout = atoi(cache_timeout);
return (timeout >= 0) ? timeout : 300; // Use provided value or default
}
return 300; // Default 5 minutes
}
/**
* Force cache refresh - invalidates current cache
* Force cache refresh - use unified cache system
*/
void nostr_request_validator_force_cache_refresh(void) {
g_auth_cache.cache_valid = 0;
g_auth_cache.cache_expires = 0;
validator_debug_log("VALIDATOR: Cache forcibly invalidated\n");
// Use unified cache refresh from config.c
force_config_cache_refresh();
validator_debug_log("VALIDATOR: Cache forcibly invalidated via unified cache\n");
}
/**
* Reload authentication configuration from unified config table
* This function is no longer needed - configuration is handled by unified cache
*/
static int reload_auth_config(void) {
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
int rc;
// Clear cache
memset(&g_auth_cache, 0, sizeof(g_auth_cache));
// Open database using global database path
if (strlen(g_database_path) == 0) {
validator_debug_log("VALIDATOR: No database path available\n");
// Use defaults
g_auth_cache.auth_required = 0;
g_auth_cache.max_file_size = 104857600; // 100MB
g_auth_cache.admin_enabled = 0;
g_auth_cache.nip42_mode = 1; // Optional
int cache_timeout = get_cache_timeout();
g_auth_cache.cache_expires = time(NULL) + cache_timeout;
g_auth_cache.cache_valid = 1;
return NOSTR_SUCCESS;
}
rc = sqlite3_open_v2(g_database_path, &db, SQLITE_OPEN_READONLY, NULL);
if (rc != SQLITE_OK) {
validator_debug_log("VALIDATOR: Could not open database\n");
// Use defaults
g_auth_cache.auth_required = 0;
g_auth_cache.max_file_size = 104857600; // 100MB
g_auth_cache.admin_enabled = 0;
g_auth_cache.nip42_mode = 1; // Optional
int cache_timeout = get_cache_timeout();
g_auth_cache.cache_expires = time(NULL) + cache_timeout;
g_auth_cache.cache_valid = 1;
return NOSTR_SUCCESS;
}
// Load configuration values from unified config table
const char *config_sql =
"SELECT key, value FROM config WHERE key IN ('require_auth', "
"'auth_rules_enabled', 'max_file_size', 'admin_enabled', 'admin_pubkey', "
"'nip42_require_auth', 'nip42_challenge_timeout', "
"'nip42_time_tolerance')";
rc = sqlite3_prepare_v2(db, config_sql, -1, &stmt, NULL);
if (rc == SQLITE_OK) {
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char *key = (const char *)sqlite3_column_text(stmt, 0);
const char *value = (const char *)sqlite3_column_text(stmt, 1);
if (!key || !value)
continue;
if (strcmp(key, "require_auth") == 0) {
g_auth_cache.auth_required = (strcmp(value, "true") == 0) ? 1 : 0;
} else if (strcmp(key, "auth_rules_enabled") == 0) {
// Override auth_required with auth_rules_enabled if present (higher
// priority)
g_auth_cache.auth_required = (strcmp(value, "true") == 0) ? 1 : 0;
} else if (strcmp(key, "max_file_size") == 0) {
g_auth_cache.max_file_size = atol(value);
} else if (strcmp(key, "admin_enabled") == 0) {
g_auth_cache.admin_enabled = (strcmp(value, "true") == 0) ? 1 : 0;
} else if (strcmp(key, "admin_pubkey") == 0) {
strncpy(g_auth_cache.admin_pubkey, value,
sizeof(g_auth_cache.admin_pubkey) - 1);
} else if (strcmp(key, "nip42_require_auth") == 0) {
if (strcmp(value, "false") == 0) {
g_auth_cache.nip42_mode = 0; // Disabled
} else if (strcmp(value, "required") == 0) {
g_auth_cache.nip42_mode = 2; // Required
} else if (strcmp(value, "true") == 0) {
g_auth_cache.nip42_mode = 1; // Optional/Enabled
} else {
g_auth_cache.nip42_mode = 1; // Default to Optional/Enabled
}
} else if (strcmp(key, "nip42_challenge_timeout") == 0) {
g_auth_cache.nip42_challenge_timeout = atoi(value);
} else if (strcmp(key, "nip42_time_tolerance") == 0) {
g_auth_cache.nip42_time_tolerance = atoi(value);
}
}
sqlite3_finalize(stmt);
}
sqlite3_close(db);
// Set cache expiration with environment variable support
int cache_timeout = get_cache_timeout();
g_auth_cache.cache_expires = time(NULL) + cache_timeout;
g_auth_cache.cache_valid = 1;
// Set defaults for missing values
if (g_auth_cache.max_file_size == 0) {
g_auth_cache.max_file_size = 104857600; // 100MB
}
// Debug logging
fprintf(stderr,
"VALIDATOR: Configuration loaded from unified config table - "
"auth_required: %d, max_file_size: %ld, nip42_mode: %d, "
"cache_timeout: %d\n",
g_auth_cache.auth_required, g_auth_cache.max_file_size,
g_auth_cache.nip42_mode, cache_timeout);
fprintf(stderr,
"VALIDATOR: NIP-42 mode details - nip42_mode=%d (0=disabled, "
"1=optional/enabled, 2=required)\n",
g_auth_cache.nip42_mode);
// Configuration is now handled by the unified cache in config.c
validator_debug_log("VALIDATOR: Using unified cache system for configuration\n");
return NOSTR_SUCCESS;
}