From 575bcf1f038ac3777014c6fb8fe9676749f9aead Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Tue, 1 Jun 2021 22:28:43 +0200 Subject: [PATCH] add remote address to transfer and commands logs --- common/actions_test.go | 2 +- common/common_test.go | 22 ++++++------- common/connection.go | 28 +++++++++------- common/connection_test.go | 16 ++++----- common/protocol_test.go | 12 +++---- common/transfer.go | 4 +-- common/transfer_test.go | 12 +++---- docs/logs.md | 4 ++- ftpd/internal_test.go | 14 ++++---- ftpd/server.go | 4 +-- httpd/httpd_test.go | 12 +++---- httpd/internal_test.go | 10 +++--- httpd/webclient.go | 6 ++-- logger/logger.go | 6 ++-- sftpd/handler.go | 3 ++ sftpd/internal_test.go | 68 +++++++++++++++++++-------------------- sftpd/server.go | 4 +-- sftpd/ssh_cmd.go | 7 ++-- sftpd/subsystem.go | 2 +- webdavd/internal_test.go | 14 ++++---- webdavd/server.go | 2 +- webdavd/webdavd_test.go | 4 +-- 22 files changed, 134 insertions(+), 122 deletions(-) diff --git a/common/actions_test.go b/common/actions_test.go index e40b7d56..f6e6713b 100644 --- a/common/actions_test.go +++ b/common/actions_test.go @@ -188,7 +188,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_test.go b/common/common_test.go index aa0453ce..a19cf2f6 100644 --- a/common/common_test.go +++ b/common/common_test.go @@ -239,7 +239,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, } @@ -310,7 +310,7 @@ func TestIdleConnections(t *testing.T) { user := dataprovider.User{ 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, @@ -322,7 +322,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, } @@ -330,7 +330,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, @@ -370,7 +370,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, } @@ -386,7 +386,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, } @@ -394,7 +394,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{ Username: userTestUsername, }) fakeConn = &fakeConnection{ @@ -431,7 +431,7 @@ func TestConnectionStatus(t *testing.T) { Username: username, } fs := vfs.NewOsFs("", os.TempDir(), "") - c1 := NewBaseConnection("id1", ProtocolSFTP, user) + c1 := NewBaseConnection("id1", ProtocolSFTP, "", user) fakeConn1 := &fakeConnection{ BaseConnection: c1, } @@ -439,12 +439,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", @@ -677,7 +677,7 @@ func TestCachedFs(t *testing.T) { user := dataprovider.User{ 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 de61ed58..6513a5ac 100644 --- a/common/connection.go +++ b/common/connection.go @@ -28,15 +28,16 @@ type BaseConnection struct { // user associated with this connection if any User dataprovider.User // start time for this connection - startTime time.Time - protocol string + startTime time.Time + protocol string + remoteAddr string sync.RWMutex transferID uint64 activeTransfers []ActiveTransfer } // NewBaseConnection returns a new BaseConnection -func NewBaseConnection(id, protocol string, user dataprovider.User) *BaseConnection { +func NewBaseConnection(id, protocol, remoteAddr string, user dataprovider.User) *BaseConnection { connID := id if utils.IsStringInSlice(protocol, supportedProtocols) { connID = fmt.Sprintf("%v_%v", protocol, id) @@ -46,6 +47,7 @@ func NewBaseConnection(id, protocol string, user dataprovider.User) *BaseConnect User: user, startTime: time.Now(), protocol: protocol, + remoteAddr: remoteAddr, lastActivity: time.Now().UnixNano(), transferID: 0, } @@ -238,7 +240,7 @@ 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) + logger.CommandLog(mkdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, c.remoteAddr) return nil } @@ -271,7 +273,7 @@ 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) + logger.CommandLog(removeLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, c.remoteAddr) if info.Mode()&os.ModeSymlink == 0 { vfolder, err := c.User.GetVirtualFolderForPath(path.Dir(virtualPath)) if err == nil { @@ -342,7 +344,7 @@ 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) + logger.CommandLog(rmdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1, c.remoteAddr) return nil } @@ -402,7 +404,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) + "", "", "", -1, c.remoteAddr) ExecuteActionNotification(&c.User, operationRename, fsSourcePath, virtualSourcePath, fsTargetPath, "", c.protocol, 0, nil) return nil @@ -438,7 +440,8 @@ func (c *BaseConnection) CreateSymlink(virtualSourcePath, virtualTargetPath stri c.Log(logger.LevelWarn, "failed to create symlink %#v -> %#v: %+v", fsSourcePath, fsTargetPath, err) return c.GetFsError(fs, err) } - logger.CommandLog(symlinkLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1) + logger.CommandLog(symlinkLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1, "", + "", "", -1, c.remoteAddr) return nil } @@ -504,7 +507,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) + -1, -1, "", "", "", -1, c.remoteAddr) return nil } @@ -521,7 +524,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) + "", "", "", -1, c.remoteAddr) return nil } @@ -540,7 +543,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) + accessTimeString, modificationTimeString, "", -1, c.remoteAddr) return nil } @@ -573,7 +576,8 @@ func (c *BaseConnection) SetStat(virtualPath string, attributes *StatAttributes) c.Log(logger.LevelWarn, "failed to truncate path %#v, size: %v, err: %+v", fsPath, attributes.Size, err) return c.GetFsError(fs, err) } - logger.CommandLog(truncateLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", attributes.Size) + logger.CommandLog(truncateLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", + "", attributes.Size, c.remoteAddr) } return nil diff --git a/common/connection_test.go b/common/connection_test.go index 422bb72d..a4c63a73 100644 --- a/common/connection_test.go +++ b/common/connection_test.go @@ -62,7 +62,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") @@ -83,7 +83,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) @@ -100,14 +100,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 { @@ -138,7 +138,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) } @@ -173,7 +173,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" @@ -218,7 +218,7 @@ func TestUpdateQuotaAfterRename(t *testing.T) { func TestErrorsMapping(t *testing.T) { fs := vfs.NewOsFs("", os.TempDir(), "") - conn := NewBaseConnection("", ProtocolSFTP, dataprovider.User{HomeDir: os.TempDir()}) + conn := NewBaseConnection("", ProtocolSFTP, "", dataprovider.User{HomeDir: os.TempDir()}) for _, protocol := range supportedProtocols { conn.SetProtocol(protocol) err := conn.GetFsError(fs, os.ErrNotExist) @@ -280,7 +280,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 726b5a69..c565d34d 100644 --- a/common/protocol_test.go +++ b/common/protocol_test.go @@ -1926,7 +1926,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) @@ -2399,16 +2399,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") @@ -2639,7 +2639,7 @@ func TestProxyProtocol(t *testing.T) { } func TestSetProtocol(t *testing.T) { - conn := common.NewBaseConnection("id", "sshd_exec", dataprovider.User{HomeDir: os.TempDir()}) + conn := common.NewBaseConnection("id", "sshd_exec", "", dataprovider.User{HomeDir: os.TempDir()}) conn.SetProtocol(common.ProtocolSCP) require.Equal(t, "SCP_id", conn.GetID()) } @@ -2649,7 +2649,7 @@ func TestGetFsError(t *testing.T) { u.FsConfig.Provider = vfs.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 3f2002c5..5acdcd01 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.ID, t.Connection.protocol, 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.ID, t.Connection.protocol, 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 66abce3d..dfcd6c5d 100644 --- a/common/transfer_test.go +++ b/common/transfer_test.go @@ -16,7 +16,7 @@ import ( ) func TestTransferUpdateQuota(t *testing.T) { - conn := NewBaseConnection("", ProtocolSFTP, dataprovider.User{}) + conn := NewBaseConnection("", ProtocolSFTP, "", dataprovider.User{}) transfer := BaseTransfer{ Connection: conn, transferType: TransferUpload, @@ -61,7 +61,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() @@ -95,7 +95,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) @@ -130,7 +130,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{ @@ -192,7 +192,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()) @@ -261,7 +261,7 @@ func TestRemovePartialCryptoFile(t *testing.T) { Username: "test", 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/docs/logs.md b/docs/logs.md index 0526ce34..d45c9570 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 + - `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 - `username`, string @@ -22,6 +23,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 + - `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 - `target_path` string @@ -37,7 +39,7 @@ The logs can be divided into the following categories: - **"http logs"**, REST API logs: - `sender` string. `httpd` - `level` string - - `remote_addr` string. IP and port of the remote client + - `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.) - `user_agent` string diff --git a/ftpd/internal_test.go b/ftpd/internal_test.go index afd1a547..b547e4f9 100644 --- a/ftpd/internal_test.go +++ b/ftpd/internal_test.go @@ -513,7 +513,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) @@ -530,7 +530,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("") @@ -555,7 +555,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) @@ -618,7 +618,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") @@ -646,7 +646,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("/") @@ -667,7 +667,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 @@ -721,7 +721,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 a15fb9b3..a47e6f58 100644 --- a/ftpd/server.go +++ b/ftpd/server.go @@ -155,7 +155,7 @@ 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, user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, cc.RemoteAddr().String(), user), clientContext: cc, } common.Connections.Add(connection) @@ -335,7 +335,7 @@ func (s *Server) validateUser(user dataprovider.User, cc ftpserver.ClientContext return nil, err } connection := &Connection{ - BaseConnection: common.NewBaseConnection(fmt.Sprintf("%v_%v", s.ID, cc.ID()), common.ProtocolFTP, user), + BaseConnection: common.NewBaseConnection(fmt.Sprintf("%v_%v", s.ID, cc.ID()), common.ProtocolFTP, remoteAddr, user), clientContext: cc, } err = common.Connections.Swap(connection) diff --git a/httpd/httpd_test.go b/httpd/httpd_test.go index bb10b0b0..d49f35fe 100644 --- a/httpd/httpd_test.go +++ b/httpd/httpd_test.go @@ -2540,7 +2540,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, } @@ -2553,12 +2553,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, } @@ -3236,7 +3236,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, } @@ -4628,7 +4628,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) @@ -4757,7 +4757,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 e98087de..4b047317 100644 --- a/httpd/internal_test.go +++ b/httpd/internal_test.go @@ -1146,7 +1146,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) @@ -1159,7 +1159,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, } @@ -1371,7 +1371,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()) @@ -1393,7 +1393,7 @@ func TestRenderDirError(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, } @@ -1412,7 +1412,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 2e18a415..ae02439f 100644 --- a/httpd/webclient.go +++ b/httpd/webclient.go @@ -286,7 +286,7 @@ func handleWebClientDownload(w http.ResponseWriter, r *http.Request) { } connection := &Connection{ - BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, user), + BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, r.RemoteAddr, user), request: r, } common.Connections.Add(connection) @@ -323,7 +323,7 @@ func handleClientGetDirContents(w http.ResponseWriter, r *http.Request) { } connection := &Connection{ - BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, user), + BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, r.RemoteAddr, user), request: r, } common.Connections.Add(connection) @@ -383,7 +383,7 @@ func handleClientGetFiles(w http.ResponseWriter, r *http.Request) { return } connection := &Connection{ - BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), request: r, } common.Connections.Add(connection) diff --git a/logger/logger.go b/logger/logger.go index 286d42a9..4cc0ae58 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -237,10 +237,11 @@ func ErrorToConsole(format string, v ...interface{}) { } // TransferLog logs uploads or downloads -func TransferLog(operation string, path string, elapsed int64, size int64, user string, connectionID string, protocol string) { +func TransferLog(operation, path string, elapsed int64, size int64, user, connectionID, protocol, remoteAddr string) { logger.Info(). Timestamp(). Str("sender", operation). + Str("remote_addr", remoteAddr). Int64("elapsed_ms", elapsed). Int64("size_bytes", size). Str("username", user). @@ -252,10 +253,11 @@ func TransferLog(operation string, path string, elapsed int64, size int64, user // 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) { + sshCommand string, size int64, remoteAddr string) { logger.Info(). Timestamp(). Str("sender", command). + Str("remote_addr", remoteAddr). Str("username", user). Str("file_path", path). Str("target_path", target). diff --git a/sftpd/handler.go b/sftpd/handler.go index 1417a498..a64a46b0 100644 --- a/sftpd/handler.go +++ b/sftpd/handler.go @@ -33,6 +33,9 @@ func (c *Connection) GetClientVersion() string { // GetRemoteAddress return the connected client's address func (c *Connection) GetRemoteAddress() string { + if c.RemoteAddr == nil { + return "" + } return c.RemoteAddr.String() } diff --git a/sftpd/internal_test.go b/sftpd/internal_test.go index 9ea5d652..27b267cf 100644 --- a/sftpd/internal_test.go +++ b/sftpd/internal_test.go @@ -158,7 +158,7 @@ func TestUploadResumeInvalidOffset(t *testing.T) { Username: "testuser", } 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) @@ -186,7 +186,7 @@ func TestReadWriteErrors(t *testing.T) { Username: "testuser", } 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() @@ -234,7 +234,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, } @@ -255,7 +255,7 @@ func TestTransferCancelFn(t *testing.T) { Username: "testuser", } 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) @@ -279,7 +279,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 @@ -331,7 +331,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") @@ -366,7 +366,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) @@ -463,7 +463,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{ @@ -601,7 +601,7 @@ func TestCommandsWithExtensionsFilter(t *testing.T) { } connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", user), channel: &mockSSHChannel, } cmd := sshCommand{ @@ -662,7 +662,7 @@ func TestSSHCommandsRemoteFs(t *testing.T) { }, } connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), channel: &mockSSHChannel, } cmd := sshCommand{ @@ -707,7 +707,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{ @@ -758,7 +758,7 @@ func TestGitVirtualFolders(t *testing.T) { HomeDir: os.TempDir(), } conn := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), } cmd := sshCommand{ command: "git-receive-pack", @@ -804,7 +804,7 @@ func TestRsyncOptions(t *testing.T) { HomeDir: os.TempDir(), } conn := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), } sshCmd := sshCommand{ command: "rsync", @@ -821,7 +821,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", @@ -853,7 +853,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", @@ -915,7 +915,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 @@ -991,7 +991,7 @@ func TestCommandGetFsError(t *testing.T) { }, } conn := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, user), + BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), } sshCmd := sshCommand{ command: "rsync", @@ -1009,7 +1009,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{ @@ -1101,7 +1101,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{ @@ -1140,7 +1140,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{ HomeDir: os.TempDir(), }), channel: &mockSSHChannel, @@ -1166,7 +1166,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{ HomeDir: os.TempDir(), }), channel: &mockSSHChannel, @@ -1203,7 +1203,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{ @@ -1264,7 +1264,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{ @@ -1338,7 +1338,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{ @@ -1379,7 +1379,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{ @@ -1421,7 +1421,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{ HomeDir: os.TempDir(), }), channel: &mockSSHChannel, @@ -1467,7 +1467,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{ @@ -1508,7 +1508,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{ @@ -1542,7 +1542,7 @@ func TestSCPDownloadFileData(t *testing.T) { } fs := vfs.NewOsFs("", os.TempDir(), "") connection := &Connection{ - BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, dataprovider.User{HomeDir: os.TempDir()}), + BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{HomeDir: os.TempDir()}), channel: &mockSSHChannelReadErr, } scpCommand := scpCommand{ @@ -1592,7 +1592,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{ @@ -1681,7 +1681,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" @@ -1725,7 +1725,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") @@ -1884,7 +1884,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", @@ -1933,7 +1933,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 fc7e954a..ba53441d 100644 --- a/sftpd/server.go +++ b/sftpd/server.go @@ -460,7 +460,7 @@ 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, user), + BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, conn.RemoteAddr().String(), user), ClientVersion: string(sconn.ClientVersion()), RemoteAddr: conn.RemoteAddr(), channel: channel, @@ -470,7 +470,7 @@ func (c *Configuration) AcceptInboundConnection(conn net.Conn, config *ssh.Serve case "exec": // protocol will be set later inside processSSHCommand it could be SSH or SCP connection := Connection{ - BaseConnection: common.NewBaseConnection(connID, "sshd_exec", user), + BaseConnection: common.NewBaseConnection(connID, "sshd_exec", conn.RemoteAddr().String(), user), ClientVersion: string(sconn.ClientVersion()), RemoteAddr: conn.RemoteAddr(), channel: channel, diff --git a/sftpd/ssh_cmd.go b/sftpd/ssh_cmd.go index 466b96dd..9fa0f712 100644 --- a/sftpd/ssh_cmd.go +++ b/sftpd/ssh_cmd.go @@ -726,9 +726,6 @@ func (c *sshCommand) sendExitStatus(err error) { status = uint32(1) c.connection.Log(logger.LevelWarn, "command failed: %#v args: %v user: %v err: %v", c.command, c.args, c.connection.User.Username, err) - } else { - logger.CommandLog(sshCommandLogSender, cmdPath, targetPath, c.connection.User.Username, "", c.connection.ID, - common.ProtocolSSH, -1, -1, "", "", c.connection.command, -1) } exitStatus := sshSubsystemExitStatus{ Status: status, @@ -753,6 +750,10 @@ func (c *sshCommand) sendExitStatus(err error) { } common.ExecuteActionNotification(&c.connection.User, common.OperationSSHCmd, cmdPath, c.getDestPath(), targetPath, c.command, 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()) + } } } diff --git a/sftpd/subsystem.go b/sftpd/subsystem.go index ae226fd4..1f6dc825 100644 --- a/sftpd/subsystem.go +++ b/sftpd/subsystem.go @@ -46,7 +46,7 @@ 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{}, channel: newSubsystemChannel(reader, writer), diff --git a/webdavd/internal_test.go b/webdavd/internal_test.go index b8b263b3..2ccfdc14 100644 --- a/webdavd/internal_test.go +++ b/webdavd/internal_test.go @@ -334,7 +334,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{} @@ -498,7 +498,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) @@ -567,7 +567,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) @@ -628,7 +628,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") @@ -679,7 +679,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() @@ -728,7 +728,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, @@ -821,7 +821,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 e3f9716c..cbb6df8f 100644 --- a/webdavd/server.go +++ b/webdavd/server.go @@ -204,7 +204,7 @@ 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, user), + BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolWebDAV, r.RemoteAddr, user), request: r, } common.Connections.Add(connection) diff --git a/webdavd/webdavd_test.go b/webdavd/webdavd_test.go index ef41f2e2..62eb61e8 100644 --- a/webdavd/webdavd_test.go +++ b/webdavd/webdavd_test.go @@ -1029,7 +1029,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)) @@ -1084,7 +1084,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))