From 3ed4a706f2d47bf7fc43f5cf7c4d073ca1212b3e Mon Sep 17 00:00:00 2001 From: Will McCutchen <will@mccutch.org> Date: Mon, 12 Jun 2017 08:33:00 -0700 Subject: [PATCH] WIP /digest-auth handler --- httpbin/handlers.go | 46 +++++++++++++++++++++++++++++++++++++++++++++ httpbin/helpers.go | 1 + httpbin/httpbin.go | 4 +--- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/httpbin/handlers.go b/httpbin/handlers.go index 29ed07d..64bed3f 100644 --- a/httpbin/handlers.go +++ b/httpbin/handlers.go @@ -11,6 +11,8 @@ import ( "strconv" "strings" "time" + + "github.com/mccutchen/go-httpbin/httpbin/digest" ) var acceptedMediaTypes = []string{ @@ -841,3 +843,47 @@ func doImage(w http.ResponseWriter, kind string) { func (h *HTTPBin) XML(w http.ResponseWriter, r *http.Request) { writeResponse(w, http.StatusOK, "application/xml", MustAsset("sample.xml")) } + +// DigestAuth blah +// +// /digest-auth/<qop>/<user>/<passwd> +// /digest-auth/<qop>/<user>/<passwd>/<algorithm> +func (h *HTTPBin) DigestAuth(w http.ResponseWriter, r *http.Request) { + parts := strings.Split(r.URL.Path, "/") + count := len(parts) + + if count != 5 && count != 6 { + http.Error(w, "Not Found", http.StatusNotFound) + return + } + + qop := strings.ToLower(parts[2]) + user := parts[3] + password := parts[4] + + algorithm := "MD5" + if count == 6 { + algorithm = strings.ToUpper(parts[5]) + } + + if qop != "auth" { + http.Error(w, "Invalid QOP directive", http.StatusBadRequest) + return + } + if algorithm != "MD5" && algorithm != "SHA-256" { + http.Error(w, "Invalid algorithm", http.StatusBadRequest) + return + } + + if !digest.Check(r, user, password) { + w.Header().Set("WWW-Authenticate", digest.Challenge("go-httpbin", algorithm)) + w.WriteHeader(http.StatusUnauthorized) + return + } + + resp, _ := json.Marshal(&authResponse{ + Authorized: true, + User: user, + }) + writeJSON(w, resp, http.StatusOK) +} diff --git a/httpbin/helpers.go b/httpbin/helpers.go index 682996e..e1d94fd 100644 --- a/httpbin/helpers.go +++ b/httpbin/helpers.go @@ -77,6 +77,7 @@ func parseBody(w http.ResponseWriter, r *http.Request, resp *bodyResponse, maxMe // Restrict size of request body r.Body = http.MaxBytesReader(w, r.Body, maxMemory) + defer r.Body.Close() ct := r.Header.Get("Content-Type") switch { diff --git a/httpbin/httpbin.go b/httpbin/httpbin.go index 69d38cd..1c2a462 100644 --- a/httpbin/httpbin.go +++ b/httpbin/httpbin.go @@ -114,6 +114,7 @@ func (h *HTTPBin) Handler() http.Handler { mux.HandleFunc("/basic-auth/", h.BasicAuth) mux.HandleFunc("/hidden-basic-auth/", h.HiddenBasicAuth) + mux.HandleFunc("/digest-auth/", h.DigestAuth) mux.HandleFunc("/deflate", h.Deflate) mux.HandleFunc("/gzip", h.Gzip) @@ -140,9 +141,6 @@ func (h *HTTPBin) Handler() http.Handler { mux.HandleFunc("/image/", h.Image) mux.HandleFunc("/xml", h.XML) - // Not implemented - mux.HandleFunc("/digest-auth/", notImplementedHandler) - // Make sure our ServeMux doesn't "helpfully" redirect these invalid // endpoints by adding a trailing slash. See the ServeMux docs for more // info: https://golang.org/pkg/net/http/#ServeMux -- GitLab