From c41ae116eb7785deabeb93b317d6e8a45768ffad Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Sat, 24 Jul 2021 20:11:17 +0200 Subject: [PATCH] improve logging Fixes #381 --- common/actions_test.go | 2 +- common/common.go | 8 +++-- common/common_test.go | 26 ++++++++------ common/connection.go | 25 +++++++------ common/connection_test.go | 16 ++++----- common/protocol_test.go | 12 +++---- common/transfer.go | 4 +-- common/transfer_test.go | 12 +++---- dataprovider/dataprovider.go | 27 ++++++++------ docs/logs.md | 3 ++ ftpd/handler.go | 7 +++- ftpd/internal_test.go | 14 ++++---- ftpd/server.go | 10 +++--- httpd/api_http_user.go | 5 +-- httpd/handler.go | 7 +++- httpd/httpd_test.go | 16 +++++---- httpd/internal_test.go | 12 +++---- httpd/webclient.go | 15 ++++---- logger/logger.go | 5 +-- logger/request_logger.go | 13 +++++++ sftpd/handler.go | 11 +++++- sftpd/internal_test.go | 68 ++++++++++++++++++------------------ sftpd/server.go | 20 ++++++----- sftpd/ssh_cmd.go | 3 +- sftpd/subsystem.go | 3 +- util/util.go | 13 +++++++ webdavd/handler.go | 7 +++- webdavd/internal_test.go | 14 ++++---- webdavd/server.go | 5 +-- webdavd/webdavd_test.go | 4 +-- 30 files changed, 237 insertions(+), 150 deletions(-) diff --git a/common/actions_test.go b/common/actions_test.go index 67af2faa..715fab79 100644 --- a/common/actions_test.go +++ b/common/actions_test.go @@ -205,7 +205,7 @@ func TestPreDeleteAction(t *testing.T) { user.Permissions = make(map[string][]string) user.Permissions["/"] = []string{dataprovider.PermAny} fs := vfs.NewOsFs("id", homeDir, "") - c := NewBaseConnection("id", ProtocolSFTP, "", user) + c := NewBaseConnection("id", ProtocolSFTP, "", "", user) testfile := filepath.Join(user.HomeDir, "testfile") err = os.WriteFile(testfile, []byte("test"), os.ModePerm) diff --git a/common/common.go b/common/common.go index 7df168ca..8ea84921 100644 --- a/common/common.go +++ b/common/common.go @@ -287,6 +287,7 @@ type ActiveTransfer interface { type ActiveConnection interface { GetID() string GetUsername() string + GetLocalAddress() string GetRemoteAddress() string GetClientVersion() string GetProtocol() string @@ -596,7 +597,8 @@ func (conns *ActiveConnections) Add(c ActiveConnection) { conns.connections = append(conns.connections, c) metric.UpdateActiveConnectionsSize(len(conns.connections)) - logger.Debug(c.GetProtocol(), c.GetID(), "connection added, num open connections: %v", len(conns.connections)) + logger.Debug(c.GetProtocol(), c.GetID(), "connection added, local address %#v, remote address %#v, num open connections: %v", + c.GetLocalAddress(), c.GetRemoteAddress(), len(conns.connections)) } // Swap replaces an existing connection with the given one. @@ -630,8 +632,8 @@ func (conns *ActiveConnections) Remove(connectionID string) { conns.connections[lastIdx] = nil conns.connections = conns.connections[:lastIdx] metric.UpdateActiveConnectionsSize(lastIdx) - logger.Debug(conn.GetProtocol(), conn.GetID(), "connection removed, close fs error: %v, num open connections: %v", - err, lastIdx) + logger.Debug(conn.GetProtocol(), conn.GetID(), "connection removed, local address %#v, remote address %#v close fs error: %v, num open connections: %v", + conn.GetLocalAddress(), conn.GetRemoteAddress(), err, lastIdx) return } } diff --git a/common/common_test.go b/common/common_test.go index 7ea12d76..af310380 100644 --- a/common/common_test.go +++ b/common/common_test.go @@ -60,6 +60,10 @@ func (c *fakeConnection) GetCommand() string { return c.command } +func (c *fakeConnection) GetLocalAddress() string { + return "" +} + func (c *fakeConnection) GetRemoteAddress() string { return "" } @@ -255,7 +259,7 @@ func TestMaxConnections(t *testing.T) { Config.MaxPerHostConnections = perHost assert.True(t, Connections.IsNewConnectionAllowed(ipAddr)) - c := NewBaseConnection("id", ProtocolSFTP, "", dataprovider.User{}) + c := NewBaseConnection("id", ProtocolSFTP, "", "", dataprovider.User{}) fakeConn := &fakeConnection{ BaseConnection: c, } @@ -328,7 +332,7 @@ func TestIdleConnections(t *testing.T) { Username: username, }, } - c := NewBaseConnection(sshConn1.id+"_1", ProtocolSFTP, "", user) + c := NewBaseConnection(sshConn1.id+"_1", ProtocolSFTP, "", "", user) c.lastActivity = time.Now().Add(-24 * time.Hour).UnixNano() fakeConn := &fakeConnection{ BaseConnection: c, @@ -340,7 +344,7 @@ func TestIdleConnections(t *testing.T) { Connections.AddSSHConnection(sshConn1) Connections.Add(fakeConn) assert.Equal(t, Connections.GetActiveSessions(username), 1) - c = NewBaseConnection(sshConn2.id+"_1", ProtocolSSH, "", user) + c = NewBaseConnection(sshConn2.id+"_1", ProtocolSSH, "", "", user) fakeConn = &fakeConnection{ BaseConnection: c, } @@ -348,7 +352,7 @@ func TestIdleConnections(t *testing.T) { Connections.Add(fakeConn) assert.Equal(t, Connections.GetActiveSessions(username), 2) - cFTP := NewBaseConnection("id2", ProtocolFTP, "", dataprovider.User{}) + cFTP := NewBaseConnection("id2", ProtocolFTP, "", "", dataprovider.User{}) cFTP.lastActivity = time.Now().UnixNano() fakeConn = &fakeConnection{ BaseConnection: cFTP, @@ -388,7 +392,7 @@ func TestIdleConnections(t *testing.T) { } func TestCloseConnection(t *testing.T) { - c := NewBaseConnection("id", ProtocolSFTP, "", dataprovider.User{}) + c := NewBaseConnection("id", ProtocolSFTP, "", "", dataprovider.User{}) fakeConn := &fakeConnection{ BaseConnection: c, } @@ -404,7 +408,7 @@ func TestCloseConnection(t *testing.T) { } func TestSwapConnection(t *testing.T) { - c := NewBaseConnection("id", ProtocolFTP, "", dataprovider.User{}) + c := NewBaseConnection("id", ProtocolFTP, "", "", dataprovider.User{}) fakeConn := &fakeConnection{ BaseConnection: c, } @@ -412,7 +416,7 @@ func TestSwapConnection(t *testing.T) { if assert.Len(t, Connections.GetStats(), 1) { assert.Equal(t, "", Connections.GetStats()[0].Username) } - c = NewBaseConnection("id", ProtocolFTP, "", dataprovider.User{ + c = NewBaseConnection("id", ProtocolFTP, "", "", dataprovider.User{ BaseUser: sdk.BaseUser{ Username: userTestUsername, }, @@ -453,7 +457,7 @@ func TestConnectionStatus(t *testing.T) { }, } fs := vfs.NewOsFs("", os.TempDir(), "") - c1 := NewBaseConnection("id1", ProtocolSFTP, "", user) + c1 := NewBaseConnection("id1", ProtocolSFTP, "", "", user) fakeConn1 := &fakeConnection{ BaseConnection: c1, } @@ -461,12 +465,12 @@ func TestConnectionStatus(t *testing.T) { t1.BytesReceived = 123 t2 := NewBaseTransfer(nil, c1, nil, "/p2", "/p2", "/r2", TransferDownload, 0, 0, 0, true, fs) t2.BytesSent = 456 - c2 := NewBaseConnection("id2", ProtocolSSH, "", user) + c2 := NewBaseConnection("id2", ProtocolSSH, "", "", user) fakeConn2 := &fakeConnection{ BaseConnection: c2, command: "md5sum", } - c3 := NewBaseConnection("id3", ProtocolWebDAV, "", user) + c3 := NewBaseConnection("id3", ProtocolWebDAV, "", "", user) fakeConn3 := &fakeConnection{ BaseConnection: c3, command: "PROPFIND", @@ -707,7 +711,7 @@ func TestCachedFs(t *testing.T) { HomeDir: filepath.Clean(os.TempDir()), }, } - conn := NewBaseConnection("id", ProtocolSFTP, "", user) + conn := NewBaseConnection("id", ProtocolSFTP, "", "", user) // changing the user should not affect the connection user.HomeDir = filepath.Join(os.TempDir(), "temp") err := os.Mkdir(user.HomeDir, os.ModePerm) diff --git a/common/connection.go b/common/connection.go index 9add0ea3..464c333f 100644 --- a/common/connection.go +++ b/common/connection.go @@ -33,13 +33,14 @@ type BaseConnection struct { startTime time.Time protocol string remoteAddr string + localAddr string sync.RWMutex transferID uint64 activeTransfers []ActiveTransfer } // NewBaseConnection returns a new BaseConnection -func NewBaseConnection(id, protocol, remoteAddr string, user dataprovider.User) *BaseConnection { +func NewBaseConnection(id, protocol, localAddr, remoteAddr string, user dataprovider.User) *BaseConnection { connID := id if util.IsStringInSlice(protocol, supportedProtocols) { connID = fmt.Sprintf("%v_%v", protocol, id) @@ -49,6 +50,7 @@ func NewBaseConnection(id, protocol, remoteAddr string, user dataprovider.User) User: user, startTime: time.Now(), protocol: protocol, + localAddr: localAddr, remoteAddr: remoteAddr, lastActivity: time.Now().UnixNano(), transferID: 0, @@ -242,7 +244,8 @@ func (c *BaseConnection) CreateDir(virtualPath string) error { } vfs.SetPathPermissions(fs, fsPath, c.User.GetUID(), c.User.GetGID()) - logger.CommandLog(mkdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, c.remoteAddr) + logger.CommandLog(mkdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, + c.localAddr, c.remoteAddr) ExecuteActionNotification(&c.User, operationMkdir, fsPath, virtualPath, "", "", c.protocol, 0, nil) return nil } @@ -276,7 +279,8 @@ func (c *BaseConnection) RemoveFile(fs vfs.Fs, fsPath, virtualPath string, info } } - logger.CommandLog(removeLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, c.remoteAddr) + logger.CommandLog(removeLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, + c.localAddr, c.remoteAddr) if info.Mode()&os.ModeSymlink == 0 { vfolder, err := c.User.GetVirtualFolderForPath(path.Dir(virtualPath)) if err == nil { @@ -347,7 +351,8 @@ func (c *BaseConnection) RemoveDir(virtualPath string) error { return c.GetFsError(fs, err) } - logger.CommandLog(rmdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, c.remoteAddr) + logger.CommandLog(rmdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, + c.localAddr, c.remoteAddr) ExecuteActionNotification(&c.User, operationRmdir, fsPath, virtualPath, "", "", c.protocol, 0, nil) return nil } @@ -408,7 +413,7 @@ func (c *BaseConnection) Rename(virtualSourcePath, virtualTargetPath string) err vfs.SetPathPermissions(fsDst, fsTargetPath, c.User.GetUID(), c.User.GetGID()) c.updateQuotaAfterRename(fsDst, virtualSourcePath, virtualTargetPath, fsTargetPath, initialSize) //nolint:errcheck logger.CommandLog(renameLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1, - "", "", "", -1, c.remoteAddr) + "", "", "", -1, c.localAddr, c.remoteAddr) ExecuteActionNotification(&c.User, operationRename, fsSourcePath, virtualSourcePath, fsTargetPath, "", c.protocol, 0, nil) return nil @@ -445,7 +450,7 @@ func (c *BaseConnection) CreateSymlink(virtualSourcePath, virtualTargetPath stri return c.GetFsError(fs, err) } logger.CommandLog(symlinkLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1, "", - "", "", -1, c.remoteAddr) + "", "", -1, c.localAddr, c.remoteAddr) return nil } @@ -511,7 +516,7 @@ func (c *BaseConnection) handleChmod(fs vfs.Fs, fsPath, pathForPerms string, att return c.GetFsError(fs, err) } logger.CommandLog(chmodLogSender, fsPath, "", c.User.Username, attributes.Mode.String(), c.ID, c.protocol, - -1, -1, "", "", "", -1, c.remoteAddr) + -1, -1, "", "", "", -1, c.localAddr, c.remoteAddr) return nil } @@ -528,7 +533,7 @@ func (c *BaseConnection) handleChown(fs vfs.Fs, fsPath, pathForPerms string, att return c.GetFsError(fs, err) } logger.CommandLog(chownLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, attributes.UID, attributes.GID, - "", "", "", -1, c.remoteAddr) + "", "", "", -1, c.localAddr, c.remoteAddr) return nil } @@ -547,7 +552,7 @@ func (c *BaseConnection) handleChtimes(fs vfs.Fs, fsPath, pathForPerms string, a accessTimeString := attributes.Atime.Format(chtimesFormat) modificationTimeString := attributes.Mtime.Format(chtimesFormat) logger.CommandLog(chtimesLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, - accessTimeString, modificationTimeString, "", -1, c.remoteAddr) + accessTimeString, modificationTimeString, "", -1, c.localAddr, c.remoteAddr) return nil } @@ -581,7 +586,7 @@ func (c *BaseConnection) SetStat(virtualPath string, attributes *StatAttributes) return c.GetFsError(fs, err) } logger.CommandLog(truncateLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", - "", attributes.Size, c.remoteAddr) + "", attributes.Size, c.localAddr, c.remoteAddr) } return nil diff --git a/common/connection_test.go b/common/connection_test.go index 4971d01d..8811f40c 100644 --- a/common/connection_test.go +++ b/common/connection_test.go @@ -65,7 +65,7 @@ func TestRemoveErrors(t *testing.T) { user.Permissions = make(map[string][]string) user.Permissions["/"] = []string{dataprovider.PermAny} fs := vfs.NewOsFs("", os.TempDir(), "") - conn := NewBaseConnection("", ProtocolFTP, "", user) + conn := NewBaseConnection("", ProtocolFTP, "", "", user) err := conn.IsRemoveDirAllowed(fs, mappedPath, "/virtualpath1") if assert.Error(t, err) { assert.Contains(t, err.Error(), "permission denied") @@ -88,7 +88,7 @@ func TestSetStatMode(t *testing.T) { user.Permissions = make(map[string][]string) user.Permissions["/"] = []string{dataprovider.PermAny} fs := newMockOsFs(true, "", user.GetHomeDir()) - conn := NewBaseConnection("", ProtocolWebDAV, "", user) + conn := NewBaseConnection("", ProtocolWebDAV, "", "", user) err := conn.handleChmod(fs, fakePath, fakePath, nil) assert.NoError(t, err) err = conn.handleChown(fs, fakePath, fakePath, nil) @@ -105,14 +105,14 @@ func TestSetStatMode(t *testing.T) { func TestRecursiveRenameWalkError(t *testing.T) { fs := vfs.NewOsFs("", os.TempDir(), "") - conn := NewBaseConnection("", ProtocolWebDAV, "", dataprovider.User{}) + conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{}) err := conn.checkRecursiveRenameDirPermissions(fs, fs, "/source", "/target") assert.ErrorIs(t, err, os.ErrNotExist) } func TestCrossRenameFsErrors(t *testing.T) { fs := vfs.NewOsFs("", os.TempDir(), "") - conn := NewBaseConnection("", ProtocolWebDAV, "", dataprovider.User{}) + conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{}) res := conn.hasSpaceForCrossRename(fs, vfs.QuotaCheckResult{}, 1, "missingsource") assert.False(t, res) if runtime.GOOS != osWindows { @@ -143,7 +143,7 @@ func TestRenameVirtualFolders(t *testing.T) { VirtualPath: vdir, }) fs := vfs.NewOsFs("", os.TempDir(), "") - conn := NewBaseConnection("", ProtocolFTP, "", u) + conn := NewBaseConnection("", ProtocolFTP, "", "", u) res := conn.isRenamePermitted(fs, fs, "source", "target", vdir, "vdirtarget", nil) assert.False(t, res) } @@ -180,7 +180,7 @@ func TestUpdateQuotaAfterRename(t *testing.T) { assert.NoError(t, err) fs, err := user.GetFilesystem("id") assert.NoError(t, err) - c := NewBaseConnection("", ProtocolSFTP, "", user) + c := NewBaseConnection("", ProtocolSFTP, "", "", user) request := sftp.NewRequest("Rename", "/testfile") if runtime.GOOS != osWindows { request.Filepath = "/dir" @@ -225,7 +225,7 @@ func TestUpdateQuotaAfterRename(t *testing.T) { func TestErrorsMapping(t *testing.T) { fs := vfs.NewOsFs("", os.TempDir(), "") - conn := NewBaseConnection("", ProtocolSFTP, "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}}) + conn := NewBaseConnection("", ProtocolSFTP, "", "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}}) for _, protocol := range supportedProtocols { conn.SetProtocol(protocol) err := conn.GetFsError(fs, os.ErrNotExist) @@ -291,7 +291,7 @@ func TestMaxWriteSize(t *testing.T) { } fs, err := user.GetFilesystem("123") assert.NoError(t, err) - conn := NewBaseConnection("", ProtocolFTP, "", user) + conn := NewBaseConnection("", ProtocolFTP, "", "", user) quotaResult := vfs.QuotaCheckResult{ HasSpace: true, } diff --git a/common/protocol_test.go b/common/protocol_test.go index 1fd37005..a6efe153 100644 --- a/common/protocol_test.go +++ b/common/protocol_test.go @@ -1927,7 +1927,7 @@ func TestFsPermissionErrors(t *testing.T) { func TestResolvePathError(t *testing.T) { u := getTestUser() u.HomeDir = "relative_path" - conn := common.NewBaseConnection("", common.ProtocolFTP, "", u) + conn := common.NewBaseConnection("", common.ProtocolFTP, "", "", u) testPath := "apath" _, err := conn.ListDir(testPath) assert.Error(t, err) @@ -2404,16 +2404,16 @@ func TestSFTPLoopError(t *testing.T) { user1.VirtualFolders[0].FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword) user2.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword) - conn := common.NewBaseConnection("", common.ProtocolWebDAV, "", user1) + conn := common.NewBaseConnection("", common.ProtocolWebDAV, "", "", user1) _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath) assert.ErrorIs(t, err, os.ErrPermission) - conn = common.NewBaseConnection("", common.ProtocolSFTP, "", user1) + conn = common.NewBaseConnection("", common.ProtocolSFTP, "", "", user1) _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath) if assert.Error(t, err) { assert.Contains(t, err.Error(), "SFTP loop") } - conn = common.NewBaseConnection("", common.ProtocolFTP, "", user1) + conn = common.NewBaseConnection("", common.ProtocolFTP, "", "", user1) _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath) if assert.Error(t, err) { assert.Contains(t, err.Error(), "SFTP loop") @@ -2650,7 +2650,7 @@ func TestProxyProtocol(t *testing.T) { } func TestSetProtocol(t *testing.T) { - conn := common.NewBaseConnection("id", "sshd_exec", "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}}) + conn := common.NewBaseConnection("id", "sshd_exec", "", "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}}) conn.SetProtocol(common.ProtocolSCP) require.Equal(t, "SCP_id", conn.GetID()) } @@ -2660,7 +2660,7 @@ func TestGetFsError(t *testing.T) { u.FsConfig.Provider = sdk.GCSFilesystemProvider u.FsConfig.GCSConfig.Bucket = "test" u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials") - conn := common.NewBaseConnection("", common.ProtocolFTP, "", u) + conn := common.NewBaseConnection("", common.ProtocolFTP, "", "", u) _, _, err := conn.GetFsAndResolvedPath("/vpath") assert.Error(t, err) } diff --git a/common/transfer.go b/common/transfer.go index ed80c8e5..ed4e3ef1 100644 --- a/common/transfer.go +++ b/common/transfer.go @@ -236,7 +236,7 @@ func (t *BaseTransfer) Close() error { elapsed := time.Since(t.start).Nanoseconds() / 1000000 if t.transferType == TransferDownload { logger.TransferLog(downloadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesSent), t.Connection.User.Username, - t.Connection.ID, t.Connection.protocol, t.Connection.remoteAddr) + t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr) ExecuteActionNotification(&t.Connection.User, operationDownload, t.fsPath, t.requestPath, "", "", t.Connection.protocol, atomic.LoadInt64(&t.BytesSent), t.ErrTransfer) } else { @@ -247,7 +247,7 @@ func (t *BaseTransfer) Close() error { t.Connection.Log(logger.LevelDebug, "uploaded file size %v", fileSize) t.updateQuota(numFiles, fileSize) logger.TransferLog(uploadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesReceived), t.Connection.User.Username, - t.Connection.ID, t.Connection.protocol, t.Connection.remoteAddr) + t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr) ExecuteActionNotification(&t.Connection.User, operationUpload, t.fsPath, t.requestPath, "", "", t.Connection.protocol, fileSize, t.ErrTransfer) } diff --git a/common/transfer_test.go b/common/transfer_test.go index 4b4d3db2..1c76b6d7 100644 --- a/common/transfer_test.go +++ b/common/transfer_test.go @@ -17,7 +17,7 @@ import ( ) func TestTransferUpdateQuota(t *testing.T) { - conn := NewBaseConnection("", ProtocolSFTP, "", dataprovider.User{}) + conn := NewBaseConnection("", ProtocolSFTP, "", "", dataprovider.User{}) transfer := BaseTransfer{ Connection: conn, transferType: TransferUpload, @@ -64,7 +64,7 @@ func TestTransferThrottling(t *testing.T) { // some tolerance wantedUploadElapsed -= wantedDownloadElapsed / 10 wantedDownloadElapsed -= wantedDownloadElapsed / 10 - conn := NewBaseConnection("id", ProtocolSCP, "", u) + conn := NewBaseConnection("id", ProtocolSCP, "", "", u) transfer := NewBaseTransfer(nil, conn, nil, "", "", "", TransferUpload, 0, 0, 0, true, fs) transfer.BytesReceived = testFileSize transfer.Connection.UpdateLastActivity() @@ -100,7 +100,7 @@ func TestRealPath(t *testing.T) { u.Permissions["/"] = []string{dataprovider.PermAny} file, err := os.Create(testFile) require.NoError(t, err) - conn := NewBaseConnection(fs.ConnectionID(), ProtocolSFTP, "", u) + conn := NewBaseConnection(fs.ConnectionID(), ProtocolSFTP, "", "", u) transfer := NewBaseTransfer(file, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 0, 0, true, fs) rPath := transfer.GetRealFsPath(testFile) assert.Equal(t, testFile, rPath) @@ -137,7 +137,7 @@ func TestTruncate(t *testing.T) { } _, err = file.Write([]byte("hello")) assert.NoError(t, err) - conn := NewBaseConnection(fs.ConnectionID(), ProtocolSFTP, "", u) + conn := NewBaseConnection(fs.ConnectionID(), ProtocolSFTP, "", "", u) transfer := NewBaseTransfer(file, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 5, 100, false, fs) err = conn.SetStat("/transfer_test_file", &StatAttributes{ @@ -201,7 +201,7 @@ func TestTransferErrors(t *testing.T) { if !assert.NoError(t, err) { assert.FailNow(t, "unable to open test file") } - conn := NewBaseConnection("id", ProtocolSFTP, "", u) + conn := NewBaseConnection("id", ProtocolSFTP, "", "", u) transfer := NewBaseTransfer(file, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 0, 0, true, fs) assert.Nil(t, transfer.cancelFn) assert.Equal(t, testFile, transfer.GetFsPath()) @@ -272,7 +272,7 @@ func TestRemovePartialCryptoFile(t *testing.T) { HomeDir: os.TempDir(), }, } - conn := NewBaseConnection(fs.ConnectionID(), ProtocolSFTP, "", u) + conn := NewBaseConnection(fs.ConnectionID(), ProtocolSFTP, "", "", u) transfer := NewBaseTransfer(nil, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 0, 0, true, fs) transfer.ErrTransfer = errors.New("test error") _, err = transfer.getUploadFileSize() diff --git a/dataprovider/dataprovider.go b/dataprovider/dataprovider.go index 91da042d..a21e87ef 100644 --- a/dataprovider/dataprovider.go +++ b/dataprovider/dataprovider.go @@ -1532,7 +1532,6 @@ func isPasswordOK(user *User, password string) (bool, error) { } } else if strings.HasPrefix(user.Password, bcryptPwdPrefix) { if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil { - providerLog(logger.LevelWarn, "error comparing password with bcrypt hash: %v", err) return match, ErrInvalidCredentials } match = true @@ -1583,20 +1582,24 @@ func checkUserAndPass(user *User, password, ip, protocol string) (User, error) { if !user.Filters.Hooks.CheckPasswordDisabled { hookResponse, err := executeCheckPasswordHook(user.Username, password, ip, protocol) if err != nil { - providerLog(logger.LevelDebug, "error executing check password hook: %v", err) + providerLog(logger.LevelDebug, "error executing check password hook for user %#v, ip %v, protocol %v: %v", + user.Username, ip, protocol, err) return *user, errors.New("unable to check credentials") } switch hookResponse.Status { case -1: // no hook configured case 1: - providerLog(logger.LevelDebug, "password accepted by check password hook") + providerLog(logger.LevelDebug, "password accepted by check password hook for user %#v, ip %v, protocol %v", + user.Username, ip, protocol) return *user, nil case 2: - providerLog(logger.LevelDebug, "partial success from check password hook") + providerLog(logger.LevelDebug, "partial success from check password hook for user %#v, ip %v, protocol %v", + user.Username, ip, protocol) password = hookResponse.ToVerify default: - providerLog(logger.LevelDebug, "password rejected by check password hook, status: %v", hookResponse.Status) + providerLog(logger.LevelDebug, "password rejected by check password hook for user %#v, ip %v, protocol %v, status: %v", + user.Username, ip, protocol, hookResponse.Status) return *user, ErrInvalidCredentials } } @@ -2116,7 +2119,8 @@ func executePreLoginHook(username, loginMethod, ip, protocol string) (User, erro startTime := time.Now() out, err := getPreLoginHookResponse(loginMethod, ip, protocol, userAsJSON) if err != nil { - return u, fmt.Errorf("pre-login hook error: %v, elapsed %v", err, time.Since(startTime)) + return u, fmt.Errorf("pre-login hook error: %v, username %#v, ip %v, protocol %v elapsed %v", + err, username, ip, protocol, time.Since(startTime)) } providerLog(logger.LevelDebug, "pre-login hook completed, elapsed: %v", time.Since(startTime)) if util.IsByteArrayEmpty(out) { @@ -2209,8 +2213,8 @@ func ExecutePostLoginHook(user *User, loginMethod, ip, protocol string, err erro respCode = resp.StatusCode resp.Body.Close() } - providerLog(logger.LevelDebug, "post login hook executed, response code: %v, elapsed: %v err: %v", - respCode, time.Since(startTime), err) + providerLog(logger.LevelDebug, "post login hook executed for user %#v, ip %v, protocol %v, response code: %v, elapsed: %v err: %v", + user.Username, ip, protocol, respCode, time.Since(startTime), err) return } ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) @@ -2224,7 +2228,8 @@ func ExecutePostLoginHook(user *User, loginMethod, ip, protocol string, err erro fmt.Sprintf("SFTPGO_LOGIND_PROTOCOL=%v", protocol)) startTime := time.Now() err = cmd.Run() - providerLog(logger.LevelDebug, "post login hook executed, elapsed %v err: %v", time.Since(startTime), err) + providerLog(logger.LevelDebug, "post login hook executed for user %#v, ip %v, protocol %v, elapsed %v err: %v", + user.Username, ip, protocol, time.Since(startTime), err) }() } @@ -2312,9 +2317,9 @@ func doExternalAuth(username, password string, pubKey []byte, keyboardInteractiv startTime := time.Now() out, err := getExternalAuthResponse(username, password, pkey, keyboardInteractive, ip, protocol, tlsCert, userAsJSON) if err != nil { - return user, fmt.Errorf("external auth error: %v, elapsed: %v", err, time.Since(startTime)) + return user, fmt.Errorf("external auth error for user %#v: %v, elapsed: %v", username, err, time.Since(startTime)) } - providerLog(logger.LevelDebug, "external auth completed, elapsed: %v", time.Since(startTime)) + providerLog(logger.LevelDebug, "external auth completed for user %#v, elapsed: %v", username, time.Since(startTime)) if util.IsByteArrayEmpty(out) { providerLog(logger.LevelDebug, "empty response from external hook, no modification requested for user %#v id: %v", username, u.ID) diff --git a/docs/logs.md b/docs/logs.md index d45c9570..72dce4ea 100644 --- a/docs/logs.md +++ b/docs/logs.md @@ -13,6 +13,7 @@ The logs can be divided into the following categories: - `sender` string. `Upload` or `Download` - `time` string. Date/time with millisecond precision - `level` string + - `local_addr` string. IP/port of the local address the connection arrived on. For example `127.0.0.1:1234` - `remote_addr` string. IP and, optionally, port of the remote client. For example `127.0.0.1:1234` or `127.0.0.1` - `elapsed_ms`, int64. Elapsed time, as milliseconds, for the upload/download - `size_bytes`, int64. Size, as bytes, of the download/upload @@ -23,6 +24,7 @@ The logs can be divided into the following categories: - **"command logs"**, SFTP/SCP command logs: - `sender` string. `Rename`, `Rmdir`, `Mkdir`, `Symlink`, `Remove`, `Chmod`, `Chown`, `Chtimes`, `Truncate`, `SSHCommand` - `level` string + - `local_addr` string. IP/port of the local address the connection arrived on. For example `127.0.0.1:1234` - `remote_addr` string. IP and, optionally, port of the remote client. For example `127.0.0.1:1234` or `127.0.0.1` - `username`, string - `file_path` string @@ -39,6 +41,7 @@ The logs can be divided into the following categories: - **"http logs"**, REST API logs: - `sender` string. `httpd` - `level` string + - `local_addr` string. IP/port of the local address the connection arrived on. For example `127.0.0.1:1234` - `remote_addr` string. IP and, optionally, port of the remote client. For example `127.0.0.1:1234` or `127.0.0.1` - `proto` string, for example `HTTP/1.1` - `method` string. HTTP method (`GET`, `POST`, `PUT`, `DELETE` etc.) diff --git a/ftpd/handler.go b/ftpd/handler.go index 7af7f9d3..629ae52c 100644 --- a/ftpd/handler.go +++ b/ftpd/handler.go @@ -40,7 +40,12 @@ func (c *Connection) GetClientVersion() string { return "Unknown" } -// GetRemoteAddress return the connected client's address +// GetLocalAddress returns local connection address +func (c *Connection) GetLocalAddress() string { + return c.clientContext.LocalAddr().String() +} + +// GetRemoteAddress returns the connected client's address func (c *Connection) GetRemoteAddress() string { return c.clientContext.RemoteAddr().String() } diff --git a/ftpd/internal_test.go b/ftpd/internal_test.go index 5767151b..d612cfff 100644 --- a/ftpd/internal_test.go +++ b/ftpd/internal_test.go @@ -516,7 +516,7 @@ func TestClientVersion(t *testing.T) { connID := fmt.Sprintf("2_%v", mockCC.ID()) user := dataprovider.User{} connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user), clientContext: mockCC, } common.Connections.Add(connection) @@ -533,7 +533,7 @@ func TestDriverMethodsNotImplemented(t *testing.T) { connID := fmt.Sprintf("2_%v", mockCC.ID()) user := dataprovider.User{} connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user), clientContext: mockCC, } _, err := connection.Create("") @@ -560,7 +560,7 @@ func TestResolvePathErrors(t *testing.T) { mockCC := mockFTPClientContext{} connID := fmt.Sprintf("%v", mockCC.ID()) connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user), clientContext: mockCC, } err := connection.Mkdir("", os.ModePerm) @@ -625,7 +625,7 @@ func TestUploadFileStatError(t *testing.T) { connID := fmt.Sprintf("%v", mockCC.ID()) fs := vfs.NewOsFs(connID, user.HomeDir, "") connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user), clientContext: mockCC, } testFile := filepath.Join(user.HomeDir, "test", "testfile") @@ -655,7 +655,7 @@ func TestAVBLErrors(t *testing.T) { mockCC := mockFTPClientContext{} connID := fmt.Sprintf("%v", mockCC.ID()) connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user), clientContext: mockCC, } _, err := connection.GetAvailableSpace("/") @@ -678,7 +678,7 @@ func TestUploadOverwriteErrors(t *testing.T) { connID := fmt.Sprintf("%v", mockCC.ID()) fs := newMockOsFs(nil, nil, false, connID, user.GetHomeDir()) connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user), clientContext: mockCC, } flags := 0 @@ -734,7 +734,7 @@ func TestTransferErrors(t *testing.T) { connID := fmt.Sprintf("%v", mockCC.ID()) fs := newMockOsFs(nil, nil, false, connID, user.GetHomeDir()) connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user), clientContext: mockCC, } baseTransfer := common.NewBaseTransfer(file, connection.BaseConnection, nil, file.Name(), file.Name(), testfile, diff --git a/ftpd/server.go b/ftpd/server.go index aa048891..8419b80f 100644 --- a/ftpd/server.go +++ b/ftpd/server.go @@ -156,8 +156,9 @@ func (s *Server) ClientConnected(cc ftpserver.ClientContext) (string, error) { connID := fmt.Sprintf("%v_%v", s.ID, cc.ID()) user := dataprovider.User{} connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, cc.RemoteAddr().String(), user), - clientContext: cc, + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, cc.LocalAddr().String(), + cc.RemoteAddr().String(), user), + clientContext: cc, } common.Connections.Add(connection) return s.initialMsg, nil @@ -336,8 +337,9 @@ func (s *Server) validateUser(user dataprovider.User, cc ftpserver.ClientContext return nil, common.ErrInternalFailure } connection := &Connection{ - BaseConnection: common.NewBaseConnection(fmt.Sprintf("%v_%v", s.ID, cc.ID()), common.ProtocolFTP, remoteAddr, user), - clientContext: cc, + BaseConnection: common.NewBaseConnection(fmt.Sprintf("%v_%v", s.ID, cc.ID()), common.ProtocolFTP, + cc.LocalAddr().String(), remoteAddr, user), + clientContext: cc, } err = common.Connections.Swap(connection) if err != nil { diff --git a/httpd/api_http_user.go b/httpd/api_http_user.go index 71346e46..4ea20a19 100644 --- a/httpd/api_http_user.go +++ b/httpd/api_http_user.go @@ -37,8 +37,9 @@ func getUserConnection(w http.ResponseWriter, r *http.Request) (*Connection, err return nil, err } connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), - request: r, + BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, util.GetHTTPLocalAddress(r), + r.RemoteAddr, user), + request: r, } return connection, nil } diff --git a/httpd/handler.go b/httpd/handler.go index 9b7c0b32..eba6b41d 100644 --- a/httpd/handler.go +++ b/httpd/handler.go @@ -28,7 +28,12 @@ func (c *Connection) GetClientVersion() string { return "" } -// GetRemoteAddress return the connected client's address +// GetLocalAddress returns local connection address +func (c *Connection) GetLocalAddress() string { + return util.GetHTTPLocalAddress(c.request) +} + +// GetRemoteAddress returns the connected client's address func (c *Connection) GetRemoteAddress() string { if c.request != nil { return c.request.RemoteAddr diff --git a/httpd/httpd_test.go b/httpd/httpd_test.go index 5034522f..79773637 100644 --- a/httpd/httpd_test.go +++ b/httpd/httpd_test.go @@ -177,6 +177,10 @@ func (c *fakeConnection) GetCommand() string { return c.command } +func (c *fakeConnection) GetLocalAddress() string { + return "" +} + func (c *fakeConnection) GetRemoteAddress() string { return "" } @@ -2778,7 +2782,7 @@ func TestCloseActiveConnection(t *testing.T) { _, err := httpdtest.CloseConnection("non_existent_id", http.StatusNotFound) assert.NoError(t, err) user := getTestUser() - c := common.NewBaseConnection("connID", common.ProtocolSFTP, "", user) + c := common.NewBaseConnection("connID", common.ProtocolSFTP, "", "", user) fakeConn := &fakeConnection{ BaseConnection: c, } @@ -2791,12 +2795,12 @@ func TestCloseActiveConnection(t *testing.T) { func TestCloseConnectionAfterUserUpdateDelete(t *testing.T) { user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated) assert.NoError(t, err) - c := common.NewBaseConnection("connID", common.ProtocolFTP, "", user) + c := common.NewBaseConnection("connID", common.ProtocolFTP, "", "", user) fakeConn := &fakeConnection{ BaseConnection: c, } common.Connections.Add(fakeConn) - c1 := common.NewBaseConnection("connID1", common.ProtocolSFTP, "", user) + c1 := common.NewBaseConnection("connID1", common.ProtocolSFTP, "", "", user) fakeConn1 := &fakeConnection{ BaseConnection: c1, } @@ -3530,7 +3534,7 @@ func TestLoaddataMode(t *testing.T) { assert.Equal(t, int64(789), folder.LastQuotaUpdate) assert.Len(t, folder.Users, 0) - c := common.NewBaseConnection("connID", common.ProtocolFTP, "", user) + c := common.NewBaseConnection("connID", common.ProtocolFTP, "", "", user) fakeConn := &fakeConnection{ BaseConnection: c, } @@ -5060,7 +5064,7 @@ func TestWebClientMaxConnections(t *testing.T) { // now add a fake connection fs := vfs.NewOsFs("id", os.TempDir(), "") connection := &httpd.Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolHTTP, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolHTTP, "", "", user), } common.Connections.Add(connection) @@ -5198,7 +5202,7 @@ func TestMaxSessions(t *testing.T) { // now add a fake connection fs := vfs.NewOsFs("id", os.TempDir(), "") connection := &httpd.Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolHTTP, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolHTTP, "", "", user), } common.Connections.Add(connection) _, err = getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword) diff --git a/httpd/internal_test.go b/httpd/internal_test.go index 181fabaf..f1c3d52e 100644 --- a/httpd/internal_test.go +++ b/httpd/internal_test.go @@ -1211,7 +1211,7 @@ func TestCompressorAbortHandler(t *testing.T) { }() connection := &Connection{ - BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", dataprovider.User{}), + BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", dataprovider.User{}), request: nil, } renderCompressedFiles(&failingWriter{}, connection, "", nil) @@ -1226,7 +1226,7 @@ func TestZipErrors(t *testing.T) { user.Permissions = make(map[string][]string) user.Permissions["/"] = []string{dataprovider.PermAny} connection := &Connection{ - BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), + BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user), request: nil, } @@ -1442,7 +1442,7 @@ func TestConnection(t *testing.T) { user.Permissions = make(map[string][]string) user.Permissions["/"] = []string{dataprovider.PermAny} connection := &Connection{ - BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), + BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user), request: nil, } assert.Empty(t, connection.GetClientVersion()) @@ -1466,7 +1466,7 @@ func TestGetFileWriterErrors(t *testing.T) { user.Permissions = make(map[string][]string) user.Permissions["/"] = []string{dataprovider.PermAny} connection := &Connection{ - BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), + BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user), request: nil, } _, err := connection.getFileWriter("name") @@ -1482,7 +1482,7 @@ func TestGetFileWriterErrors(t *testing.T) { }, } connection = &Connection{ - BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), + BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user), request: nil, } _, err = connection.getFileWriter("/path") @@ -1499,7 +1499,7 @@ func TestHTTPDFile(t *testing.T) { user.Permissions = make(map[string][]string) user.Permissions["/"] = []string{dataprovider.PermAny} connection := &Connection{ - BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), + BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user), request: nil, } diff --git a/httpd/webclient.go b/httpd/webclient.go index 6a8be49f..92b82451 100644 --- a/httpd/webclient.go +++ b/httpd/webclient.go @@ -283,8 +283,9 @@ func handleWebClientDownloadZip(w http.ResponseWriter, r *http.Request) { return } connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), - request: r, + BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, util.GetHTTPLocalAddress(r), + r.RemoteAddr, user), + request: r, } common.Connections.Add(connection) defer common.Connections.Remove(connection.GetID()) @@ -326,8 +327,9 @@ func handleClientGetDirContents(w http.ResponseWriter, r *http.Request) { return } connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), - request: r, + BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, util.GetHTTPLocalAddress(r), + r.RemoteAddr, user), + request: r, } common.Connections.Add(connection) defer common.Connections.Remove(connection.GetID()) @@ -386,8 +388,9 @@ func handleClientGetFiles(w http.ResponseWriter, r *http.Request) { return } connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), - request: r, + BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, util.GetHTTPLocalAddress(r), + r.RemoteAddr, user), + request: r, } common.Connections.Add(connection) defer common.Connections.Remove(connection.GetID()) diff --git a/logger/logger.go b/logger/logger.go index 8ec740c2..f4b5c97a 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -259,10 +259,11 @@ func ErrorToConsole(format string, v ...interface{}) { } // TransferLog logs uploads or downloads -func TransferLog(operation, path string, elapsed int64, size int64, user, connectionID, protocol, remoteAddr string) { +func TransferLog(operation, path string, elapsed int64, size int64, user, connectionID, protocol, localAddr, remoteAddr string) { logger.Info(). Timestamp(). Str("sender", operation). + Str("local_addr", localAddr). Str("remote_addr", remoteAddr). Int64("elapsed_ms", elapsed). Int64("size_bytes", size). @@ -275,7 +276,7 @@ func TransferLog(operation, path string, elapsed int64, size int64, user, connec // CommandLog logs an SFTP/SCP/SSH command func CommandLog(command, path, target, user, fileMode, connectionID, protocol string, uid, gid int, atime, mtime, - sshCommand string, size int64, remoteAddr string) { + sshCommand string, size int64, localAddr, remoteAddr string) { logger.Info(). Timestamp(). Str("sender", command). diff --git a/logger/request_logger.go b/logger/request_logger.go index d825a102..bcfcdf7b 100644 --- a/logger/request_logger.go +++ b/logger/request_logger.go @@ -2,6 +2,7 @@ package logger import ( "fmt" + "net" "net/http" "time" @@ -40,6 +41,7 @@ func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry { } fields := map[string]interface{}{ + "local_addr": getLocalAddress(r), "remote_addr": r.RemoteAddr, "proto": r.Proto, "method": r.Method, @@ -77,3 +79,14 @@ func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) { Str("panic", fmt.Sprintf("%+v", v)). Send() } + +func getLocalAddress(r *http.Request) string { + if r == nil { + return "" + } + localAddr, ok := r.Context().Value(http.LocalAddrContextKey).(net.Addr) + if ok { + return localAddr.String() + } + return "" +} diff --git a/sftpd/handler.go b/sftpd/handler.go index 5a0ada38..300446b6 100644 --- a/sftpd/handler.go +++ b/sftpd/handler.go @@ -22,6 +22,7 @@ type Connection struct { ClientVersion string // Remote address for this connection RemoteAddr net.Addr + LocalAddr net.Addr channel io.ReadWriteCloser command string } @@ -31,7 +32,15 @@ func (c *Connection) GetClientVersion() string { return c.ClientVersion } -// GetRemoteAddress return the connected client's address +// GetLocalAddress returns local connection address +func (c *Connection) GetLocalAddress() string { + if c.LocalAddr == nil { + return "" + } + return c.LocalAddr.String() +} + +// GetRemoteAddress returns the connected client's address func (c *Connection) GetRemoteAddress() string { if c.RemoteAddr == nil { return "" diff --git a/sftpd/internal_test.go b/sftpd/internal_test.go index 7f2a1fbf..4b109db6 100644 --- a/sftpd/internal_test.go +++ b/sftpd/internal_test.go @@ -161,7 +161,7 @@ func TestUploadResumeInvalidOffset(t *testing.T) { }, } fs := vfs.NewOsFs("", os.TempDir(), "") - conn := common.NewBaseConnection("", common.ProtocolSFTP, "", user) + conn := common.NewBaseConnection("", common.ProtocolSFTP, "", "", user) baseTransfer := common.NewBaseTransfer(file, conn, nil, file.Name(), file.Name(), testfile, common.TransferUpload, 10, 0, 0, false, fs) transfer := newTransfer(baseTransfer, nil, nil, nil) _, err = transfer.WriteAt([]byte("test"), 0) @@ -191,7 +191,7 @@ func TestReadWriteErrors(t *testing.T) { }, } fs := vfs.NewOsFs("", os.TempDir(), "") - conn := common.NewBaseConnection("", common.ProtocolSFTP, "", user) + conn := common.NewBaseConnection("", common.ProtocolSFTP, "", "", user) baseTransfer := common.NewBaseTransfer(file, conn, nil, file.Name(), file.Name(), testfile, common.TransferDownload, 0, 0, 0, false, fs) transfer := newTransfer(baseTransfer, nil, nil, nil) err = file.Close() @@ -239,7 +239,7 @@ func TestReadWriteErrors(t *testing.T) { } func TestUnsupportedListOP(t *testing.T) { - conn := common.NewBaseConnection("", common.ProtocolSFTP, "", dataprovider.User{}) + conn := common.NewBaseConnection("", common.ProtocolSFTP, "", "", dataprovider.User{}) sftpConn := Connection{ BaseConnection: conn, } @@ -262,7 +262,7 @@ func TestTransferCancelFn(t *testing.T) { }, } fs := vfs.NewOsFs("", os.TempDir(), "") - conn := common.NewBaseConnection("", common.ProtocolSFTP, "", user) + conn := common.NewBaseConnection("", common.ProtocolSFTP, "", "", user) baseTransfer := common.NewBaseTransfer(file, conn, cancelFn, file.Name(), file.Name(), testfile, common.TransferDownload, 0, 0, 0, false, fs) transfer := newTransfer(baseTransfer, nil, nil, nil) @@ -286,7 +286,7 @@ func TestUploadFiles(t *testing.T) { fs := vfs.NewOsFs("123", os.TempDir(), "") u := dataprovider.User{} c := Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", u), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", u), } var flags sftp.FileOpenFlags flags.Write = true @@ -338,7 +338,7 @@ func TestWithInvalidHome(t *testing.T) { fs, err := u.GetFilesystem("123") assert.NoError(t, err) c := Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", u), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", u), } _, err = fs.ResolvePath("../upper_path") assert.Error(t, err, "tested path is not a home subdir") @@ -373,7 +373,7 @@ func TestSFTPGetUsedQuota(t *testing.T) { u.Permissions = make(map[string][]string) u.Permissions["/"] = []string{dataprovider.PermAny} connection := Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", u), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", u), } quotaResult := connection.HasSpace(false, false, "/") assert.False(t, quotaResult.HasSpace) @@ -470,7 +470,7 @@ func TestSSHCommandErrors(t *testing.T) { user.Permissions = make(map[string][]string) user.Permissions["/"] = []string{dataprovider.PermAny} connection := Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", "", user), channel: &mockSSHChannel, } cmd := sshCommand{ @@ -610,7 +610,7 @@ func TestCommandsWithExtensionsFilter(t *testing.T) { } connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", "", user), channel: &mockSSHChannel, } cmd := sshCommand{ @@ -673,7 +673,7 @@ func TestSSHCommandsRemoteFs(t *testing.T) { }, } connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), channel: &mockSSHChannel, } cmd := sshCommand{ @@ -720,7 +720,7 @@ func TestSSHCmdGetFsErrors(t *testing.T) { user.Permissions = map[string][]string{} user.Permissions["/"] = []string{dataprovider.PermAny} connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), channel: &mockSSHChannel, } cmd := sshCommand{ @@ -773,7 +773,7 @@ func TestGitVirtualFolders(t *testing.T) { }, } conn := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), } cmd := sshCommand{ command: "git-receive-pack", @@ -821,7 +821,7 @@ func TestRsyncOptions(t *testing.T) { }, } conn := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), } sshCmd := sshCommand{ command: "rsync", @@ -838,7 +838,7 @@ func TestRsyncOptions(t *testing.T) { user.Permissions = permissions conn = &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), } sshCmd = sshCommand{ command: "rsync", @@ -872,7 +872,7 @@ func TestSystemCommandSizeForPath(t *testing.T) { fs, err := user.GetFilesystem("123") assert.NoError(t, err) conn := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), } sshCmd := sshCommand{ command: "rsync", @@ -936,7 +936,7 @@ func TestSystemCommandErrors(t *testing.T) { fs, err := user.GetFilesystem("123") assert.NoError(t, err) connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), channel: &mockSSHChannel, } var sshCmd sshCommand @@ -1012,7 +1012,7 @@ func TestCommandGetFsError(t *testing.T) { }, } conn := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), } sshCmd := sshCommand{ command: "rsync", @@ -1030,7 +1030,7 @@ func TestCommandGetFsError(t *testing.T) { ReadError: nil, } conn = &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", user), channel: &mockSSHChannel, } scpCommand := scpCommand{ @@ -1124,7 +1124,7 @@ func TestSCPUploadError(t *testing.T) { user.Permissions["/"] = []string{dataprovider.PermAny} connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), channel: &mockSSHChannel, } scpCommand := scpCommand{ @@ -1163,7 +1163,7 @@ func TestSCPInvalidEndDir(t *testing.T) { StdErrBuffer: bytes.NewBuffer(stdErrBuf), } connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", dataprovider.User{ + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", dataprovider.User{ BaseUser: sdk.BaseUser{ HomeDir: os.TempDir(), }, @@ -1191,7 +1191,7 @@ func TestSCPParseUploadMessage(t *testing.T) { } fs := vfs.NewOsFs("", os.TempDir(), "") connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", dataprovider.User{ + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", dataprovider.User{ BaseUser: sdk.BaseUser{ HomeDir: os.TempDir(), }, @@ -1230,7 +1230,7 @@ func TestSCPProtocolMessages(t *testing.T) { WriteError: writeErr, } connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{}), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{}), channel: &mockSSHChannel, } scpCommand := scpCommand{ @@ -1291,7 +1291,7 @@ func TestSCPTestDownloadProtocolMessages(t *testing.T) { WriteError: writeErr, } connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{}), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{}), channel: &mockSSHChannel, } scpCommand := scpCommand{ @@ -1365,7 +1365,7 @@ func TestSCPCommandHandleErrors(t *testing.T) { assert.NoError(t, err) }() connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{}), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{}), channel: &mockSSHChannel, } scpCommand := scpCommand{ @@ -1406,7 +1406,7 @@ func TestSCPErrorsMockFs(t *testing.T) { }() connection := &Connection{ channel: &mockSSHChannel, - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", u), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", u), } scpCommand := scpCommand{ sshCommand: sshCommand{ @@ -1448,7 +1448,7 @@ func TestSCPRecursiveDownloadErrors(t *testing.T) { }() fs := vfs.NewOsFs("123", os.TempDir(), "") connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{ + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{ BaseUser: sdk.BaseUser{ HomeDir: os.TempDir(), }, @@ -1496,7 +1496,7 @@ func TestSCPRecursiveUploadErrors(t *testing.T) { WriteError: writeErr, } connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{}), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{}), channel: &mockSSHChannel, } scpCommand := scpCommand{ @@ -1537,7 +1537,7 @@ func TestSCPCreateDirs(t *testing.T) { fs, err := u.GetFilesystem("123") assert.NoError(t, err) connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", u), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", u), channel: &mockSSHChannel, } scpCommand := scpCommand{ @@ -1571,7 +1571,7 @@ func TestSCPDownloadFileData(t *testing.T) { } fs := vfs.NewOsFs("", os.TempDir(), "") connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}}), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}}), channel: &mockSSHChannelReadErr, } scpCommand := scpCommand{ @@ -1623,7 +1623,7 @@ func TestSCPUploadFiledata(t *testing.T) { } fs := vfs.NewOsFs("", os.TempDir(), "") connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", user), channel: &mockSSHChannel, } scpCommand := scpCommand{ @@ -1714,7 +1714,7 @@ func TestUploadError(t *testing.T) { } fs := vfs.NewOsFs("", os.TempDir(), "") connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", user), } testfile := "testfile" @@ -1762,7 +1762,7 @@ func TestTransferFailingReader(t *testing.T) { fs := newMockOsFs(nil, nil, true, "", os.TempDir()) connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), } request := sftp.NewRequest("Open", "afile.txt") @@ -1923,7 +1923,7 @@ func TestRecursiveCopyErrors(t *testing.T) { fs, err := user.GetFilesystem("123") assert.NoError(t, err) conn := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user), } sshCmd := sshCommand{ command: "sftpgo-copy", @@ -1974,7 +1974,7 @@ func TestRecoverer(t *testing.T) { c.AcceptInboundConnection(nil, nil) connID := "connectionID" connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, "", dataprovider.User{}), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, "", "", dataprovider.User{}), } c.handleSftpConnection(nil, connection) sshCmd := sshCommand{ diff --git a/sftpd/server.go b/sftpd/server.go index 64716a15..31b4e50b 100644 --- a/sftpd/server.go +++ b/sftpd/server.go @@ -437,20 +437,24 @@ func (c *Configuration) AcceptInboundConnection(conn net.Conn, config *ssh.Serve if string(req.Payload[4:]) == "sftp" { ok = true connection := Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, conn.RemoteAddr().String(), user), - ClientVersion: string(sconn.ClientVersion()), - RemoteAddr: conn.RemoteAddr(), - channel: channel, + BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, conn.LocalAddr().String(), + conn.RemoteAddr().String(), user), + ClientVersion: string(sconn.ClientVersion()), + RemoteAddr: conn.RemoteAddr(), + LocalAddr: conn.LocalAddr(), + channel: channel, } go c.handleSftpConnection(channel, &connection) } case "exec": // protocol will be set later inside processSSHCommand it could be SSH or SCP connection := Connection{ - BaseConnection: common.NewBaseConnection(connID, "sshd_exec", conn.RemoteAddr().String(), user), - ClientVersion: string(sconn.ClientVersion()), - RemoteAddr: conn.RemoteAddr(), - channel: channel, + BaseConnection: common.NewBaseConnection(connID, "sshd_exec", conn.LocalAddr().String(), + conn.RemoteAddr().String(), user), + ClientVersion: string(sconn.ClientVersion()), + RemoteAddr: conn.RemoteAddr(), + LocalAddr: conn.LocalAddr(), + channel: channel, } ok = processSSHCommand(req.Payload, &connection, c.EnabledSSHCommands) } diff --git a/sftpd/ssh_cmd.go b/sftpd/ssh_cmd.go index 28bfafc3..29e0c193 100644 --- a/sftpd/ssh_cmd.go +++ b/sftpd/ssh_cmd.go @@ -753,7 +753,8 @@ func (c *sshCommand) sendExitStatus(err error) { common.ProtocolSSH, 0, err) if err == nil { logger.CommandLog(sshCommandLogSender, cmdPath, targetPath, c.connection.User.Username, "", c.connection.ID, - common.ProtocolSSH, -1, -1, "", "", c.connection.command, -1, c.connection.GetRemoteAddress()) + common.ProtocolSSH, -1, -1, "", "", c.connection.command, -1, c.connection.GetLocalAddress(), + c.connection.GetRemoteAddress()) } } } diff --git a/sftpd/subsystem.go b/sftpd/subsystem.go index 1e4cd0b4..30ae4c5d 100644 --- a/sftpd/subsystem.go +++ b/sftpd/subsystem.go @@ -46,9 +46,10 @@ func ServeSubSystemConnection(user *dataprovider.User, connectionID string, read dataprovider.UpdateLastLogin(user) //nolint:errcheck connection := &Connection{ - BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolSFTP, "", *user), + BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolSFTP, "", "", *user), ClientVersion: "", RemoteAddr: &net.IPAddr{}, + LocalAddr: &net.IPAddr{}, channel: newSubsystemChannel(reader, writer), } common.Connections.Add(connection) diff --git a/util/util.go b/util/util.go index 5e6275ed..6dfb2da1 100644 --- a/util/util.go +++ b/util/util.go @@ -563,6 +563,19 @@ func GetRealIP(r *http.Request) string { return ip } +// GetHTTPLocalAddress returns the local address for an http.Request +// or empty if it cannot be determined +func GetHTTPLocalAddress(r *http.Request) string { + if r == nil { + return "" + } + localAddr, ok := r.Context().Value(http.LocalAddrContextKey).(net.Addr) + if ok { + return localAddr.String() + } + return "" +} + // ParseAllowedIPAndRanges returns a list of functions that allow to find if a func ParseAllowedIPAndRanges(allowed []string) ([]func(net.IP) bool, error) { res := make([]func(net.IP) bool, len(allowed)) diff --git a/webdavd/handler.go b/webdavd/handler.go index 6f098cc9..6f9ad9f8 100644 --- a/webdavd/handler.go +++ b/webdavd/handler.go @@ -31,7 +31,12 @@ func (c *Connection) GetClientVersion() string { return "" } -// GetRemoteAddress return the connected client's address +// GetLocalAddress returns local connection address +func (c *Connection) GetLocalAddress() string { + return util.GetHTTPLocalAddress(c.request) +} + +// GetRemoteAddress returns the connected client's address func (c *Connection) GetRemoteAddress() string { if c.request != nil { return c.request.RemoteAddr diff --git a/webdavd/internal_test.go b/webdavd/internal_test.go index 02fde1b2..a587f713 100644 --- a/webdavd/internal_test.go +++ b/webdavd/internal_test.go @@ -335,7 +335,7 @@ func TestOrderDirsToRemove(t *testing.T) { user := dataprovider.User{} fs := vfs.NewOsFs("id", os.TempDir(), "") connection := &Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), request: nil, } dirsToRemove := []objectMapping{} @@ -503,7 +503,7 @@ func TestResolvePathErrors(t *testing.T) { user.Permissions["/"] = []string{dataprovider.PermAny} fs := vfs.NewOsFs("connID", user.HomeDir, "") connection := &Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), } err := connection.Mkdir(ctx, "", os.ModePerm) @@ -574,7 +574,7 @@ func TestFileAccessErrors(t *testing.T) { user.Permissions["/"] = []string{dataprovider.PermAny} fs := vfs.NewOsFs("connID", user.HomeDir, "") connection := &Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), } missingPath := "missing path" fsMissingPath := filepath.Join(user.HomeDir, missingPath) @@ -637,7 +637,7 @@ func TestRemoveDirTree(t *testing.T) { user.Permissions["/"] = []string{dataprovider.PermAny} fs := vfs.NewOsFs("connID", user.HomeDir, "") connection := &Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), } vpath := path.Join("adir", "missing") @@ -690,7 +690,7 @@ func TestContentType(t *testing.T) { user.Permissions["/"] = []string{dataprovider.PermAny} fs := vfs.NewOsFs("connID", user.HomeDir, "") connection := &Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), } testFilePath := filepath.Join(user.HomeDir, testFile) ctx := context.Background() @@ -741,7 +741,7 @@ func TestTransferReadWriteErrors(t *testing.T) { user.Permissions["/"] = []string{dataprovider.PermAny} fs := vfs.NewOsFs("connID", user.HomeDir, "") connection := &Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), } testFilePath := filepath.Join(user.HomeDir, testFile) baseTransfer := common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, testFile, @@ -836,7 +836,7 @@ func TestTransferSeek(t *testing.T) { user.Permissions["/"] = []string{dataprovider.PermAny} fs := vfs.NewOsFs("connID", user.HomeDir, "") connection := &Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), } testFilePath := filepath.Join(user.HomeDir, testFile) testFileContents := []byte("content") diff --git a/webdavd/server.go b/webdavd/server.go index 7129d87b..fdeaab3b 100644 --- a/webdavd/server.go +++ b/webdavd/server.go @@ -201,8 +201,9 @@ func (s *webDavServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, requestStartKey, time.Now()) connection := &Connection{ - BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolWebDAV, r.RemoteAddr, user), - request: r, + BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolWebDAV, util.GetHTTPLocalAddress(r), + r.RemoteAddr, user), + request: r, } common.Connections.Add(connection) defer common.Connections.Remove(connection.GetID()) diff --git a/webdavd/webdavd_test.go b/webdavd/webdavd_test.go index e9e69caa..3b9cef63 100644 --- a/webdavd/webdavd_test.go +++ b/webdavd/webdavd_test.go @@ -1030,7 +1030,7 @@ func TestMaxConnections(t *testing.T) { // now add a fake connection fs := vfs.NewOsFs("id", os.TempDir(), "") connection := &webdavd.Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), } common.Connections.Add(connection) assert.Error(t, checkBasicFunc(client)) @@ -1085,7 +1085,7 @@ func TestMaxSessions(t *testing.T) { // now add a fake connection fs := vfs.NewOsFs("id", os.TempDir(), "") connection := &webdavd.Connection{ - BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), + BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user), } common.Connections.Add(connection) assert.Error(t, checkBasicFunc(client))