From 9ed9624352296fc340934cb9fddbe8ef84666738 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sat, 10 Nov 2018 16:03:42 +0000 Subject: [PATCH] added http upload test and minor tidy of handler --- service/http.go | 6 +-- service/http_test.go | 87 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/service/http.go b/service/http.go index 3f033f6a..ad90f57f 100644 --- a/service/http.go +++ b/service/http.go @@ -40,8 +40,7 @@ func SPNEGOKRB5Authenticate(f http.Handler, c *Config, l *log.Logger) http.Handl s := strings.SplitN(r.Header.Get(HTTPHeaderAuthRequest), " ", 2) if len(s) != 2 || s[0] != HTTPHeaderAuthResponseValueKey { w.Header().Set(HTTPHeaderAuthResponse, HTTPHeaderAuthResponseValueKey) - w.WriteHeader(401) - w.Write([]byte(UnauthorizedMsg)) + http.Error(w, UnauthorizedMsg, http.StatusUnauthorized) return } id, authned, err := c.Authenticate(s[1], r.RemoteAddr) @@ -76,8 +75,7 @@ func rejectSPNEGO(w http.ResponseWriter, l *log.Logger, logMsg string) { func spnegoResponseReject(w http.ResponseWriter) { w.Header().Set(HTTPHeaderAuthResponse, spnegoNegTokenRespReject) - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(UnauthorizedMsg)) + http.Error(w, UnauthorizedMsg, http.StatusUnauthorized) } func spnegoResponseAcceptCompleted(w http.ResponseWriter) { diff --git a/service/http_test.go b/service/http_test.go index 16d9e2e0..2cc4f4de 100644 --- a/service/http_test.go +++ b/service/http_test.go @@ -1,10 +1,14 @@ package service import ( + "bytes" "encoding/hex" "fmt" + "io" "io/ioutil" "log" + "math/rand" + "mime/multipart" "net/http" "net/http/httptest" "sync" @@ -236,6 +240,68 @@ func TestService_SPNEGOKRB_ReplayCache_Concurrency(t *testing.T) { wg2.Wait() } +func TestService_SPNEGOKRB_Upload(t *testing.T) { + s := httpServer() + defer s.Close() + + cl := getClient() + sname := types.PrincipalName{ + NameType: nametype.KRB_NT_PRINCIPAL, + NameString: []string{"HTTP", "host.test.gokrb5"}, + } + b, _ := hex.DecodeString(testdata.HTTP_KEYTAB) + kt, _ := keytab.Parse(b) + st := time.Now().UTC() + tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName, cl.Credentials.Realm, + sname, "TEST.GOKRB5", + types.NewKrbFlags(), + kt, + 18, + 1, + st, + st, + st.Add(time.Duration(24)*time.Hour), + st.Add(time.Duration(48)*time.Hour), + ) + if err != nil { + t.Fatalf("Error getting test ticket: %v", err) + } + + bodyBuf := &bytes.Buffer{} + bodyWriter := multipart.NewWriter(bodyBuf) + + fileWriter, err := bodyWriter.CreateFormFile("uploadfile", "testfile.bin") + if err != nil { + t.Fatalf("error writing to buffer: %v", err) + } + + data := make([]byte, 10240) + rand.Read(data) + br := bytes.NewReader(data) + _, err = io.Copy(fileWriter, br) + if err != nil { + t.Fatalf("error copying bytes: %v", err) + } + bodyWriter.Close() + + r, _ := http.NewRequest("POST", s.URL, bodyBuf) + err = client.SetSPNEGOHeader(*cl.Credentials, tkt, sessionKey, r) + if err != nil { + t.Fatalf("Error setting client SPNEGO header: %v", err) + } + r.Header.Set("Content-Type", bodyWriter.FormDataContentType()) + httpResp, err := http.DefaultClient.Do(r) + if err != nil { + t.Fatalf("Request error: %v\n", err) + } + if httpResp.StatusCode != http.StatusOK { + bodyBytes, _ := ioutil.ReadAll(httpResp.Body) + bodyString := string(bodyBytes) + httpResp.Body.Close() + t.Errorf("unexpected code from http server (%d): %s", httpResp.StatusCode, bodyString) + } +} + func httpGet(r *http.Request, wg *sync.WaitGroup) { defer wg.Done() http.DefaultClient.Do(r) @@ -252,6 +318,27 @@ func httpServer() *httptest.Server { } func testAppHandler(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodPost { + maxUploadSize := int64(11240) + if err := r.ParseMultipartForm(maxUploadSize); err != nil { + http.Error(w, fmt.Sprintf("cannot parse multipart form: %v", err), http.StatusBadRequest) + return + } + r.Body = http.MaxBytesReader(w, r.Body, maxUploadSize) + file, _, err := r.FormFile("uploadfile") + if err != nil { + http.Error(w, "INVALID_FILE", http.StatusBadRequest) + return + } + defer file.Close() + + // write out to /dev/null + _, err = io.Copy(ioutil.Discard, file) + if err != nil { + http.Error(w, "WRITE_ERR", http.StatusInternalServerError) + return + } + } w.WriteHeader(http.StatusOK) ctx := r.Context() fmt.Fprintf(w, "\nTEST.GOKRB5 Handler\nAuthenticed user: %s\nUser's realm: %s\n",