Add maximum upload size saftey and guards

This commit is contained in:
James Mills 2020-03-29 17:41:10 +10:00
parent b8aee1d2b5
commit a22a2ae031
No known key found for this signature in database
GPG key ID: AC4C014F1440EBD6
4 changed files with 55 additions and 12 deletions

View file

@ -210,8 +210,7 @@ func (a *App) uploadHandler(w http.ResponseWriter, r *http.Request) {
ctx := &struct{}{} ctx := &struct{}{}
a.render("upload", w, ctx) a.render("upload", w, ctx)
} else if r.Method == "POST" { } else if r.Method == "POST" {
// TODO: Move to a constant r.ParseMultipartForm(a.Config.Server.MaxUploadSize)
r.ParseMultipartForm((10 << 20) * 10) // 100MB
file, handler, err := r.FormFile("video_file") file, handler, err := r.FormFile("video_file")
if err != nil { if err != nil {
@ -414,6 +413,37 @@ func (a *App) importHandler(w http.ResponseWriter, r *http.Request) {
} }
defer os.Remove(uf.Name()) defer os.Remove(uf.Name())
log.WithField("video_url", videoInfo.VideoURL).Info("requesting video size")
res, err := http.Head(videoInfo.VideoURL)
if err != nil {
err := fmt.Errorf("error getting size of video %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
contentLength := utils.SafeParseInt64(res.Header.Get("Content-Length"), -1)
if contentLength == -1 {
err := fmt.Errorf("error calculating size of video")
log.WithField("contentLength", contentLength).Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if contentLength > a.Config.Server.MaxUploadSize {
err := fmt.Errorf(
"imported video would exceed maximum upload size of %s",
humanize.Bytes(uint64(a.Config.Server.MaxUploadSize)),
)
log.
WithField("contentLength", contentLength).
WithField("max_upload_size", a.Config.Server.MaxUploadSize).
Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
log.WithField("contentLength", contentLength).Info("downloading video")
if err := utils.Download(videoInfo.VideoURL, uf.Name()); err != nil { if err := utils.Download(videoInfo.VideoURL, uf.Name()); err != nil {
err := fmt.Errorf("error downloading video %s: %w", url, err) err := fmt.Errorf("error downloading video %s: %w", url, err)
log.Error(err) log.Error(err)

View file

@ -26,6 +26,7 @@ type ServerConfig struct {
Port int `json:"port"` Port int `json:"port"`
StorePath string `json:"store_path"` StorePath string `json:"store_path"`
UploadPath string `json:"upload_path"` UploadPath string `json:"upload_path"`
MaxUploadSize int64 `json:"max_upload_size"`
} }
// ThumbnailerConfig settings for Transcoder // ThumbnailerConfig settings for Transcoder
@ -61,15 +62,16 @@ func DefaultConfig() *Config {
}, },
}, },
Server: &ServerConfig{ Server: &ServerConfig{
Host: "127.0.0.1", Host: "0.0.0.0",
Port: 0, Port: 8000,
UploadPath: "uploads", UploadPath: "uploads",
MaxUploadSize: 104857600,
}, },
Thumbnailer: &ThumbnailerConfig{ Thumbnailer: &ThumbnailerConfig{
Timeout: 30, Timeout: 60,
}, },
Transcoder: &TranscoderConfig{ Transcoder: &TranscoderConfig{
Timeout: 60, Timeout: 300,
}, },
Feed: &FeedConfig{ Feed: &FeedConfig{
ExternalURL: "http://localhost", ExternalURL: "http://localhost",

View file

@ -9,7 +9,8 @@
"host": "0.0.0.0", "host": "0.0.0.0",
"port": 8000, "port": 8000,
"store_path": "tube.db", "store_path": "tube.db",
"upload_path": "uploads" "upload_path": "uploads",
"max_upload_size": 104857600
}, },
"thumbnailer": { "thumbnailer": {
"timeout": 60 "timeout": 60

View file

@ -7,9 +7,19 @@ import (
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
"strconv"
"time" "time"
) )
// SafeParseInt64 ...
func SafeParseInt64(s string, d int64) int64 {
n, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return d
}
return n
}
func Download(url, filename string) error { func Download(url, filename string) error {
res, err := http.Get(url) res, err := http.Get(url)
if err != nil { if err != nil {