diff --git a/build/bud04.o b/build/bud04.o index 1c8d1e5..a8808ef 100644 Binary files a/build/bud04.o and b/build/bud04.o differ diff --git a/build/ginxsom-fcgi b/build/ginxsom-fcgi index 43dde29..ddfa92a 100755 Binary files a/build/ginxsom-fcgi and b/build/ginxsom-fcgi differ diff --git a/build/main.o b/build/main.o index 1057a48..039ebfb 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/config/local-nginx.conf b/config/local-nginx.conf index fe082a4..c76a1f6 100644 --- a/config/local-nginx.conf +++ b/config/local-nginx.conf @@ -351,14 +351,33 @@ http { autoindex_format json; } - # Root redirect - Server info endpoint + # Root endpoint - Server info from FastCGI location = / { - return 200 '{\n "server": "ginxsom",\n "version": "v0.1.4",\n "description": "Ginxsom Blossom Server",\n "endpoints": {\n "blob_get": "GET /",\n "blob_head": "HEAD /",\n "upload": "PUT /upload",\n "upload_requirements": "HEAD /upload",\n "list": "GET /list/",\n "delete": "DELETE /",\n "mirror": "PUT /mirror",\n "report": "PUT /report",\n "health": "GET /health"\n },\n "supported_buds": [\n "BUD-01",\n "BUD-02",\n "BUD-04",\n "BUD-06",\n "BUD-08",\n "BUD-09"\n ],\n "limits": {\n "max_upload_size": 104857600,\n "supported_mime_types": [\n "image/jpeg",\n "image/png",\n "image/webp",\n "image/gif",\n "video/mp4",\n "video/webm",\n "audio/mpeg",\n "audio/ogg",\n "text/plain",\n "application/pdf"\n ]\n },\n "authentication": {\n "required_for_upload": false,\n "required_for_delete": true,\n "required_for_list": false,\n "nip42_enabled": true\n }\n}'; - add_header Content-Type application/json; - add_header Access-Control-Allow-Origin * always; - add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH" always; - add_header Access-Control-Allow-Headers "Authorization, Content-Type, Content-Length, Accept, Origin, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, Keep-Alive, X-Requested-With, If-Modified-Since, *" always; - add_header Access-Control-Max-Age 86400 always; + if ($request_method !~ ^(GET)$) { + return 405; + } + fastcgi_pass fastcgi_backend; + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param DOCUMENT_URI $document_uri; + fastcgi_param DOCUMENT_ROOT $document_root; + fastcgi_param SERVER_PROTOCOL $server_protocol; + fastcgi_param REQUEST_SCHEME $scheme; + fastcgi_param HTTPS $https if_not_empty; + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_ADDR $server_addr; + fastcgi_param SERVER_PORT $server_port; + fastcgi_param SERVER_NAME $server_name; + fastcgi_param REDIRECT_STATUS 200; + fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; + fastcgi_param HTTP_AUTHORIZATION $http_authorization; } } @@ -683,14 +702,33 @@ http { autoindex_format json; } - # Root redirect - Server info endpoint + # Root endpoint - Server info from FastCGI location = / { - return 200 '{\n "server": "ginxsom",\n "version": "v0.1.4",\n "description": "Ginxsom Blossom Server (HTTPS)",\n "endpoints": {\n "blob_get": "GET /",\n "blob_head": "HEAD /",\n "upload": "PUT /upload",\n "upload_requirements": "HEAD /upload",\n "list": "GET /list/",\n "delete": "DELETE /",\n "mirror": "PUT /mirror",\n "report": "PUT /report",\n "health": "GET /health"\n },\n "supported_buds": [\n "BUD-01",\n "BUD-02",\n "BUD-04",\n "BUD-06",\n "BUD-08",\n "BUD-09"\n ],\n "limits": {\n "max_upload_size": 104857600,\n "supported_mime_types": [\n "image/jpeg",\n "image/png",\n "image/webp",\n "image/gif",\n "video/mp4",\n "video/webm",\n "audio/mpeg",\n "audio/ogg",\n "text/plain",\n "application/pdf"\n ]\n },\n "authentication": {\n "required_for_upload": false,\n "required_for_delete": true,\n "required_for_list": false,\n "nip42_enabled": true\n }\n}'; - add_header Content-Type application/json; - add_header Access-Control-Allow-Origin * always; - add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH" always; - add_header Access-Control-Allow-Headers "Authorization, Content-Type, Content-Length, Accept, Origin, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, Keep-Alive, X-Requested-With, If-Modified-Since, *" always; - add_header Access-Control-Max-Age 86400 always; + if ($request_method !~ ^(GET)$) { + return 405; + } + fastcgi_pass fastcgi_backend; + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param DOCUMENT_URI $document_uri; + fastcgi_param DOCUMENT_ROOT $document_root; + fastcgi_param SERVER_PROTOCOL $server_protocol; + fastcgi_param REQUEST_SCHEME $scheme; + fastcgi_param HTTPS $https if_not_empty; + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_ADDR $server_addr; + fastcgi_param SERVER_PORT $server_port; + fastcgi_param SERVER_NAME $server_name; + fastcgi_param REDIRECT_STATUS 200; + fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; + fastcgi_param HTTP_AUTHORIZATION $http_authorization; } } } diff --git a/deploy_lt.sh b/deploy_lt.sh index 47912d2..e3a62b2 100755 --- a/deploy_lt.sh +++ b/deploy_lt.sh @@ -97,8 +97,10 @@ ssh $REMOTE_USER@$REMOTE_HOST << EOF echo "Binary copied successfully" EOF -# Skip nginx config update - user prefers manual control -print_status "Skipping nginx configuration update (manual control preferred)" +# NOTE: Do NOT update nginx configuration automatically +# The deployment script should only update ginxsom binaries and do nothing else with the system +# Nginx configuration should be managed manually by the system administrator +print_status "Skipping nginx configuration update (manual control required)" print_success "Files copied to remote server" diff --git a/remote.nginx.config b/remote.nginx.config index f0a0a9e..6ef282d 100644 --- a/remote.nginx.config +++ b/remote.nginx.config @@ -210,14 +210,14 @@ server { add_header Access-Control-Max-Age 86400 always; } - # Default location - Server info endpoint + # Default location - Server info from FastCGI location / { - return 200 '{\n "server": "ginxsom",\n "version": "v0.1.4",\n "description": "Ginxsom Blossom Server",\n "endpoints": {\n "blob_get": "GET /",\n "blob_head": "HEAD /",\n "upload": "PUT /upload",\n "upload_requirements": "HEAD /upload",\n "list": "GET /list/",\n "delete": "DELETE /",\n "mirror": "PUT /mirror",\n "report": "PUT /report",\n "health": "GET /health"\n },\n "supported_buds": [\n "BUD-01",\n "BUD-02",\n "BUD-04",\n "BUD-06",\n "BUD-08",\n "BUD-09"\n ],\n "limits": {\n "max_upload_size": 104857600,\n "supported_mime_types": [\n "image/jpeg",\n "image/png",\n "image/webp",\n "image/gif",\n "video/mp4",\n "video/webm",\n "audio/mpeg",\n "audio/ogg",\n "text/plain",\n "application/pdf"\n ]\n },\n "authentication": {\n "required_for_upload": false,\n "required_for_delete": true,\n "required_for_list": false,\n "nip42_enabled": true\n }\n}'; - add_header Content-Type application/json; - add_header Access-Control-Allow-Origin * always; - add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH" always; - add_header Access-Control-Allow-Headers "Authorization, Content-Type, Content-Length, Accept, Origin, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, Keep-Alive, X-Requested-With, If-Modified-Since, *" always; - add_header Access-Control-Max-Age 86400 always; + if ($request_method !~ ^(GET)$) { + return 405; + } + fastcgi_pass ginxsom_backend; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi; } } diff --git a/src/bud04.c b/src/bud04.c index 5c13d19..f176b28 100644 --- a/src/bud04.c +++ b/src/bud04.c @@ -427,8 +427,16 @@ void handle_mirror_request(void) { const char* extension = mime_to_extension(content_type_final); // Save file to storage directory using global g_storage_dir variable - char filepath[512]; - snprintf(filepath, sizeof(filepath), "%s/%s%s", g_storage_dir, sha256_hex, extension); + char filepath[4096]; + int filepath_len = snprintf(filepath, sizeof(filepath), "%s/%s%s", g_storage_dir, sha256_hex, extension); + if (filepath_len >= (int)sizeof(filepath)) { + free_mirror_download(download); + send_error_response(500, "file_error", + "File path too long", + "Internal server error during file path construction"); + log_request("PUT", "/mirror", uploader_pubkey ? "authenticated" : "anonymous", 500); + return; + } FILE* outfile = fopen(filepath, "wb"); if (!outfile) { diff --git a/src/ginxsom.h b/src/ginxsom.h index c8c79f6..78539c2 100644 --- a/src/ginxsom.h +++ b/src/ginxsom.h @@ -10,8 +10,8 @@ // Version information (auto-updated by build system) #define VERSION_MAJOR 0 #define VERSION_MINOR 1 -#define VERSION_PATCH 5 -#define VERSION "v0.1.5" +#define VERSION_PATCH 6 +#define VERSION "v0.1.6" #include #include diff --git a/src/main.c b/src/main.c index 0c63c03..e4071e9 100644 --- a/src/main.c +++ b/src/main.c @@ -1390,11 +1390,66 @@ if (!config_loaded /* && !initialize_server_config() */) { ///////////////////////////////////////////////////////////////////// // CENTRALIZED REQUEST VALIDATION SYSTEM ///////////////////////////////////////////////////////////////////// - + + // Special case: Root endpoint is public and doesn't require authentication + if (strcmp(request_method, "GET") == 0 && strcmp(request_uri, "/") == 0) { + // Handle GET / requests - Server info endpoint + printf("Status: 200 OK\r\n"); + printf("Content-Type: application/json\r\n\r\n"); + printf("{\n"); + printf(" \"server\": \"ginxsom\",\n"); + printf(" \"version\": \"%s\",\n", VERSION); + printf(" \"description\": \"Ginxsom Blossom Server\",\n"); + printf(" \"endpoints\": {\n"); + printf(" \"blob_get\": \"GET /\",\n"); + printf(" \"blob_head\": \"HEAD /\",\n"); + printf(" \"upload\": \"PUT /upload\",\n"); + printf(" \"upload_requirements\": \"HEAD /upload\",\n"); + printf(" \"list\": \"GET /list/\",\n"); + printf(" \"delete\": \"DELETE /\",\n"); + printf(" \"mirror\": \"PUT /mirror\",\n"); + printf(" \"report\": \"PUT /report\",\n"); + printf(" \"health\": \"GET /health\",\n"); + printf(" \"auth\": \"GET /auth\"\n"); + printf(" },\n"); + printf(" \"supported_buds\": [\n"); + printf(" \"BUD-01\",\n"); + printf(" \"BUD-02\",\n"); + printf(" \"BUD-04\",\n"); + printf(" \"BUD-06\",\n"); + printf(" \"BUD-08\",\n"); + printf(" \"BUD-09\"\n"); + printf(" ],\n"); + printf(" \"limits\": {\n"); + printf(" \"max_upload_size\": 104857600,\n"); + printf(" \"supported_mime_types\": [\n"); + printf(" \"image/jpeg\",\n"); + printf(" \"image/png\",\n"); + printf(" \"image/webp\",\n"); + printf(" \"image/gif\",\n"); + printf(" \"video/mp4\",\n"); + printf(" \"video/webm\",\n"); + printf(" \"audio/mpeg\",\n"); + printf(" \"audio/ogg\",\n"); + printf(" \"text/plain\",\n"); + printf(" \"application/pdf\"\n"); + printf(" ]\n"); + printf(" },\n"); + printf(" \"authentication\": {\n"); + printf(" \"required_for_upload\": false,\n"); + printf(" \"required_for_delete\": true,\n"); + printf(" \"required_for_list\": false,\n"); + printf(" \"nip42_enabled\": true\n"); + printf(" }\n"); + printf("}\n"); + log_request("GET", "/", "server_info", 200); + continue; + } + // Determine operation from request method and URI const char *operation = "unknown"; const char *resource_hash = NULL; - + if (strcmp(request_method, "HEAD") == 0 && strcmp(request_uri, "/upload") == 0) { operation = "head_upload"; } else if (strcmp(request_method, "HEAD") == 0) { @@ -1562,6 +1617,58 @@ if (!config_loaded /* && !initialize_server_config() */) { "Pubkey must be 64 hex characters"); log_request("GET", request_uri, "none", 400); } + } else if (strcmp(request_method, "GET") == 0 && + strcmp(request_uri, "/") == 0) { + // Handle GET / requests - Server info endpoint + printf("Status: 200 OK\r\n"); + printf("Content-Type: application/json\r\n\r\n"); + printf("{\n"); + printf(" \"server\": \"ginxsom\",\n"); + printf(" \"version\": \"%s\",\n", VERSION); + printf(" \"description\": \"Ginxsom Blossom Server\",\n"); + printf(" \"endpoints\": {\n"); + printf(" \"blob_get\": \"GET /\",\n"); + printf(" \"blob_head\": \"HEAD /\",\n"); + printf(" \"upload\": \"PUT /upload\",\n"); + printf(" \"upload_requirements\": \"HEAD /upload\",\n"); + printf(" \"list\": \"GET /list/\",\n"); + printf(" \"delete\": \"DELETE /\",\n"); + printf(" \"mirror\": \"PUT /mirror\",\n"); + printf(" \"report\": \"PUT /report\",\n"); + printf(" \"health\": \"GET /health\",\n"); + printf(" \"auth\": \"GET /auth\"\n"); + printf(" },\n"); + printf(" \"supported_buds\": [\n"); + printf(" \"BUD-01\",\n"); + printf(" \"BUD-02\",\n"); + printf(" \"BUD-04\",\n"); + printf(" \"BUD-06\",\n"); + printf(" \"BUD-08\",\n"); + printf(" \"BUD-09\"\n"); + printf(" ],\n"); + printf(" \"limits\": {\n"); + printf(" \"max_upload_size\": 104857600,\n"); + printf(" \"supported_mime_types\": [\n"); + printf(" \"image/jpeg\",\n"); + printf(" \"image/png\",\n"); + printf(" \"image/webp\",\n"); + printf(" \"image/gif\",\n"); + printf(" \"video/mp4\",\n"); + printf(" \"video/webm\",\n"); + printf(" \"audio/mpeg\",\n"); + printf(" \"audio/ogg\",\n"); + printf(" \"text/plain\",\n"); + printf(" \"application/pdf\"\n"); + printf(" ]\n"); + printf(" },\n"); + printf(" \"authentication\": {\n"); + printf(" \"required_for_upload\": false,\n"); + printf(" \"required_for_delete\": true,\n"); + printf(" \"required_for_list\": false,\n"); + printf(" \"nip42_enabled\": true\n"); + printf(" }\n"); + printf("}\n"); + log_request("GET", "/", "server_info", 200); } else if (strcmp(request_method, "GET") == 0 && strcmp(request_uri, "/auth") == 0) { // Handle GET /auth requests using the existing handler