Skip to content

Commit dcf5537

Browse files
committed
Check os permissions as if acting as user
Signed-off-by: Peter Verraedt <peter@verraedt.be>
1 parent dad346c commit dcf5537

31 files changed

+180
-157
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ require (
4444
github.com/mhale/smtpd v0.8.0
4545
github.com/minio/sio v0.3.1
4646
github.com/otiai10/copy v1.9.0
47+
github.com/peterverraedt/useros v0.1.5
4748
github.com/pires/go-proxyproto v0.6.2
4849
github.com/pkg/sftp v1.13.6-0.20230213180117-971c283182b6
4950
github.com/pquerna/otp v1.4.0
@@ -121,6 +122,7 @@ require (
121122
github.com/jackc/pgpassfile v1.0.0 // indirect
122123
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
123124
github.com/jmespath/go-jmespath v0.4.0 // indirect
125+
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 // indirect
124126
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
125127
github.com/kr/fs v0.1.0 // indirect
126128
github.com/lestrrat-go/blackmagic v1.0.1 // indirect

go.sum

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,9 @@ github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx
14111411
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
14121412
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
14131413
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
1414+
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 h1:hgVxRoDDPtQE68PT4LFvNlPz2nBKd3OMlGKIQ69OmR4=
1415+
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531/go.mod h1:fqTUQpVYBvhCNIsMXGl2GE9q6z94DIP6NtFKXCSTVbg=
1416+
github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d h1:J8tJzRyiddAFF65YVgxli+TyWBi0f79Sld6rJP6CBcY=
14141417
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
14151418
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
14161419
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -1708,6 +1711,8 @@ github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9Cjg
17081711
github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
17091712
github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM=
17101713
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
1714+
github.com/peterverraedt/useros v0.1.5 h1:zwt96Q/3vm89gAUlgFzyfq3aiTVpGsvapIQqnxEphXA=
1715+
github.com/peterverraedt/useros v0.1.5/go.mod h1:JJp7q3r6tvRHC0QcQ3BifCSvQGQeeBxShAjdUS/yg1I=
17111716
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
17121717
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
17131718
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=

internal/common/actions_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ func TestPreDeleteAction(t *testing.T) {
262262
}
263263
user.Permissions = make(map[string][]string)
264264
user.Permissions["/"] = []string{dataprovider.PermAny}
265-
fs := vfs.NewOsFs("id", homeDir, "")
265+
fs := vfs.NewOsFs("id", homeDir, "", 0, 0)
266266
c := NewBaseConnection("id", ProtocolSFTP, "", "", user)
267267

268268
testfile := filepath.Join(user.HomeDir, "testfile")

internal/common/common_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ func TestConnectionStatus(t *testing.T) {
830830
Username: username,
831831
},
832832
}
833-
fs := vfs.NewOsFs("", os.TempDir(), "")
833+
fs := vfs.NewOsFs("", os.TempDir(), "", 0, 0)
834834
c1 := NewBaseConnection("id1", ProtocolSFTP, "", "", user)
835835
fakeConn1 := &fakeConnection{
836836
BaseConnection: c1,

internal/common/connection.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,6 @@ func (c *BaseConnection) CreateDir(virtualPath string, checkFilePatterns bool) e
365365
c.Log(logger.LevelError, "error creating dir: %q error: %+v", fsPath, err)
366366
return c.GetFsError(fs, err)
367367
}
368-
vfs.SetPathPermissions(fs, fsPath, c.User.GetUID(), c.User.GetGID())
369368
elapsed := time.Since(startTime).Nanoseconds() / 1000000
370369

371370
logger.CommandLog(mkdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1,
@@ -764,7 +763,6 @@ func (c *BaseConnection) renameInternal(virtualSourcePath, virtualTargetPath str
764763
c.Log(logger.LevelError, "failed to rename %q -> %q: %+v", fsSourcePath, fsTargetPath, err)
765764
return c.GetFsError(fsSrc, err)
766765
}
767-
vfs.SetPathPermissions(fsDst, fsTargetPath, c.User.GetUID(), c.User.GetGID())
768766
elapsed := time.Since(startTime).Nanoseconds() / 1000000
769767
c.updateQuotaAfterRename(fsDst, virtualSourcePath, virtualTargetPath, fsTargetPath, initialSize, files, size) //nolint:errcheck
770768
logger.CommandLog(renameLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1,

internal/common/connection_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (fs *MockOsFs) Walk(root string, walkFn filepath.WalkFunc) error {
8686

8787
func newMockOsFs(hasVirtualFolders bool, connectionID, rootDir, name string, err error) vfs.Fs {
8888
return &MockOsFs{
89-
Fs: vfs.NewOsFs(connectionID, rootDir, ""),
89+
Fs: vfs.NewOsFs(connectionID, rootDir, "", 0, 0),
9090
name: name,
9191
hasVirtualFolders: hasVirtualFolders,
9292
err: err,
@@ -114,7 +114,7 @@ func TestRemoveErrors(t *testing.T) {
114114
}
115115
user.Permissions = make(map[string][]string)
116116
user.Permissions["/"] = []string{dataprovider.PermAny}
117-
fs := vfs.NewOsFs("", os.TempDir(), "")
117+
fs := vfs.NewOsFs("", os.TempDir(), "", 0, 0)
118118
conn := NewBaseConnection("", ProtocolFTP, "", "", user)
119119
err := conn.IsRemoveDirAllowed(fs, mappedPath, "/virtualpath1")
120120
if assert.Error(t, err) {
@@ -159,7 +159,7 @@ func TestSetStatMode(t *testing.T) {
159159
}
160160

161161
func TestRecursiveRenameWalkError(t *testing.T) {
162-
fs := vfs.NewOsFs("", filepath.Clean(os.TempDir()), "")
162+
fs := vfs.NewOsFs("", filepath.Clean(os.TempDir()), "", 0, 0)
163163
conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{
164164
BaseUser: sdk.BaseUser{
165165
Permissions: map[string][]string{
@@ -193,7 +193,7 @@ func TestRecursiveRenameWalkError(t *testing.T) {
193193
}
194194

195195
func TestCrossRenameFsErrors(t *testing.T) {
196-
fs := vfs.NewOsFs("", os.TempDir(), "")
196+
fs := vfs.NewOsFs("", os.TempDir(), "", 0, 0)
197197
conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{})
198198
res := conn.hasSpaceForCrossRename(fs, vfs.QuotaCheckResult{}, 1, "missingsource")
199199
assert.False(t, res)
@@ -224,7 +224,7 @@ func TestRenameVirtualFolders(t *testing.T) {
224224
},
225225
VirtualPath: vdir,
226226
})
227-
fs := vfs.NewOsFs("", os.TempDir(), "")
227+
fs := vfs.NewOsFs("", os.TempDir(), "", 0, 0)
228228
conn := NewBaseConnection("", ProtocolFTP, "", "", u)
229229
res := conn.isRenamePermitted(fs, fs, "source", "target", vdir, "vdirtarget", nil)
230230
assert.False(t, res)
@@ -376,7 +376,7 @@ func TestUpdateQuotaAfterRename(t *testing.T) {
376376
}
377377

378378
func TestErrorsMapping(t *testing.T) {
379-
fs := vfs.NewOsFs("", os.TempDir(), "")
379+
fs := vfs.NewOsFs("", os.TempDir(), "", 0, 0)
380380
conn := NewBaseConnection("", ProtocolSFTP, "", "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}})
381381
osErrorsProtocols := []string{ProtocolWebDAV, ProtocolFTP, ProtocolHTTP, ProtocolHTTPShare,
382382
ProtocolDataRetention, ProtocolOIDC, protocolEventAction}

internal/common/eventmanager.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,6 @@ func getFileWriter(conn *BaseConnection, virtualPath string, expectedSize int64)
795795
if err != nil {
796796
return nil, numFiles, truncatedSize, nil, conn.GetFsError(fs, err)
797797
}
798-
vfs.SetPathPermissions(fs, fsPath, conn.User.GetUID(), conn.User.GetGID())
799798

800799
if isFileOverwrite {
801800
if vfs.HasTruncateSupport(fs) || vfs.IsCryptOsFs(fs) {
@@ -1927,7 +1926,7 @@ func executeFoldersQuotaResetRuleAction(conditions dataprovider.ConditionOptions
19271926
BaseVirtualFolder: folder,
19281927
VirtualPath: "/",
19291928
}
1930-
numFiles, size, err := f.ScanQuota()
1929+
numFiles, size, err := f.ScanQuota(0, 0)
19311930
QuotaScans.RemoveVFolderQuotaScan(folder.Name)
19321931
if err != nil {
19331932
eventManagerLog(logger.LevelError, "error scanning quota for folder %q: %v", folder.Name, err)

internal/common/transfer_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestTransferUpdateQuota(t *testing.T) {
3535
transfer := BaseTransfer{
3636
Connection: conn,
3737
transferType: TransferUpload,
38-
Fs: vfs.NewOsFs("", os.TempDir(), ""),
38+
Fs: vfs.NewOsFs("", os.TempDir(), "", 0, 0),
3939
}
4040
transfer.BytesReceived.Store(123)
4141
errFake := errors.New("fake error")
@@ -74,7 +74,7 @@ func TestTransferThrottling(t *testing.T) {
7474
DownloadBandwidth: 40,
7575
},
7676
}
77-
fs := vfs.NewOsFs("", os.TempDir(), "")
77+
fs := vfs.NewOsFs("", os.TempDir(), "", 0, 0)
7878
testFileSize := int64(131072)
7979
wantedUploadElapsed := 1000 * (testFileSize / 1024) / u.UploadBandwidth
8080
wantedDownloadElapsed := 1000 * (testFileSize / 1024) / u.DownloadBandwidth
@@ -106,7 +106,7 @@ func TestTransferThrottling(t *testing.T) {
106106

107107
func TestRealPath(t *testing.T) {
108108
testFile := filepath.Join(os.TempDir(), "afile.txt")
109-
fs := vfs.NewOsFs("123", os.TempDir(), "")
109+
fs := vfs.NewOsFs("123", os.TempDir(), "", 0, 0)
110110
u := dataprovider.User{
111111
BaseUser: sdk.BaseUser{
112112
Username: "user",
@@ -140,7 +140,7 @@ func TestRealPath(t *testing.T) {
140140

141141
func TestTruncate(t *testing.T) {
142142
testFile := filepath.Join(os.TempDir(), "transfer_test_file")
143-
fs := vfs.NewOsFs("123", os.TempDir(), "")
143+
fs := vfs.NewOsFs("123", os.TempDir(), "", 0, 0)
144144
u := dataprovider.User{
145145
BaseUser: sdk.BaseUser{
146146
Username: "user",
@@ -209,7 +209,7 @@ func TestTransferErrors(t *testing.T) {
209209
isCancelled = true
210210
}
211211
testFile := filepath.Join(os.TempDir(), "transfer_test_file")
212-
fs := vfs.NewOsFs("id", os.TempDir(), "")
212+
fs := vfs.NewOsFs("id", os.TempDir(), "", 0, 0)
213213
u := dataprovider.User{
214214
BaseUser: sdk.BaseUser{
215215
Username: "test",
@@ -316,7 +316,7 @@ func TestFTPMode(t *testing.T) {
316316
transfer := BaseTransfer{
317317
Connection: conn,
318318
transferType: TransferUpload,
319-
Fs: vfs.NewOsFs("", os.TempDir(), ""),
319+
Fs: vfs.NewOsFs("", os.TempDir(), "", 0, 0),
320320
}
321321
transfer.BytesReceived.Store(123)
322322
assert.Empty(t, transfer.ftpMode)
@@ -394,7 +394,7 @@ func TestTransferQuota(t *testing.T) {
394394

395395
conn := NewBaseConnection("", ProtocolSFTP, "", "", user)
396396
transfer := NewBaseTransfer(nil, conn, nil, "file.txt", "file.txt", "/transfer_test_file", TransferUpload,
397-
0, 0, 0, 0, true, vfs.NewOsFs("", os.TempDir(), ""), dataprovider.TransferQuota{})
397+
0, 0, 0, 0, true, vfs.NewOsFs("", os.TempDir(), "", 0, 0), dataprovider.TransferQuota{})
398398
err := transfer.CheckRead()
399399
assert.NoError(t, err)
400400
err = transfer.CheckWrite()
@@ -448,7 +448,7 @@ func TestUploadOutsideHomeRenameError(t *testing.T) {
448448
transfer := BaseTransfer{
449449
Connection: conn,
450450
transferType: TransferUpload,
451-
Fs: vfs.NewOsFs("", filepath.Join(os.TempDir(), "home"), ""),
451+
Fs: vfs.NewOsFs("", filepath.Join(os.TempDir(), "home"), "", 0, 0),
452452
}
453453
transfer.BytesReceived.Store(123)
454454

internal/dataprovider/user.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func (u *User) getRootFs(connectionID string) (fs vfs.Fs, err error) {
173173
case sdk.HTTPFilesystemProvider:
174174
return vfs.NewHTTPFs(connectionID, u.GetHomeDir(), "", u.FsConfig.HTTPConfig)
175175
default:
176-
return vfs.NewOsFs(connectionID, u.GetHomeDir(), ""), nil
176+
return vfs.NewOsFs(connectionID, u.GetHomeDir(), "", u.UID, u.GID), nil
177177
}
178178
}
179179

@@ -204,7 +204,6 @@ func (u *User) checkDirWithParents(virtualDirPath, connectionID string) error {
204204
if err != nil {
205205
return err
206206
}
207-
vfs.SetPathPermissions(fs, fsPath, u.GetUID(), u.GetGID())
208207
} else {
209208
return fmt.Errorf("unable to stat path %q: %w", vPath, err)
210209
}
@@ -218,7 +217,7 @@ func (u *User) checkLocalHomeDir(connectionID string) {
218217
case sdk.LocalFilesystemProvider, sdk.CryptedFilesystemProvider:
219218
return
220219
default:
221-
osFs := vfs.NewOsFs(connectionID, u.GetHomeDir(), "")
220+
osFs := vfs.NewOsFs(connectionID, u.GetHomeDir(), "", u.UID, u.GID)
222221
osFs.CheckRootPath(u.Username, u.GetUID(), u.GetGID())
223222
}
224223
}
@@ -565,7 +564,7 @@ func (u *User) GetFilesystemForPath(virtualPath, connectionID string) (vfs.Fs, e
565564
}
566565
forbiddenSelfUsers = append(forbiddenSelfUsers, forbiddens...)
567566
}
568-
fs, err := folder.GetFilesystem(connectionID, forbiddenSelfUsers)
567+
fs, err := folder.GetFilesystem(connectionID, u.UID, u.GID, forbiddenSelfUsers)
569568
if err == nil {
570569
u.fsCache[folder.VirtualPath] = fs
571570
}
@@ -617,7 +616,7 @@ func (u *User) CheckMetadataConsistency() error {
617616
}
618617
for idx := range u.VirtualFolders {
619618
v := &u.VirtualFolders[idx]
620-
if err = v.CheckMetadataConsistency(); err != nil {
619+
if err = v.CheckMetadataConsistency(u.UID, u.GID); err != nil {
621620
return err
622621
}
623622
}
@@ -642,7 +641,7 @@ func (u *User) ScanQuota() (int, int64, error) {
642641
if !v.IsIncludedInUserQuota() {
643642
continue
644643
}
645-
num, s, err := v.ScanQuota()
644+
num, s, err := v.ScanQuota(u.UID, u.GID)
646645
if err != nil {
647646
return numFiles, size, err
648647
}

internal/ftpd/handler.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,6 @@ func (c *Connection) handleFTPUploadToNewFile(fs vfs.Fs, flags int, resolvedPath
414414
return nil, c.GetFsError(fs, err)
415415
}
416416

417-
vfs.SetPathPermissions(fs, filePath, c.User.GetUID(), c.User.GetGID())
418-
419417
// we can get an error only for resume
420418
maxWriteSize, _ := c.GetMaxWriteSize(diskQuota, false, 0, fs.IsUploadResumeSupported())
421419

@@ -496,8 +494,6 @@ func (c *Connection) handleFTPUploadToExistingFile(fs vfs.Fs, flags int, resolve
496494
}
497495
}
498496

499-
vfs.SetPathPermissions(fs, filePath, c.User.GetUID(), c.User.GetGID())
500-
501497
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, resolvedPath, filePath, requestPath,
502498
common.TransferUpload, minWriteOffset, initialSize, maxWriteSize, truncatedSize, false, fs, transferQuota)
503499
baseTransfer.SetFtpMode(c.getFTPMode())

0 commit comments

Comments
 (0)