diff options
author | Kamil Trzciński <ayufan@ayufan.eu> | 2019-02-28 17:46:18 +0300 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2019-02-28 17:46:18 +0300 |
commit | a6d5eb8ecac9f3f74f156037d200dff620b2fa2c (patch) | |
tree | f33757a8c0b2de950c5d4690b236c8da226480f0 /internal/client | |
parent | 7254174ea9ee4c611f65329dc7a0603388b3742e (diff) |
Fix handling of paths
Diffstat (limited to 'internal/client')
-rw-r--r-- | internal/client/api.go | 41 | ||||
-rw-r--r-- | internal/client/domain_response.go | 24 | ||||
-rw-r--r-- | internal/client/lookup_path.go | 75 |
3 files changed, 99 insertions, 41 deletions
diff --git a/internal/client/api.go b/internal/client/api.go index 77f5d94a..5566f151 100644 --- a/internal/client/api.go +++ b/internal/client/api.go @@ -4,49 +4,8 @@ import ( "encoding/json" "net/http" "net/url" - "strings" ) -type LookupConfig struct { - NamespaceProject bool `json:"namespace_project"` - HTTPSOnly bool `json:"https_only"` - AccessControl bool `json:"access_control"` - ProjectID uint64 `json:"id"` -} - -type LookupPath struct { - LookupConfig - - Prefix string `json:"prefix"` - Path string `json:"path"` -} - -func (lp *LookupPath) Tail(r *http.Request) string { - if strings.HasPrefix(r.URL.Path, lp.Prefix) { - return r.URL.Path[len(lp.Path):] - } - - return "" -} - -type DomainResponse struct { - Domain string `json:"domain"` - Certificate string `json:"certificate"` - Key string `json:"certificate_key"` - - LookupPath []LookupPath `json:"lookup_paths"` -} - -func (d *DomainResponse) GetPath(r *http.Request) *LookupPath { - for _, lp := range d.LookupPath { - if strings.HasPrefix(r.RequestURI, lp.Prefix) { - return &lp - } - } - - return nil -} - func RequestDomain(apiUrl, host string) *DomainResponse { var values url.Values values.Add("host", host) diff --git a/internal/client/domain_response.go b/internal/client/domain_response.go new file mode 100644 index 00000000..77d9b474 --- /dev/null +++ b/internal/client/domain_response.go @@ -0,0 +1,24 @@ +package client + +import ( + "net/http" + "strings" +) + +type DomainResponse struct { + Domain string `json:"domain"` + Certificate string `json:"certificate"` + Key string `json:"certificate_key"` + + LookupPath []LookupPath `json:"lookup_paths"` +} + +func (d *DomainResponse) GetPath(r *http.Request) *LookupPath { + for _, lp := range d.LookupPath { + if strings.HasPrefix(r.RequestURI, lp.Prefix) { + return &lp + } + } + + return nil +} diff --git a/internal/client/lookup_path.go b/internal/client/lookup_path.go new file mode 100644 index 00000000..f11dd925 --- /dev/null +++ b/internal/client/lookup_path.go @@ -0,0 +1,75 @@ +package client + +import ( + "fmt" + "net/http" + "os" + "path/filepath" + "strings" + + "golang.org/x/sys/unix" +) + +type LookupConfig struct { + NamespaceProject bool `json:"namespace_project"` + HTTPSOnly bool `json:"https_only"` + AccessControl bool `json:"access_control"` + ProjectID uint64 `json:"id"` +} + +type LookupPath struct { + LookupConfig + + Prefix string `json:"prefix"` + Path string `json:"path"` +} + +func (lp *LookupPath) Tail(r *http.Request) string { + if strings.HasPrefix(r.URL.Path, lp.Prefix) { + return r.URL.Path[len(lp.Path):] + } + + return "" +} + +func (lp *LookupPath) resolvePath(path string) (string, error) { + fullPath := filepath.Join(lp.Path, path) + fullPath, err := filepath.EvalSymlinks(fullPath) + if err != nil { + return "", err + } + + // The requested path resolved to somewhere outside of the public/ directory + if !strings.HasPrefix(fullPath, lp.Path) { + return "", fmt.Errorf("%q should be in %q", fullPath, lp.Path) + } + + return fullPath, nil +} + +func (lp *LookupPath) Resolve(path string) (string, error) { + fullPath, err := lp.resolvePath(path) + if err != nil { + return "", err + } + + return fullPath[len(lp.Path):], nil +} + +func (lp *LookupPath) Stat(path string) (os.FileInfo, error) { + fullPath, err := lp.resolvePath(path) + if err != nil { + return nil, err + } + + return os.Lstat(fullPath) +} + +func (lp *LookupPath) Open(path string) (*os.File, error) { + fullPath, err := lp.resolvePath(path) + if err != nil { + return nil, err + } + + return os.OpenFile(fullPath, os.O_RDONLY|unix.O_NOFOLLOW, 0) +} |