]> Sergey Matveev's repositories - godlighty.git/blobdiff - handler.go
Authentication and authorization
[godlighty.git] / handler.go
index 3aacc29f6b74d502616308481e159445bdafc95b..df16c38d5e11bf05092f7c6b1bcaf606be8a87c7 100644 (file)
@@ -20,6 +20,7 @@ package godlighty
 import (
        "bytes"
        "compress/gzip"
+       "errors"
        "fmt"
        "io/ioutil"
        "log"
@@ -42,8 +43,6 @@ const (
 )
 
 var (
-       CompressibleContentTypes = make(map[string]struct{})
-
        gzPool = sync.Pool{
                New: func() interface{} { return gzip.NewWriter(ioutil.Discard) },
        }
@@ -82,19 +81,49 @@ func (h Handler) Handle(
                return
        }
 
-       for _, hook := range cfg.Hooks {
-               if done := hook(w, r); done {
-                       return
-               }
+       var username string
+       var err error
+       if cfg.Auth != nil {
+               username, err = performAuth(w, r, cfg.Auth)
+       }
+       if username != "" {
+               username = "user:" + username + " "
        }
-
        printErr := func(code int, err error) {
-               fmt.Printf("%s %s \"%s %s %s\" %d \"%s\" \"%s\"\n",
+               fmt.Printf("%s %s \"%s %s %s\" %d \"%s\" %s\"%s\"\n",
                        r.RemoteAddr, host, r.Method, r.URL.Path, r.Proto,
                        code, err.Error(),
-                       r.Header.Get("User-Agent"),
+                       username, r.Header.Get("User-Agent"),
                )
        }
+       switch err {
+       case nil:
+               break
+       case Unauthorized:
+               printErr(http.StatusUnauthorized, err)
+               return
+       default:
+               printErr(http.StatusInternalServerError, err)
+               http.Error(w, "internal error", http.StatusInternalServerError)
+               return
+       }
+
+       if cfg.TLS != nil && len(cfg.TLS.ClientCAs) > 0 {
+               if r.TLS == nil {
+                       err = errors.New("TLS client authentication required")
+                       printErr(http.StatusForbidden, err)
+                       http.Error(w, err.Error(), http.StatusForbidden)
+                       return
+               } else {
+                       username += r.TLS.PeerCertificates[0].Subject.String() + " "
+               }
+       }
+
+       for _, hook := range cfg.Hooks {
+               if done := hook(w, r); done {
+                       return
+               }
+       }
 
        if cfg.Root == "" {
                notFound()
@@ -110,19 +139,19 @@ func (h Handler) Handle(
                }
                wc := &CountResponseWriter{ResponseWriter: w}
                dav.ServeHTTP(wc, r)
-               fmt.Printf("%s %s \"WebDAV %s\" %d %d \"%s\"\n",
+               fmt.Printf("%s %s \"WebDAV %s\" %d %d %s\"%s\"\n",
                        r.RemoteAddr, host, r.URL.Path,
                        wc.Status, wc.Size,
-                       r.Header.Get("User-Agent"),
+                       username, r.Header.Get("User-Agent"),
                )
                return
        }
 
        if !(r.Method == "" || r.Method == http.MethodGet) {
-               fmt.Printf("%s %s \"%s %s %s\" %d \"%s\"\n",
+               fmt.Printf("%s %s \"%s %s %s\" %d %s\"%s\"\n",
                        r.RemoteAddr, host, r.Method, r.URL.Path, r.Proto,
                        http.StatusMethodNotAllowed,
-                       r.Header.Get("User-Agent"),
+                       username, r.Header.Get("User-Agent"),
                )
                http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
                return
@@ -256,18 +285,18 @@ IndexLookup:
                wr := wc.(*gzipResponseWriter)
                w.WriteHeader(wr.status)
                w.Write(bufCompressed.Bytes())
-               fmt.Printf("%s %s \"%s %s %s\" %d %d \"%s\"\n",
+               fmt.Printf("%s %s \"%s %s %s\" %d %d %s\"%s\"\n",
                        r.RemoteAddr, host, r.Method, r.URL.Path, r.Proto,
                        wr.status, size,
-                       r.Header.Get("User-Agent"),
+                       username, r.Header.Get("User-Agent"),
                )
                return
        }
        wr := wc.(*CountResponseWriter)
-       fmt.Printf("%s %s \"%s %s %s\" %d %d \"%s\"\n",
+       fmt.Printf("%s %s \"%s %s %s\" %d %d %s\"%s\"\n",
                r.RemoteAddr, host, r.Method, r.URL.Path, r.Proto,
                wr.Status, wr.Size,
-               r.Header.Get("User-Agent"),
+               username, r.Header.Get("User-Agent"),
        )
 }