grim/hgkeeper

Deny invalid path

13 months ago, aklitzing
5a19892df841
Deny invalid path

If an authenticated user calls `hg init hg.host.com/dummy/../../../etc`
it will create the repository in another root directory if the process of
hgkeeper has permissions for this.
This could be an attack to the server.

Also hgkeeper admin repository can be overriden like this.
`hg init ssh://hg.host.com/dummy/../hgkeeper/keys`

Reviewed at https://reviews.imfreedom.org/r/2422/
package http
import (
"net/http"
"strings"
"time"
"go.uber.org/zap"
)
type loggerResponseWriter struct {
w http.ResponseWriter
wroteHeader bool
statusCode int
written int64
}
var _ http.ResponseWriter = (*loggerResponseWriter)(nil)
func (w *loggerResponseWriter) Header() http.Header {
return w.w.Header()
}
func (w *loggerResponseWriter) Write(data []byte) (int, error) {
if !w.wroteHeader {
w.WriteHeader(http.StatusOK)
}
n, err := w.w.Write(data)
w.written += int64(n)
return n, err
}
func (w *loggerResponseWriter) WriteHeader(statusCode int) {
if !w.wroteHeader {
w.statusCode = statusCode
w.wroteHeader = true
}
w.w.WriteHeader(w.statusCode)
}
func (w *loggerResponseWriter) StatusCode() int {
return w.statusCode
}
func (w *loggerResponseWriter) Written() int64 {
return w.written
}
func getAddr(r *http.Request) string {
// check for the X-Forwarded-For header and use if it we have it
if fwd := r.Header.Get("X-Forwarded-For"); fwd != "" {
return fwd
}
// Request.RemoteAddr is ipv4:port or [ipv6]:port so we have to trim off
// the extra bits.
addr := r.RemoteAddr
// we use LastIndex so we can parse IPv6 addresses
if idx := strings.LastIndex(addr, ":"); idx != -1 {
addr = addr[:idx]
}
// if the ipv6 was wrapped in [] we need to unwrap it
if idx := strings.Index(addr, "]"); idx != -1 {
addr = addr[1:idx]
}
return addr
}
func Logger(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rw := &loggerResponseWriter{
w: w,
}
defer func() {
// implement the NCSA Combined Log Format
// http://publib.boulder.ibm.com/tividd/td/ITWSA/ITWSA_info45/en_US/HTML/guide/c-logs.html#combined
addr := getAddr(r)
username := "-"
if user, _, ok := r.BasicAuth(); ok && username != "" {
username = user
}
referer := r.Referer()
if referer == "" {
referer = "-"
}
userAgent := r.UserAgent()
if userAgent == "" {
userAgent = "-"
}
zap.S().Infof(
"%s - %s [%s] \"%s %s %s\" %d %d %q %q\n",
addr,
username,
time.Now().Format("02/Jan/2006:15:04:05 -0700"),
r.Method,
r.URL.Path,
r.Proto,
rw.StatusCode(),
rw.Written(),
referer,
userAgent,
)
}()
h.ServeHTTP(rw, r)
})
}