Skip to content

Commit

Permalink
use PathEscape
Browse files Browse the repository at this point in the history
  • Loading branch information
neolynx committed Oct 10, 2024
1 parent 0403480 commit eeea21e
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 16 deletions.
13 changes: 8 additions & 5 deletions api/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"sync"

"github.com/aptly-dev/aptly/utils"
"github.com/gin-gonic/gin"
"github.com/saracen/walker"
)
Expand Down Expand Up @@ -72,7 +73,7 @@ func apiFilesUpload(c *gin.Context) {
return
}

path := filepath.Join(context.UploadPath(), c.Params.ByName("dir"))
path := filepath.Join(context.UploadPath(), utils.PathEscape(c.Params.ByName("dir")))
err := os.MkdirAll(path, 0777)

if err != nil {
Expand Down Expand Up @@ -128,7 +129,7 @@ func apiFilesListFiles(c *gin.Context) {

list := []string{}
listLock := &sync.Mutex{}
root := filepath.Join(context.UploadPath(), c.Params.ByName("dir"))
root := filepath.Join(context.UploadPath(), utils.PathEscape(c.Params.ByName("dir")))

err := filepath.Walk(root, func(path string, _ os.FileInfo, err error) error {
if err != nil {
Expand Down Expand Up @@ -164,7 +165,7 @@ func apiFilesDeleteDir(c *gin.Context) {
return
}

err := os.RemoveAll(filepath.Join(context.UploadPath(), c.Params.ByName("dir")))
err := os.RemoveAll(filepath.Join(context.UploadPath(), utils.PathEscape(c.Params.ByName("dir"))))
if err != nil {
AbortWithJSONError(c, 500, err)
return
Expand All @@ -179,12 +180,14 @@ func apiFilesDeleteFile(c *gin.Context) {
return
}

if !verifyPath(c.Params.ByName("name")) {
dir := utils.PathEscape(c.Params.ByName("dir"))
name := utils.PathEscape(c.Params.ByName("name"))
if !verifyPath(name) {
AbortWithJSONError(c, 400, fmt.Errorf("wrong file"))
return
}

err := os.Remove(filepath.Join(context.UploadPath(), c.Params.ByName("dir"), c.Params.ByName("name")))
err := os.Remove(filepath.Join(context.UploadPath(), dir, name))
if err != nil {
if err1, ok := err.(*os.PathError); !ok || !os.IsNotExist(err1.Err) {
AbortWithJSONError(c, 500, err)
Expand Down
16 changes: 9 additions & 7 deletions api/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/aptly-dev/aptly/deb"
"github.com/aptly-dev/aptly/pgp"
"github.com/aptly-dev/aptly/task"
"github.com/aptly-dev/aptly/utils"
"github.com/gin-gonic/gin"
)

Expand Down Expand Up @@ -43,11 +44,10 @@ func getSigner(options *SigningOptions) (pgp.Signer, error) {
return signer, nil
}

// Replace '_' with '/' and double '__' with single '_', remove leading '/', remove '..'
func parseEscapedPath(path string) string {
// Replace '_' with '/' and double '__' with single '_', pathEscape
func slashEscape(path string) string {
result := strings.Replace(strings.Replace(path, "_", "/", -1), "//", "_", -1)
result = strings.Replace(result, "..", "", -1)
result = strings.TrimPrefix(result, "/")
result = utils.PathEscape(result)
if result == "" {
result = "."
}
Expand Down Expand Up @@ -88,7 +88,7 @@ func apiPublishList(c *gin.Context) {

// POST /publish/:prefix
func apiPublishRepoOrSnapshot(c *gin.Context) {
param := parseEscapedPath(c.Params.ByName("prefix"))
param := slashEscape(c.Params.ByName("prefix"))
storage, prefix := deb.ParsePrefix(param)

var b struct {
Expand All @@ -115,6 +115,8 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
return
}

b.Distribution = utils.PathEscape(b.Distribution)

signer, err := getSigner(&b.Signing)
if err != nil {
AbortWithJSONError(c, 500, fmt.Errorf("unable to initialize GPG signer: %s", err))
Expand Down Expand Up @@ -250,7 +252,7 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {

// PUT /publish/:prefix/:distribution
func apiPublishUpdateSwitch(c *gin.Context) {
param := parseEscapedPath(c.Params.ByName("prefix"))
param := slashEscape(c.Params.ByName("prefix"))
storage, prefix := deb.ParsePrefix(param)
distribution := c.Params.ByName("distribution")

Expand Down Expand Up @@ -375,7 +377,7 @@ func apiPublishDrop(c *gin.Context) {
force := c.Request.URL.Query().Get("force") == "1"
skipCleanup := c.Request.URL.Query().Get("SkipCleanup") == "1"

param := parseEscapedPath(c.Params.ByName("prefix"))
param := slashEscape(c.Params.ByName("prefix"))
storage, prefix := deb.ParsePrefix(param)
distribution := c.Params.ByName("distribution")

Expand Down
8 changes: 4 additions & 4 deletions api/repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,8 @@ func apiReposPackageFromDir(c *gin.Context) {
return
}

dirParam := c.Params.ByName("dir")
fileParam := c.Params.ByName("file")
dirParam := utils.PathEscape(c.Params.ByName("dir"))
fileParam := utils.PathEscape(c.Params.ByName("file"))
if fileParam != "" && !verifyPath(fileParam) {
AbortWithJSONError(c, 400, fmt.Errorf("wrong file"))
return
Expand Down Expand Up @@ -620,8 +620,8 @@ func apiReposIncludePackageFromDir(c *gin.Context) {

var sources []string
var taskName string
dirParam := c.Params.ByName("dir")
fileParam := c.Params.ByName("file")
dirParam := utils.PathEscape(c.Params.ByName("dir"))
fileParam := utils.PathEscape(c.Params.ByName("file"))
if fileParam != "" && !verifyPath(fileParam) {
AbortWithJSONError(c, 400, fmt.Errorf("wrong file"))
return
Expand Down
8 changes: 8 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package utils
import (
"fmt"
"os"
"strings"

"golang.org/x/sys/unix"
)
Expand All @@ -22,3 +23,10 @@ func DirIsAccessible(filename string) error {
}
return nil
}

// Remove leading '/', remove '..'
func PathEscape(path string) (result string) {
result = strings.Replace(path, "..", "", -1)
result = strings.TrimPrefix(result, "/")
return
}

0 comments on commit eeea21e

Please sign in to comment.