scp: return better error messages

Fixes #171
This commit is contained in:
Nicola Murino
2020-09-18 19:13:09 +02:00
parent 242dde4480
commit 209badf10c
5 changed files with 59 additions and 18 deletions

View File

@@ -124,8 +124,9 @@ func (c *scpCommand) handleCreateDir(dirPath string) error {
} }
if !c.connection.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(dirPath)) { if !c.connection.User.HasPerm(dataprovider.PermCreateDirs, path.Dir(dirPath)) {
c.connection.Log(logger.LevelWarn, "error creating dir: %#v, permission denied", dirPath) c.connection.Log(logger.LevelWarn, "error creating dir: %#v, permission denied", dirPath)
c.sendErrorMessage(common.ErrPermissionDenied) err := c.connection.Fs.GetPermissionError()
return common.ErrPermissionDenied c.sendErrorMessage(err)
return err
} }
err = c.createDir(p) err = c.createDir(p)
@@ -239,13 +240,15 @@ func (c *scpCommand) handleUpload(uploadFilePath string, sizeToRead int64) error
if !c.connection.User.IsFileAllowed(uploadFilePath) { if !c.connection.User.IsFileAllowed(uploadFilePath) {
c.connection.Log(logger.LevelWarn, "writing file %#v is not allowed", uploadFilePath) c.connection.Log(logger.LevelWarn, "writing file %#v is not allowed", uploadFilePath)
c.sendErrorMessage(common.ErrPermissionDenied) err := c.connection.Fs.GetPermissionError()
c.sendErrorMessage(err)
return err
} }
p, err := c.connection.Fs.ResolvePath(uploadFilePath) p, err := c.connection.Fs.ResolvePath(uploadFilePath)
if err != nil { if err != nil {
c.connection.Log(logger.LevelWarn, "error uploading file: %#v, err: %v", uploadFilePath, err) c.connection.Log(logger.LevelWarn, "error uploading file: %#v, err: %v", uploadFilePath, err)
c.sendErrorMessage(c.connection.GetFsError(err)) c.sendErrorMessage(err)
return err return err
} }
filePath := p filePath := p
@@ -256,8 +259,9 @@ func (c *scpCommand) handleUpload(uploadFilePath string, sizeToRead int64) error
if (statErr == nil && stat.Mode()&os.ModeSymlink == os.ModeSymlink) || c.connection.Fs.IsNotExist(statErr) { if (statErr == nil && stat.Mode()&os.ModeSymlink == os.ModeSymlink) || c.connection.Fs.IsNotExist(statErr) {
if !c.connection.User.HasPerm(dataprovider.PermUpload, path.Dir(uploadFilePath)) { if !c.connection.User.HasPerm(dataprovider.PermUpload, path.Dir(uploadFilePath)) {
c.connection.Log(logger.LevelWarn, "cannot upload file: %#v, permission denied", uploadFilePath) c.connection.Log(logger.LevelWarn, "cannot upload file: %#v, permission denied", uploadFilePath)
c.sendErrorMessage(common.ErrPermissionDenied) err := c.connection.Fs.GetPermissionError()
return common.ErrPermissionDenied c.sendErrorMessage(err)
return err
} }
return c.handleUploadFile(p, filePath, sizeToRead, true, 0, uploadFilePath) return c.handleUploadFile(p, filePath, sizeToRead, true, 0, uploadFilePath)
} }
@@ -277,8 +281,9 @@ func (c *scpCommand) handleUpload(uploadFilePath string, sizeToRead int64) error
if !c.connection.User.HasPerm(dataprovider.PermOverwrite, uploadFilePath) { if !c.connection.User.HasPerm(dataprovider.PermOverwrite, uploadFilePath) {
c.connection.Log(logger.LevelWarn, "cannot overwrite file: %#v, permission denied", uploadFilePath) c.connection.Log(logger.LevelWarn, "cannot overwrite file: %#v, permission denied", uploadFilePath)
c.sendErrorMessage(common.ErrPermissionDenied) err := c.connection.Fs.GetPermissionError()
return common.ErrPermissionDenied c.sendErrorMessage(err)
return err
} }
if common.Config.IsAtomicUploadEnabled() && c.connection.Fs.IsAtomicUploadSupported() { if common.Config.IsAtomicUploadEnabled() && c.connection.Fs.IsAtomicUploadSupported() {
@@ -286,7 +291,7 @@ func (c *scpCommand) handleUpload(uploadFilePath string, sizeToRead int64) error
if err != nil { if err != nil {
c.connection.Log(logger.LevelError, "error renaming existing file for atomic upload, source: %#v, dest: %#v, err: %v", c.connection.Log(logger.LevelError, "error renaming existing file for atomic upload, source: %#v, dest: %#v, err: %v",
p, filePath, err) p, filePath, err)
c.sendErrorMessage(c.connection.GetFsError(err)) c.sendErrorMessage(err)
return err return err
} }
} }
@@ -444,22 +449,23 @@ func (c *scpCommand) handleDownload(filePath string) error {
if err != nil { if err != nil {
err := fmt.Errorf("Invalid file path") err := fmt.Errorf("Invalid file path")
c.connection.Log(logger.LevelWarn, "error downloading file: %#v, invalid file path", filePath) c.connection.Log(logger.LevelWarn, "error downloading file: %#v, invalid file path", filePath)
c.sendErrorMessage(c.connection.GetFsError(err)) c.sendErrorMessage(err)
return err return err
} }
var stat os.FileInfo var stat os.FileInfo
if stat, err = c.connection.Fs.Stat(p); err != nil { if stat, err = c.connection.Fs.Stat(p); err != nil {
c.connection.Log(logger.LevelWarn, "error downloading file: %#v->%#v, err: %v", filePath, p, err) c.connection.Log(logger.LevelWarn, "error downloading file: %#v->%#v, err: %v", filePath, p, err)
c.sendErrorMessage(c.connection.GetFsError(err)) c.sendErrorMessage(err)
return err return err
} }
if stat.IsDir() { if stat.IsDir() {
if !c.connection.User.HasPerm(dataprovider.PermDownload, filePath) { if !c.connection.User.HasPerm(dataprovider.PermDownload, filePath) {
c.connection.Log(logger.LevelWarn, "error downloading dir: %#v, permission denied", filePath) c.connection.Log(logger.LevelWarn, "error downloading dir: %#v, permission denied", filePath)
c.sendErrorMessage(common.ErrPermissionDenied) err := c.connection.Fs.GetPermissionError()
return common.ErrPermissionDenied c.sendErrorMessage(err)
return err
} }
err = c.handleRecursiveDownload(p, stat) err = c.handleRecursiveDownload(p, stat)
return err return err
@@ -467,19 +473,22 @@ func (c *scpCommand) handleDownload(filePath string) error {
if !c.connection.User.HasPerm(dataprovider.PermDownload, path.Dir(filePath)) { if !c.connection.User.HasPerm(dataprovider.PermDownload, path.Dir(filePath)) {
c.connection.Log(logger.LevelWarn, "error downloading dir: %#v, permission denied", filePath) c.connection.Log(logger.LevelWarn, "error downloading dir: %#v, permission denied", filePath)
c.sendErrorMessage(common.ErrPermissionDenied) err := c.connection.Fs.GetPermissionError()
return common.ErrPermissionDenied c.sendErrorMessage(err)
return err
} }
if !c.connection.User.IsFileAllowed(filePath) { if !c.connection.User.IsFileAllowed(filePath) {
c.connection.Log(logger.LevelWarn, "reading file %#v is not allowed", filePath) c.connection.Log(logger.LevelWarn, "reading file %#v is not allowed", filePath)
c.sendErrorMessage(common.ErrPermissionDenied) err := c.connection.Fs.GetPermissionError()
c.sendErrorMessage(err)
return err
} }
file, r, cancelFn, err := c.connection.Fs.Open(p, 0) file, r, cancelFn, err := c.connection.Fs.Open(p, 0)
if err != nil { if err != nil {
c.connection.Log(logger.LevelError, "could not open file %#v for reading: %v", p, err) c.connection.Log(logger.LevelError, "could not open file %#v for reading: %v", p, err)
c.sendErrorMessage(c.connection.GetFsError(err)) c.sendErrorMessage(err)
return err return err
} }
@@ -625,7 +634,7 @@ func (c *scpCommand) createDir(dirPath string) error {
} }
if err = c.connection.Fs.Mkdir(dirPath); err != nil { if err = c.connection.Fs.Mkdir(dirPath); err != nil {
c.connection.Log(logger.LevelError, "error creating dir %#v: %v", dirPath, err) c.connection.Log(logger.LevelError, "error creating dir %#v: %v", dirPath, err)
c.sendErrorMessage(c.connection.GetFsError(err)) c.sendErrorMessage(err)
return err return err
} }
vfs.SetPathPermissions(c.connection.Fs, dirPath, c.connection.User.GetUID(), c.connection.User.GetGID()) vfs.SetPathPermissions(c.connection.Fs, dirPath, c.connection.User.GetUID(), c.connection.User.GetGID())

View File

@@ -402,6 +402,16 @@ func (GCSFs) IsPermission(err error) bool {
return strings.Contains(err.Error(), "403") return strings.Contains(err.Error(), "403")
} }
// GetPermissionError returns a permission error for this FS
func (GCSFs) GetPermissionError() error {
return errors.New("403 permission denied")
}
// GetNotExistError returns a not exist error for this FS
func (GCSFs) GetNotExistError() error {
return errors.New("404 no such file or directory")
}
// CheckRootPath creates the specified local root directory if it does not exists // CheckRootPath creates the specified local root directory if it does not exists
func (fs GCSFs) CheckRootPath(username string, uid int, gid int) bool { func (fs GCSFs) CheckRootPath(username string, uid int, gid int) bool {
// we need a local directory for temporary files // we need a local directory for temporary files

View File

@@ -183,6 +183,16 @@ func (OsFs) IsPermission(err error) bool {
return os.IsPermission(err) return os.IsPermission(err)
} }
// GetPermissionError returns a permission error for this FS
func (OsFs) GetPermissionError() error {
return os.ErrPermission
}
// GetNotExistError returns a not exist error for this FS
func (OsFs) GetNotExistError() error {
return os.ErrNotExist
}
// CheckRootPath creates the root directory if it does not exists // CheckRootPath creates the root directory if it does not exists
func (fs OsFs) CheckRootPath(username string, uid int, gid int) bool { func (fs OsFs) CheckRootPath(username string, uid int, gid int) bool {
var err error var err error

View File

@@ -427,6 +427,16 @@ func (S3Fs) IsPermission(err error) bool {
return strings.Contains(err.Error(), "403") return strings.Contains(err.Error(), "403")
} }
// GetPermissionError returns a permission error for this FS
func (S3Fs) GetPermissionError() error {
return errors.New("403 permission denied")
}
// GetNotExistError returns a not exist error for this FS
func (S3Fs) GetNotExistError() error {
return errors.New("404 no such file or directory")
}
// CheckRootPath creates the specified local root directory if it does not exists // CheckRootPath creates the specified local root directory if it does not exists
func (fs S3Fs) CheckRootPath(username string, uid int, gid int) bool { func (fs S3Fs) CheckRootPath(username string, uid int, gid int) bool {
// we need a local directory for temporary files // we need a local directory for temporary files

View File

@@ -40,6 +40,8 @@ type Fs interface {
ResolvePath(sftpPath string) (string, error) ResolvePath(sftpPath string) (string, error)
IsNotExist(err error) bool IsNotExist(err error) bool
IsPermission(err error) bool IsPermission(err error) bool
GetPermissionError() error
GetNotExistError() error
ScanRootDirContents() (int, int64, error) ScanRootDirContents() (int, int64, error)
GetDirSize(dirname string) (int, int64, error) GetDirSize(dirname string) (int, int64, error)
GetAtomicUploadPath(name string) string GetAtomicUploadPath(name string) string