summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@helsinki.at>2016-04-07 10:10:12 (GMT)
committerChristian Pointner <equinox@helsinki.at>2016-04-07 10:10:12 (GMT)
commitf48750eafed5f522a2e11622c8b20f4a7685bad6 (patch)
tree85e55ae7c07d8c5078d60b7f87f12bcbf0911d2b
parent2d57b3c62e85ecab15b8a378d86c48dfe1f44867 (diff)
parse multipart form as a stream to reject wrong authentication before the whole file got uploaded
-rw-r--r--src/rhimportd/uploadWeb.go68
1 files changed, 52 insertions, 16 deletions
diff --git a/src/rhimportd/uploadWeb.go b/src/rhimportd/uploadWeb.go
index 1c53fbc..ee86e0f 100644
--- a/src/rhimportd/uploadWeb.go
+++ b/src/rhimportd/uploadWeb.go
@@ -25,11 +25,14 @@
package main
import (
+ "bytes"
"code.helsinki.at/rhrd-go/rddb"
"code.helsinki.at/rhrd-go/rhimport"
"encoding/json"
+ "fmt"
"io"
"io/ioutil"
+ "mime/multipart"
"net/http"
"os"
"strings"
@@ -62,6 +65,50 @@ const (
webUploadMaxRequestSize = (2 << 30) - 1 // 2GB, (2 << 30) overflows int on 32-bit systems therefore we use 2GB - 1 Byte
)
+func webUploadParseForm(w http.ResponseWriter, r *http.Request) (username, password, srcfile string, src *multipart.Part, ok bool) {
+ mpr, err := r.MultipartReader()
+ if err != nil {
+ rhl.Printf("WebUploadHandler: error while parsing multi-part-form: %v", err)
+ webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
+ return
+ }
+
+ for {
+ p, err := mpr.NextPart()
+ if err != nil {
+ rhl.Printf("WebUploadHandler: error while parsing multi-part-form: %v", err)
+ webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
+ return
+ }
+ var dstfield *string
+ switch p.FormName() {
+ case "LOGIN_NAME":
+ dstfield = &username
+ case "PASSWORD":
+ dstfield = &password
+ case "FILENAME":
+ srcfile = p.FileName()
+ src = p
+ ok = true
+ return
+ default:
+ rhl.Printf("WebUploadHandler: unknown form field: '%s'", p.FormName())
+ webUploadErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("unknown field %s", p.FormName()))
+ return
+ }
+
+ var buf bytes.Buffer
+ if _, err := io.CopyN(&buf, p, 1<<10); err != nil && err != io.EOF { // 1kB should be enough
+ rhl.Printf("WebUploadHandler: error while extracting form field: %v", err)
+ webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
+ return
+ }
+ *dstfield = buf.String()
+ p.Close()
+ }
+ return
+}
+
func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport.SessionStoreChan, trusted bool, w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
http.Redirect(w, r, "/static/upload-form.html", http.StatusTemporaryRedirect)
@@ -81,14 +128,11 @@ func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport
return
}
r.Body = http.MaxBytesReader(w, r.Body, webUploadMaxRequestSize)
- if err := r.ParseMultipartForm(32 << 10); err != nil {
- rhl.Printf("WebUploadHandler: error while parsing multi-part-form: %v", err)
- webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
+
+ username, password, srcfile, src, ok := webUploadParseForm(w, r)
+ if !ok {
return
}
-
- username := r.FormValue("LOGIN_NAME")
- password := r.FormValue("PASSWORD")
if username == "" {
webUploadErrorResponse(w, http.StatusBadRequest, "missing field LOGIN_NAME")
return
@@ -108,15 +152,7 @@ func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport
return
}
- src, hdr, err := r.FormFile("FILENAME")
- if err != nil {
- rhdl.Printf("WebUploadHandler: error looking for upload file in form: %s", err)
- webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
- return
- }
- defer src.Close()
-
- rhdl.Printf("WebUploadHandler: got request from user '%s', filename='%s'", username, hdr.Filename)
+ rhdl.Printf("WebUploadHandler: got request from user '%s', filename='%s'", username, srcfile)
dstpath, err := ioutil.TempDir(conf.TempDir, "webupload-"+username+"-")
if err != nil {
@@ -125,7 +161,7 @@ func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport
return
}
- dstfile := dstpath + "/" + hdr.Filename
+ dstfile := dstpath + "/" + srcfile
dst, err := os.OpenFile(dstfile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
if err != nil {
rhl.Printf("WebUploadHandler: Unable to create file '%s': %v", dstfile, err)