Skip to content

Commit

Permalink
Merge pull request ipfs/kubo#1988 from ipfs/ipfs-prefix-hardening
Browse files Browse the repository at this point in the history
gateway: harden path prefix

This commit was moved from ipfs/kubo@c6e6bb0
  • Loading branch information
whyrusleeping committed Apr 4, 2016
2 parents 14d32ab + d2ab652 commit 4bda147
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 16 deletions.
14 changes: 8 additions & 6 deletions gateway/core/corehttp/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ type Gateway struct {
}

type GatewayConfig struct {
Headers map[string][]string
BlockList *BlockList
Writable bool
Headers map[string][]string
BlockList *BlockList
Writable bool
PathPrefixes []string
}

func NewGateway(conf GatewayConfig) *Gateway {
Expand Down Expand Up @@ -48,10 +49,11 @@ func (g *Gateway) ServeOption() ServeOption {
}
}

func GatewayOption(writable bool) ServeOption {
func GatewayOption(writable bool, prefixes []string) ServeOption {
g := NewGateway(GatewayConfig{
Writable: writable,
BlockList: &BlockList{},
Writable: writable,
BlockList: &BlockList{},
PathPrefixes: prefixes,
})
return g.ServeOption()
}
Expand Down
9 changes: 7 additions & 2 deletions gateway/core/corehttp/gateway_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,13 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
// It will be prepended to links in directory listings and the index.html redirect.
prefix := ""
if prefixHdr := r.Header["X-Ipfs-Gateway-Prefix"]; len(prefixHdr) > 0 {
log.Debugf("X-Ipfs-Gateway-Prefix: %s", prefixHdr[0])
prefix = prefixHdr[0]
prfx := prefixHdr[0]
for _, p := range i.config.PathPrefixes {
if prfx == p || strings.HasPrefix(prfx, p+"/") {
prefix = prfx
break
}
}
}

// IPNSHostnameOption might have constructed an IPNS path using the Host header.
Expand Down
60 changes: 52 additions & 8 deletions gateway/core/corehttp/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func newTestServerAndNode(t *testing.T, ns mockNamesys) (*httptest.Server, *core
ts.Listener,
VersionOption(),
IPNSHostnameOption(),
GatewayOption(false),
GatewayOption(false, []string{"/good-prefix"}),
)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -227,7 +227,7 @@ func TestIPNSHostnameRedirect(t *testing.T) {
t.Fatal(err)
}
req.Host = "example.net"
req.Header.Set("X-Ipfs-Gateway-Prefix", "/prefix")
req.Header.Set("X-Ipfs-Gateway-Prefix", "/good-prefix")

res, err = doWithoutRedirect(req)
if err != nil {
Expand All @@ -241,8 +241,8 @@ func TestIPNSHostnameRedirect(t *testing.T) {
hdr = res.Header["Location"]
if len(hdr) < 1 {
t.Errorf("location header not present")
} else if hdr[0] != "/prefix/foo/" {
t.Errorf("location header is %v, expected /prefix/foo/", hdr[0])
} else if hdr[0] != "/good-prefix/foo/" {
t.Errorf("location header is %v, expected /good-prefix/foo/", hdr[0])
}
}

Expand Down Expand Up @@ -387,7 +387,7 @@ func TestIPNSHostnameBacklinks(t *testing.T) {
t.Fatal(err)
}
req.Host = "example.net"
req.Header.Set("X-Ipfs-Gateway-Prefix", "/prefix")
req.Header.Set("X-Ipfs-Gateway-Prefix", "/good-prefix")

res, err = doWithoutRedirect(req)
if err != nil {
Expand All @@ -402,13 +402,57 @@ func TestIPNSHostnameBacklinks(t *testing.T) {
s = string(body)
t.Logf("body: %s\n", string(body))

if !strings.Contains(s, "Index of /prefix") {
if !strings.Contains(s, "Index of /good-prefix") {
t.Fatalf("expected a path in directory listing")
}
if !strings.Contains(s, "<a href=\"/prefix/\">") {
if !strings.Contains(s, "<a href=\"/good-prefix/\">") {
t.Fatalf("expected backlink in directory listing")
}
if !strings.Contains(s, "<a href=\"/prefix/file.txt\">") {
if !strings.Contains(s, "<a href=\"/good-prefix/file.txt\">") {
t.Fatalf("expected file in directory listing")
}

// make request to directory listing with illegal prefix
req, err = http.NewRequest("GET", ts.URL, nil)
if err != nil {
t.Fatal(err)
}
req.Host = "example.net"
req.Header.Set("X-Ipfs-Gateway-Prefix", "/bad-prefix")

res, err = doWithoutRedirect(req)
if err != nil {
t.Fatal(err)
}

// make request to directory listing with evil prefix
req, err = http.NewRequest("GET", ts.URL, nil)
if err != nil {
t.Fatal(err)
}
req.Host = "example.net"
req.Header.Set("X-Ipfs-Gateway-Prefix", "//good-prefix/foo")

res, err = doWithoutRedirect(req)
if err != nil {
t.Fatal(err)
}

// expect correct backlinks without illegal prefix
body, err = ioutil.ReadAll(res.Body)
if err != nil {
t.Fatalf("error reading response: %s", err)
}
s = string(body)
t.Logf("body: %s\n", string(body))

if !strings.Contains(s, "Index of /") {
t.Fatalf("expected a path in directory listing")
}
if !strings.Contains(s, "<a href=\"/\">") {
t.Fatalf("expected backlink in directory listing")
}
if !strings.Contains(s, "<a href=\"/file.txt\">") {
t.Fatalf("expected file in directory listing")
}
}
Expand Down

0 comments on commit 4bda147

Please sign in to comment.