diff --git a/internal/model/model.go b/internal/model/model.go index c13425c55..472d43ef8 100644 --- a/internal/model/model.go +++ b/internal/model/model.go @@ -710,9 +710,14 @@ func (m *Model) Close(device protocol.DeviceID, err error) { // Request returns the specified data segment by reading it from local disk. // Implements the protocol.Model interface. func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset int64, size int) ([]byte, error) { + if !m.folderSharedWith(folder, deviceID) { + l.Warnf("Request from %s for file %s in unshared folder %q", deviceID, name, folder) + return nil, ErrNoSuchFile + } + // Verify that the requested file exists in the local model. m.fmut.RLock() - r, ok := m.folderFiles[folder] + folderFiles, ok := m.folderFiles[folder] m.fmut.RUnlock() if !ok { @@ -720,7 +725,7 @@ func (m *Model) Request(deviceID protocol.DeviceID, folder, name string, offset return nil, ErrNoSuchFile } - lf, ok := r.Get(protocol.LocalDeviceID, name) + lf, ok := folderFiles.Get(protocol.LocalDeviceID, name) if !ok { return nil, ErrNoSuchFile } diff --git a/internal/model/model_test.go b/internal/model/model_test.go index 1e17fd23a..03361943f 100644 --- a/internal/model/model_test.go +++ b/internal/model/model_test.go @@ -68,18 +68,41 @@ func init() { func TestRequest(t *testing.T) { db, _ := leveldb.Open(storage.NewMemStorage(), nil) + m := NewModel(config.Wrap("/tmp/test", config.Configuration{}), "device", "syncthing", "dev", db) - m.AddFolder(config.FolderConfiguration{ID: "default", Path: "testdata"}) + + // device1 shares default, but device2 doesn't + m.AddFolder(config.FolderConfiguration{ID: "default", Path: "testdata", Devices: []config.FolderDeviceConfiguration{{DeviceID: device1}}}) m.ScanFolder("default") + // Existing, shared file bs, err := m.Request(device1, "default", "foo", 0, 6) if err != nil { - t.Fatal(err) + t.Error(err) } if bytes.Compare(bs, []byte("foobar")) != 0 { t.Errorf("Incorrect data from request: %q", string(bs)) } + // Existing, nonshared file + bs, err = m.Request(device2, "default", "foo", 0, 6) + if err == nil { + t.Error("Unexpected nil error on insecure file read") + } + if bs != nil { + t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs)) + } + + // Nonexistent file + bs, err = m.Request(device1, "default", "nonexistent", 0, 6) + if err == nil { + t.Error("Unexpected nil error on insecure file read") + } + if bs != nil { + t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs)) + } + + // Shared folder, but disallowed file name bs, err = m.Request(device1, "default", "../walk.go", 0, 6) if err == nil { t.Error("Unexpected nil error on insecure file read")