diff --git a/cmd/server/chunked_upload_handler.go b/cmd/server/chunked_upload_handler.go index 81fdd41..9f0389b 100644 --- a/cmd/server/chunked_upload_handler.go +++ b/cmd/server/chunked_upload_handler.go @@ -71,6 +71,23 @@ func handleChunkedUpload(w http.ResponseWriter, r *http.Request) { return } + // Validate file size against max_upload_size if configured + if conf.Server.MaxUploadSize != "" { + maxSizeBytes, err := parseSize(conf.Server.MaxUploadSize) + if err != nil { + log.Errorf("Invalid max_upload_size configuration: %v", err) + http.Error(w, "Server configuration error", http.StatusInternalServerError) + uploadErrorsTotal.Inc() + return + } + if totalSize > maxSizeBytes { + http.Error(w, fmt.Sprintf("File size %s exceeds maximum allowed size %s", + formatBytes(totalSize), conf.Server.MaxUploadSize), http.StatusRequestEntityTooLarge) + uploadErrorsTotal.Inc() + return + } + } + // Authentication (reuse existing logic) if conf.Security.EnableJWT { _, err := validateJWTFromRequest(r, conf.Security.JWTSecret) diff --git a/cmd/server/main.go b/cmd/server/main.go index 07f1be5..f49ef8e 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -1407,6 +1407,23 @@ func handleUpload(w http.ResponseWriter, r *http.Request) { } defer file.Close() + // Validate file size against max_upload_size if configured + if conf.Server.MaxUploadSize != "" { + maxSizeBytes, err := parseSize(conf.Server.MaxUploadSize) + if err != nil { + log.Errorf("Invalid max_upload_size configuration: %v", err) + http.Error(w, "Server configuration error", http.StatusInternalServerError) + uploadErrorsTotal.Inc() + return + } + if header.Size > maxSizeBytes { + http.Error(w, fmt.Sprintf("File size %s exceeds maximum allowed size %s", + formatBytes(header.Size), conf.Server.MaxUploadSize), http.StatusRequestEntityTooLarge) + uploadErrorsTotal.Inc() + return + } + } + // Validate file extension if configured if len(conf.Uploads.AllowedExtensions) > 0 { ext := strings.ToLower(filepath.Ext(header.Filename)) @@ -1644,6 +1661,23 @@ func handleV3Upload(w http.ResponseWriter, r *http.Request) { } } + // Validate file size against max_upload_size if configured + if conf.Server.MaxUploadSize != "" { + maxSizeBytes, err := parseSize(conf.Server.MaxUploadSize) + if err != nil { + log.Errorf("Invalid max_upload_size configuration: %v", err) + http.Error(w, "Server configuration error", http.StatusInternalServerError) + uploadErrorsTotal.Inc() + return + } + if r.ContentLength > maxSizeBytes { + http.Error(w, fmt.Sprintf("File size %s exceeds maximum allowed size %s", + formatBytes(r.ContentLength), conf.Server.MaxUploadSize), http.StatusRequestEntityTooLarge) + uploadErrorsTotal.Inc() + return + } + } + // Generate filename based on configuration var filename string switch conf.Server.FileNaming { @@ -1767,6 +1801,23 @@ func handleLegacyUpload(w http.ResponseWriter, r *http.Request) { } } + // Validate file size against max_upload_size if configured + if conf.Server.MaxUploadSize != "" { + maxSizeBytes, err := parseSize(conf.Server.MaxUploadSize) + if err != nil { + log.Errorf("Invalid max_upload_size configuration: %v", err) + http.Error(w, "Server configuration error", http.StatusInternalServerError) + uploadErrorsTotal.Inc() + return + } + if r.ContentLength > maxSizeBytes { + http.Error(w, fmt.Sprintf("File size %s exceeds maximum allowed size %s", + formatBytes(r.ContentLength), conf.Server.MaxUploadSize), http.StatusRequestEntityTooLarge) + uploadErrorsTotal.Inc() + return + } + } + // Create full file path storagePath := conf.Server.StoragePath if conf.ISO.Enabled { diff --git a/config-clean.toml b/config-clean.toml new file mode 100644 index 0000000..88861d8 --- /dev/null +++ b/config-clean.toml @@ -0,0 +1,89 @@ +[server] +listen_address = ":8080" +storage_path = "/opt/hmac-file-server/data/uploads" +metrics_enabled = true +metrics_path = "/metrics" +pid_file = "/var/run/hmac-file-server.pid" +max_upload_size = "10GB" +max_header_bytes = 1048576 +cleanup_interval = "24h" +max_file_age = "720h" +pre_cache = true +pre_cache_workers = 4 +pre_cache_interval = "1h" +global_extensions = [".txt", ".dat", ".iso"] +deduplication_enabled = true +min_free_bytes = "1GB" +file_naming = "original" +force_protocol = "" +enable_dynamic_workers = true +worker_scale_up_thresh = 50 +worker_scale_down_thresh = 10 + +[uploads] +allowedextensions = [".zip", ".rar", ".7z", ".tar.gz", ".tgz", ".gpg", ".enc", ".pgp", ".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp", ".wav", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".mpeg", ".mpg", ".m4v", ".3gp", ".3g2", ".mp3", ".ogg"] +chunkeduploadsenabled = true +chunksize = "32MB" +resumableuploadsenabled = true +maxresumableage = "48h" + +[downloads] +resumabledownloadsenabled = true +chunkeddownloadsenabled = true +chunksize = "32MB" +allowedextensions = [".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp", ".wav", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".mpeg", ".mpg", ".m4v", ".3gp", ".3g2", ".mp3", ".ogg"] + +[security] +secret = "f6g4ldPvQM7O2UTFeBEUUj33VrXypDAcsDt0yqKrLiOr5oQW" +enablejwt = false +jwtsecret = "f6g4ldPvQM7O2UTFeBEUUj33VrXypDAcsDt0yqKrLiOr5oQW" +jwtalgorithm = "HS256" +jwtexpiration = "24h" + +[logging] +level = "debug" +file = "/var/log/hmac-file-server/hmac-file-server.log" +max_size = 100 +max_backups = 7 +max_age = 30 +compress = true + +[deduplication] +enabled = true +directory = "/opt/hmac-file-server/data/duplicates" + +[iso] +enabled = false +size = "1GB" +mountpoint = "/mnt/iso" +charset = "utf-8" +containerfile = "/mnt/iso/container.iso" + +[timeouts] +readtimeout = "3600s" +writetimeout = "3600s" +idletimeout = "3600s" + +[versioning] +enableversioning = false +maxversions = 1 + +[clamav] +clamavenabled = false +clamavsocket = "/var/run/clamav/clamd.ctl" +numscanworkers = 2 +scanfileextensions = [".exe", ".dll", ".bin", ".com", ".bat", ".sh", ".php", ".js"] + +[redis] +redisenabled = false +redisdbindex = 0 +redisaddr = "localhost:6379" +redispassword = "" +redishealthcheckinterval = "120s" + +[workers] +numworkers = 4 +uploadqueuesize = 5000 + +[file] +filerevision = 1 diff --git a/dockerenv/config/config.toml b/dockerenv/config/config.toml index f998765..7b1aa0e 100644 --- a/dockerenv/config/config.toml +++ b/dockerenv/config/config.toml @@ -1,75 +1,81 @@ [server] -listenport = "8080" -unixsocket = false -storagepath = "/opt/hmac-file-server/data/uploads" -metricsenabled = true -metricsport = "9090" -deduplicationenabled = true -minfreebytes = "5GB" -filettl = "2y" -filettlenabled = false -autoadjustworkers = true -networkevents = false -pidfilepath = "./hmac-file-server.pid" -precaching = false +listen_address = ":8080" +storage_path = "/srv/hmac-file-server/uploads" +metrics_enabled = true +metrics_path = "/metrics" +pid_file = "/var/run/hmac-file-server.pid" +max_upload_size = "10GB" # Supports B, KB, MB, GB, TB +max_header_bytes = 1048576 # 1MB +cleanup_interval = "24h" +max_file_age = "720h" # 30 days +pre_cache = true +pre_cache_workers = 4 +pre_cache_interval = "1h" +global_extensions = [".txt", ".dat", ".iso"] # If set, overrides upload/download extensions +deduplication_enabled = true +min_free_bytes = "1GB" # Minimum free space required for uploads +file_naming = "original" # Options: "original", "HMAC" +force_protocol = "" # Options: "http", "https" - if set, redirects to this protocol +enable_dynamic_workers = true # Enable dynamic worker scaling +worker_scale_up_thresh = 50 # Queue length to scale up workers +worker_scale_down_thresh = 10 # Queue length to scale down workers -[deduplication] -enabled = true -directory = "/opt/hmac-file-server/data/duplicates" +[uploads] +allowed_extensions = [".zip", ".rar", ".7z", ".tar.gz", ".tgz", ".gpg", ".enc", ".pgp"] +chunked_uploads_enabled = true +chunk_size = "10MB" +resumable_uploads_enabled = true +max_resumable_age = "48h" + +[downloads] +resumable_downloads_enabled = true +chunked_downloads_enabled = true +chunk_size = "8192" +allowed_extensions = [".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp"] + +[security] +secret = "f6g4ldPvQM7O2UTFeBEUUj33VrXypDAcsDt0yqKrLiOr5oQW" +enablejwt = false +jwtsecret = "f6g4ldPvQM7O2UTFeBEUUj33VrXypDAcsDt0yqKrLiOr5oQW" +jwtalgorithm = "HS256" +jwtexpiration = "24h" [logging] -level = "debug" -file = "./hmac-file-server.log" +level = "info" +file = "/var/log/hmac-file-server.log" max_size = 100 max_backups = 7 max_age = 30 compress = true +[deduplication] +enabled = true +directory = "./deduplication" + [iso] -enabled = false -size = "1TB" -mountpoint = "/mnt/nfs_vol01/hmac-file-server/iso/" +enabled = true +size = "1GB" +mountpoint = "/mnt/iso" charset = "utf-8" +containerfile = "/mnt/iso/container.iso" [timeouts] -readtimeout = "3600s" -writetimeout = "3600s" -idletimeout = "3600s" - -[security] -secret = "CHANGE-THIS-TO-YOUR-SECRET-KEY-MINIMUM-32-CHARACTERS" +readtimeout = "4800s" +writetimeout = "4800s" +idletimeout = "4800s" [versioning] enableversioning = false maxversions = 1 -[uploads] -resumableuploadsenabled = false -chunkeduploadsenabled = true -chunksize = "32MB" -allowedextensions = [ - ".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp", - ".wav", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".mpeg", ".mpg", - ".m4v", ".3gp", ".3g2", ".mp3", ".ogg" -] - -[downloads] -chunkeddownloadsenabled = false -chunksize = "32MB" -allowedextensions = [ - ".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp", - ".wav", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".mpeg", ".mpg", - ".m4v", ".3gp", ".3g2", ".mp3", ".ogg" -] - [clamav] -clamavenabled = false +clamavenabled = true clamavsocket = "/var/run/clamav/clamd.ctl" -numscanworkers = 4 -scanfileextensions = [".exe", ".dll", ".bin", ".com", ".bat", ".sh", ".php", ".js"] +numscanworkers = 2 +scanfileextensions = [".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".svg", ".webp"] [redis] -redisenabled = false +redisenabled = true redisdbindex = 0 redisaddr = "localhost:6379" redispassword = "" @@ -77,7 +83,10 @@ redishealthcheckinterval = "120s" [workers] numworkers = 4 -uploadqueuesize = 5000 +uploadqueuesize = 50 [file] -filerevision = 1 +# Add file-specific configurations here + +[build] +version = "3.2" diff --git a/hmac-file-server.pid b/hmac-file-server.pid index a48cb04..3d47cf2 100644 --- a/hmac-file-server.pid +++ b/hmac-file-server.pid @@ -1 +1 @@ -619742 \ No newline at end of file +2896344 \ No newline at end of file diff --git a/test_upload.txt b/test_upload.txt index a2e74b5..dc4023c 100644 --- a/test_upload.txt +++ b/test_upload.txt @@ -1 +1 @@ -Hello, HMAC File Server! Do 17. Jul 18:59:11 CEST 2025 +Hello, HMAC File Server! Thu Jul 17 05:40:07 PM UTC 2025