diff options
| author | Russ Cox <rsc@golang.org> | 2009-04-07 00:40:07 -0700 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2009-04-07 00:40:07 -0700 |
| commit | 16b38b554fb4dae82923cb81a5c6a76ee2959d2f (patch) | |
| tree | d99b97d1215df17d8a4f968eb03664bc6512dee7 /src/lib/http | |
| parent | 640f3f25dcd238bfc6b4fd99b1808071cfa12888 (diff) | |
| download | go-16b38b554fb4dae82923cb81a5c6a76ee2959d2f.tar.xz | |
add path.Clean and other utilities.
use path.Clean in web server to sanitize URLs.
http://triv/go/../../../etc/passwd
no longer serves the password file.
it redirects to
http://triv/etc/passwd
which then gets a 404.
R=r
DELTA=288 (286 added, 0 deleted, 2 changed)
OCL=27142
CL=27152
Diffstat (limited to 'src/lib/http')
| -rw-r--r-- | src/lib/http/server.go | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/src/lib/http/server.go b/src/lib/http/server.go index df2ce3698a..fa29e9bc1c 100644 --- a/src/lib/http/server.go +++ b/src/lib/http/server.go @@ -19,6 +19,7 @@ import ( "log"; "net"; "os"; + "path"; "strconv"; ) @@ -209,7 +210,7 @@ func (c *Conn) serve() { } // HTTP cannot have multiple simultaneous active requests. // Until the server replies to this request, it can't read another, - // so we might as well run the handler in this thread. + // so we might as well run the handler in this goroutine. c.handler.ServeHTTP(c, req); if c.hijacked { return; @@ -300,6 +301,10 @@ func RedirectHandler(url string) Handler { // so that a handler might register for the two patterns // "/codesearch" and "codesearch.google.com/" // without taking over requests for http://www.google.com/. +// +// ServeMux also takes care of sanitizing the URL request path, +// redirecting any request containing . or .. elements to an +// equivalent .- and ..-free URL. type ServeMux struct { m map[string] Handler } @@ -325,9 +330,33 @@ func pathMatch(pattern, path string) bool { return len(path) >= n && path[0:n] == pattern; } +// Return the canonical path for p, eliminating . and .. elements. +func cleanPath(p string) string { + if p == "" { + return "/"; + } + if p[0] != '/' { + p = "/" + p; + } + np := path.Clean(p); + // path.Clean removes trailing slash except for root; + // put the trailing slash back if necessary. + if p[len(p)-1] == '/' && np != "/" { + np += "/"; + } + return np; +} + // ServeHTTP dispatches the request to the handler whose // pattern most closely matches the request URL. func (mux *ServeMux) ServeHTTP(c *Conn, req *Request) { + // Clean path to canonical form and redirect. + if p := cleanPath(req.Url.Path); p != req.Url.Path { + c.SetHeader("Location", p); + c.WriteHeader(StatusMovedPermanently); + return; + } + // Most-specific (longest) pattern wins. var h Handler; var n = 0; |
