improve logging

Fixes #381
This commit is contained in:
Nicola Murino 2021-07-24 20:11:17 +02:00
parent 83c7453957
commit c41ae116eb
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
30 changed files with 237 additions and 150 deletions

View file

@ -205,7 +205,7 @@ func TestPreDeleteAction(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("id", homeDir, "") fs := vfs.NewOsFs("id", homeDir, "")
c := NewBaseConnection("id", ProtocolSFTP, "", user) c := NewBaseConnection("id", ProtocolSFTP, "", "", user)
testfile := filepath.Join(user.HomeDir, "testfile") testfile := filepath.Join(user.HomeDir, "testfile")
err = os.WriteFile(testfile, []byte("test"), os.ModePerm) err = os.WriteFile(testfile, []byte("test"), os.ModePerm)

View file

@ -287,6 +287,7 @@ type ActiveTransfer interface {
type ActiveConnection interface { type ActiveConnection interface {
GetID() string GetID() string
GetUsername() string GetUsername() string
GetLocalAddress() string
GetRemoteAddress() string GetRemoteAddress() string
GetClientVersion() string GetClientVersion() string
GetProtocol() string GetProtocol() string
@ -596,7 +597,8 @@ func (conns *ActiveConnections) Add(c ActiveConnection) {
conns.connections = append(conns.connections, c) conns.connections = append(conns.connections, c)
metric.UpdateActiveConnectionsSize(len(conns.connections)) 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. // 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[lastIdx] = nil
conns.connections = conns.connections[:lastIdx] conns.connections = conns.connections[:lastIdx]
metric.UpdateActiveConnectionsSize(lastIdx) metric.UpdateActiveConnectionsSize(lastIdx)
logger.Debug(conn.GetProtocol(), conn.GetID(), "connection removed, close fs error: %v, num open connections: %v", logger.Debug(conn.GetProtocol(), conn.GetID(), "connection removed, local address %#v, remote address %#v close fs error: %v, num open connections: %v",
err, lastIdx) conn.GetLocalAddress(), conn.GetRemoteAddress(), err, lastIdx)
return return
} }
} }

View file

@ -60,6 +60,10 @@ func (c *fakeConnection) GetCommand() string {
return c.command return c.command
} }
func (c *fakeConnection) GetLocalAddress() string {
return ""
}
func (c *fakeConnection) GetRemoteAddress() string { func (c *fakeConnection) GetRemoteAddress() string {
return "" return ""
} }
@ -255,7 +259,7 @@ func TestMaxConnections(t *testing.T) {
Config.MaxPerHostConnections = perHost Config.MaxPerHostConnections = perHost
assert.True(t, Connections.IsNewConnectionAllowed(ipAddr)) assert.True(t, Connections.IsNewConnectionAllowed(ipAddr))
c := NewBaseConnection("id", ProtocolSFTP, "", dataprovider.User{}) c := NewBaseConnection("id", ProtocolSFTP, "", "", dataprovider.User{})
fakeConn := &fakeConnection{ fakeConn := &fakeConnection{
BaseConnection: c, BaseConnection: c,
} }
@ -328,7 +332,7 @@ func TestIdleConnections(t *testing.T) {
Username: username, 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() c.lastActivity = time.Now().Add(-24 * time.Hour).UnixNano()
fakeConn := &fakeConnection{ fakeConn := &fakeConnection{
BaseConnection: c, BaseConnection: c,
@ -340,7 +344,7 @@ func TestIdleConnections(t *testing.T) {
Connections.AddSSHConnection(sshConn1) Connections.AddSSHConnection(sshConn1)
Connections.Add(fakeConn) Connections.Add(fakeConn)
assert.Equal(t, Connections.GetActiveSessions(username), 1) assert.Equal(t, Connections.GetActiveSessions(username), 1)
c = NewBaseConnection(sshConn2.id+"_1", ProtocolSSH, "", user) c = NewBaseConnection(sshConn2.id+"_1", ProtocolSSH, "", "", user)
fakeConn = &fakeConnection{ fakeConn = &fakeConnection{
BaseConnection: c, BaseConnection: c,
} }
@ -348,7 +352,7 @@ func TestIdleConnections(t *testing.T) {
Connections.Add(fakeConn) Connections.Add(fakeConn)
assert.Equal(t, Connections.GetActiveSessions(username), 2) assert.Equal(t, Connections.GetActiveSessions(username), 2)
cFTP := NewBaseConnection("id2", ProtocolFTP, "", dataprovider.User{}) cFTP := NewBaseConnection("id2", ProtocolFTP, "", "", dataprovider.User{})
cFTP.lastActivity = time.Now().UnixNano() cFTP.lastActivity = time.Now().UnixNano()
fakeConn = &fakeConnection{ fakeConn = &fakeConnection{
BaseConnection: cFTP, BaseConnection: cFTP,
@ -388,7 +392,7 @@ func TestIdleConnections(t *testing.T) {
} }
func TestCloseConnection(t *testing.T) { func TestCloseConnection(t *testing.T) {
c := NewBaseConnection("id", ProtocolSFTP, "", dataprovider.User{}) c := NewBaseConnection("id", ProtocolSFTP, "", "", dataprovider.User{})
fakeConn := &fakeConnection{ fakeConn := &fakeConnection{
BaseConnection: c, BaseConnection: c,
} }
@ -404,7 +408,7 @@ func TestCloseConnection(t *testing.T) {
} }
func TestSwapConnection(t *testing.T) { func TestSwapConnection(t *testing.T) {
c := NewBaseConnection("id", ProtocolFTP, "", dataprovider.User{}) c := NewBaseConnection("id", ProtocolFTP, "", "", dataprovider.User{})
fakeConn := &fakeConnection{ fakeConn := &fakeConnection{
BaseConnection: c, BaseConnection: c,
} }
@ -412,7 +416,7 @@ func TestSwapConnection(t *testing.T) {
if assert.Len(t, Connections.GetStats(), 1) { if assert.Len(t, Connections.GetStats(), 1) {
assert.Equal(t, "", Connections.GetStats()[0].Username) assert.Equal(t, "", Connections.GetStats()[0].Username)
} }
c = NewBaseConnection("id", ProtocolFTP, "", dataprovider.User{ c = NewBaseConnection("id", ProtocolFTP, "", "", dataprovider.User{
BaseUser: sdk.BaseUser{ BaseUser: sdk.BaseUser{
Username: userTestUsername, Username: userTestUsername,
}, },
@ -453,7 +457,7 @@ func TestConnectionStatus(t *testing.T) {
}, },
} }
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
c1 := NewBaseConnection("id1", ProtocolSFTP, "", user) c1 := NewBaseConnection("id1", ProtocolSFTP, "", "", user)
fakeConn1 := &fakeConnection{ fakeConn1 := &fakeConnection{
BaseConnection: c1, BaseConnection: c1,
} }
@ -461,12 +465,12 @@ func TestConnectionStatus(t *testing.T) {
t1.BytesReceived = 123 t1.BytesReceived = 123
t2 := NewBaseTransfer(nil, c1, nil, "/p2", "/p2", "/r2", TransferDownload, 0, 0, 0, true, fs) t2 := NewBaseTransfer(nil, c1, nil, "/p2", "/p2", "/r2", TransferDownload, 0, 0, 0, true, fs)
t2.BytesSent = 456 t2.BytesSent = 456
c2 := NewBaseConnection("id2", ProtocolSSH, "", user) c2 := NewBaseConnection("id2", ProtocolSSH, "", "", user)
fakeConn2 := &fakeConnection{ fakeConn2 := &fakeConnection{
BaseConnection: c2, BaseConnection: c2,
command: "md5sum", command: "md5sum",
} }
c3 := NewBaseConnection("id3", ProtocolWebDAV, "", user) c3 := NewBaseConnection("id3", ProtocolWebDAV, "", "", user)
fakeConn3 := &fakeConnection{ fakeConn3 := &fakeConnection{
BaseConnection: c3, BaseConnection: c3,
command: "PROPFIND", command: "PROPFIND",
@ -707,7 +711,7 @@ func TestCachedFs(t *testing.T) {
HomeDir: filepath.Clean(os.TempDir()), HomeDir: filepath.Clean(os.TempDir()),
}, },
} }
conn := NewBaseConnection("id", ProtocolSFTP, "", user) conn := NewBaseConnection("id", ProtocolSFTP, "", "", user)
// changing the user should not affect the connection // changing the user should not affect the connection
user.HomeDir = filepath.Join(os.TempDir(), "temp") user.HomeDir = filepath.Join(os.TempDir(), "temp")
err := os.Mkdir(user.HomeDir, os.ModePerm) err := os.Mkdir(user.HomeDir, os.ModePerm)

View file

@ -33,13 +33,14 @@ type BaseConnection struct {
startTime time.Time startTime time.Time
protocol string protocol string
remoteAddr string remoteAddr string
localAddr string
sync.RWMutex sync.RWMutex
transferID uint64 transferID uint64
activeTransfers []ActiveTransfer activeTransfers []ActiveTransfer
} }
// NewBaseConnection returns a new BaseConnection // 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 connID := id
if util.IsStringInSlice(protocol, supportedProtocols) { if util.IsStringInSlice(protocol, supportedProtocols) {
connID = fmt.Sprintf("%v_%v", protocol, id) connID = fmt.Sprintf("%v_%v", protocol, id)
@ -49,6 +50,7 @@ func NewBaseConnection(id, protocol, remoteAddr string, user dataprovider.User)
User: user, User: user,
startTime: time.Now(), startTime: time.Now(),
protocol: protocol, protocol: protocol,
localAddr: localAddr,
remoteAddr: remoteAddr, remoteAddr: remoteAddr,
lastActivity: time.Now().UnixNano(), lastActivity: time.Now().UnixNano(),
transferID: 0, transferID: 0,
@ -242,7 +244,8 @@ func (c *BaseConnection) CreateDir(virtualPath string) error {
} }
vfs.SetPathPermissions(fs, fsPath, c.User.GetUID(), c.User.GetGID()) 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) ExecuteActionNotification(&c.User, operationMkdir, fsPath, virtualPath, "", "", c.protocol, 0, nil)
return 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 { if info.Mode()&os.ModeSymlink == 0 {
vfolder, err := c.User.GetVirtualFolderForPath(path.Dir(virtualPath)) vfolder, err := c.User.GetVirtualFolderForPath(path.Dir(virtualPath))
if err == nil { if err == nil {
@ -347,7 +351,8 @@ func (c *BaseConnection) RemoveDir(virtualPath string) error {
return c.GetFsError(fs, err) 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) ExecuteActionNotification(&c.User, operationRmdir, fsPath, virtualPath, "", "", c.protocol, 0, nil)
return 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()) vfs.SetPathPermissions(fsDst, fsTargetPath, c.User.GetUID(), c.User.GetGID())
c.updateQuotaAfterRename(fsDst, virtualSourcePath, virtualTargetPath, fsTargetPath, initialSize) //nolint:errcheck c.updateQuotaAfterRename(fsDst, virtualSourcePath, virtualTargetPath, fsTargetPath, initialSize) //nolint:errcheck
logger.CommandLog(renameLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1, 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) ExecuteActionNotification(&c.User, operationRename, fsSourcePath, virtualSourcePath, fsTargetPath, "", c.protocol, 0, nil)
return nil return nil
@ -445,7 +450,7 @@ func (c *BaseConnection) CreateSymlink(virtualSourcePath, virtualTargetPath stri
return c.GetFsError(fs, err) return c.GetFsError(fs, err)
} }
logger.CommandLog(symlinkLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1, "", logger.CommandLog(symlinkLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1, "",
"", "", -1, c.remoteAddr) "", "", -1, c.localAddr, c.remoteAddr)
return nil return nil
} }
@ -511,7 +516,7 @@ func (c *BaseConnection) handleChmod(fs vfs.Fs, fsPath, pathForPerms string, att
return c.GetFsError(fs, err) return c.GetFsError(fs, err)
} }
logger.CommandLog(chmodLogSender, fsPath, "", c.User.Username, attributes.Mode.String(), c.ID, c.protocol, 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 return nil
} }
@ -528,7 +533,7 @@ func (c *BaseConnection) handleChown(fs vfs.Fs, fsPath, pathForPerms string, att
return c.GetFsError(fs, err) return c.GetFsError(fs, err)
} }
logger.CommandLog(chownLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, attributes.UID, attributes.GID, 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 return nil
} }
@ -547,7 +552,7 @@ func (c *BaseConnection) handleChtimes(fs vfs.Fs, fsPath, pathForPerms string, a
accessTimeString := attributes.Atime.Format(chtimesFormat) accessTimeString := attributes.Atime.Format(chtimesFormat)
modificationTimeString := attributes.Mtime.Format(chtimesFormat) modificationTimeString := attributes.Mtime.Format(chtimesFormat)
logger.CommandLog(chtimesLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, 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 return nil
} }
@ -581,7 +586,7 @@ func (c *BaseConnection) SetStat(virtualPath string, attributes *StatAttributes)
return c.GetFsError(fs, err) return c.GetFsError(fs, err)
} }
logger.CommandLog(truncateLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", 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 return nil

View file

@ -65,7 +65,7 @@ func TestRemoveErrors(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
conn := NewBaseConnection("", ProtocolFTP, "", user) conn := NewBaseConnection("", ProtocolFTP, "", "", user)
err := conn.IsRemoveDirAllowed(fs, mappedPath, "/virtualpath1") err := conn.IsRemoveDirAllowed(fs, mappedPath, "/virtualpath1")
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "permission denied") assert.Contains(t, err.Error(), "permission denied")
@ -88,7 +88,7 @@ func TestSetStatMode(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := newMockOsFs(true, "", user.GetHomeDir()) fs := newMockOsFs(true, "", user.GetHomeDir())
conn := NewBaseConnection("", ProtocolWebDAV, "", user) conn := NewBaseConnection("", ProtocolWebDAV, "", "", user)
err := conn.handleChmod(fs, fakePath, fakePath, nil) err := conn.handleChmod(fs, fakePath, fakePath, nil)
assert.NoError(t, err) assert.NoError(t, err)
err = conn.handleChown(fs, fakePath, fakePath, nil) err = conn.handleChown(fs, fakePath, fakePath, nil)
@ -105,14 +105,14 @@ func TestSetStatMode(t *testing.T) {
func TestRecursiveRenameWalkError(t *testing.T) { func TestRecursiveRenameWalkError(t *testing.T) {
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
conn := NewBaseConnection("", ProtocolWebDAV, "", dataprovider.User{}) conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{})
err := conn.checkRecursiveRenameDirPermissions(fs, fs, "/source", "/target") err := conn.checkRecursiveRenameDirPermissions(fs, fs, "/source", "/target")
assert.ErrorIs(t, err, os.ErrNotExist) assert.ErrorIs(t, err, os.ErrNotExist)
} }
func TestCrossRenameFsErrors(t *testing.T) { func TestCrossRenameFsErrors(t *testing.T) {
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
conn := NewBaseConnection("", ProtocolWebDAV, "", dataprovider.User{}) conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{})
res := conn.hasSpaceForCrossRename(fs, vfs.QuotaCheckResult{}, 1, "missingsource") res := conn.hasSpaceForCrossRename(fs, vfs.QuotaCheckResult{}, 1, "missingsource")
assert.False(t, res) assert.False(t, res)
if runtime.GOOS != osWindows { if runtime.GOOS != osWindows {
@ -143,7 +143,7 @@ func TestRenameVirtualFolders(t *testing.T) {
VirtualPath: vdir, VirtualPath: vdir,
}) })
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
conn := NewBaseConnection("", ProtocolFTP, "", u) conn := NewBaseConnection("", ProtocolFTP, "", "", u)
res := conn.isRenamePermitted(fs, fs, "source", "target", vdir, "vdirtarget", nil) res := conn.isRenamePermitted(fs, fs, "source", "target", vdir, "vdirtarget", nil)
assert.False(t, res) assert.False(t, res)
} }
@ -180,7 +180,7 @@ func TestUpdateQuotaAfterRename(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
fs, err := user.GetFilesystem("id") fs, err := user.GetFilesystem("id")
assert.NoError(t, err) assert.NoError(t, err)
c := NewBaseConnection("", ProtocolSFTP, "", user) c := NewBaseConnection("", ProtocolSFTP, "", "", user)
request := sftp.NewRequest("Rename", "/testfile") request := sftp.NewRequest("Rename", "/testfile")
if runtime.GOOS != osWindows { if runtime.GOOS != osWindows {
request.Filepath = "/dir" request.Filepath = "/dir"
@ -225,7 +225,7 @@ func TestUpdateQuotaAfterRename(t *testing.T) {
func TestErrorsMapping(t *testing.T) { func TestErrorsMapping(t *testing.T) {
fs := vfs.NewOsFs("", os.TempDir(), "") 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 { for _, protocol := range supportedProtocols {
conn.SetProtocol(protocol) conn.SetProtocol(protocol)
err := conn.GetFsError(fs, os.ErrNotExist) err := conn.GetFsError(fs, os.ErrNotExist)
@ -291,7 +291,7 @@ func TestMaxWriteSize(t *testing.T) {
} }
fs, err := user.GetFilesystem("123") fs, err := user.GetFilesystem("123")
assert.NoError(t, err) assert.NoError(t, err)
conn := NewBaseConnection("", ProtocolFTP, "", user) conn := NewBaseConnection("", ProtocolFTP, "", "", user)
quotaResult := vfs.QuotaCheckResult{ quotaResult := vfs.QuotaCheckResult{
HasSpace: true, HasSpace: true,
} }

View file

@ -1927,7 +1927,7 @@ func TestFsPermissionErrors(t *testing.T) {
func TestResolvePathError(t *testing.T) { func TestResolvePathError(t *testing.T) {
u := getTestUser() u := getTestUser()
u.HomeDir = "relative_path" u.HomeDir = "relative_path"
conn := common.NewBaseConnection("", common.ProtocolFTP, "", u) conn := common.NewBaseConnection("", common.ProtocolFTP, "", "", u)
testPath := "apath" testPath := "apath"
_, err := conn.ListDir(testPath) _, err := conn.ListDir(testPath)
assert.Error(t, err) assert.Error(t, err)
@ -2404,16 +2404,16 @@ func TestSFTPLoopError(t *testing.T) {
user1.VirtualFolders[0].FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword) user1.VirtualFolders[0].FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
user2.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) _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
assert.ErrorIs(t, err, os.ErrPermission) 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) _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "SFTP loop") 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) _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
if assert.Error(t, err) { if assert.Error(t, err) {
assert.Contains(t, err.Error(), "SFTP loop") assert.Contains(t, err.Error(), "SFTP loop")
@ -2650,7 +2650,7 @@ func TestProxyProtocol(t *testing.T) {
} }
func TestSetProtocol(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) conn.SetProtocol(common.ProtocolSCP)
require.Equal(t, "SCP_id", conn.GetID()) require.Equal(t, "SCP_id", conn.GetID())
} }
@ -2660,7 +2660,7 @@ func TestGetFsError(t *testing.T) {
u.FsConfig.Provider = sdk.GCSFilesystemProvider u.FsConfig.Provider = sdk.GCSFilesystemProvider
u.FsConfig.GCSConfig.Bucket = "test" u.FsConfig.GCSConfig.Bucket = "test"
u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials") 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") _, _, err := conn.GetFsAndResolvedPath("/vpath")
assert.Error(t, err) assert.Error(t, err)
} }

View file

@ -236,7 +236,7 @@ func (t *BaseTransfer) Close() error {
elapsed := time.Since(t.start).Nanoseconds() / 1000000 elapsed := time.Since(t.start).Nanoseconds() / 1000000
if t.transferType == TransferDownload { if t.transferType == TransferDownload {
logger.TransferLog(downloadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesSent), t.Connection.User.Username, 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, ExecuteActionNotification(&t.Connection.User, operationDownload, t.fsPath, t.requestPath, "", "", t.Connection.protocol,
atomic.LoadInt64(&t.BytesSent), t.ErrTransfer) atomic.LoadInt64(&t.BytesSent), t.ErrTransfer)
} else { } else {
@ -247,7 +247,7 @@ func (t *BaseTransfer) Close() error {
t.Connection.Log(logger.LevelDebug, "uploaded file size %v", fileSize) t.Connection.Log(logger.LevelDebug, "uploaded file size %v", fileSize)
t.updateQuota(numFiles, fileSize) t.updateQuota(numFiles, fileSize)
logger.TransferLog(uploadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesReceived), t.Connection.User.Username, 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, ExecuteActionNotification(&t.Connection.User, operationUpload, t.fsPath, t.requestPath, "", "", t.Connection.protocol, fileSize,
t.ErrTransfer) t.ErrTransfer)
} }

View file

@ -17,7 +17,7 @@ import (
) )
func TestTransferUpdateQuota(t *testing.T) { func TestTransferUpdateQuota(t *testing.T) {
conn := NewBaseConnection("", ProtocolSFTP, "", dataprovider.User{}) conn := NewBaseConnection("", ProtocolSFTP, "", "", dataprovider.User{})
transfer := BaseTransfer{ transfer := BaseTransfer{
Connection: conn, Connection: conn,
transferType: TransferUpload, transferType: TransferUpload,
@ -64,7 +64,7 @@ func TestTransferThrottling(t *testing.T) {
// some tolerance // some tolerance
wantedUploadElapsed -= wantedDownloadElapsed / 10 wantedUploadElapsed -= wantedDownloadElapsed / 10
wantedDownloadElapsed -= 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 := NewBaseTransfer(nil, conn, nil, "", "", "", TransferUpload, 0, 0, 0, true, fs)
transfer.BytesReceived = testFileSize transfer.BytesReceived = testFileSize
transfer.Connection.UpdateLastActivity() transfer.Connection.UpdateLastActivity()
@ -100,7 +100,7 @@ func TestRealPath(t *testing.T) {
u.Permissions["/"] = []string{dataprovider.PermAny} u.Permissions["/"] = []string{dataprovider.PermAny}
file, err := os.Create(testFile) file, err := os.Create(testFile)
require.NoError(t, err) 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) transfer := NewBaseTransfer(file, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 0, 0, true, fs)
rPath := transfer.GetRealFsPath(testFile) rPath := transfer.GetRealFsPath(testFile)
assert.Equal(t, testFile, rPath) assert.Equal(t, testFile, rPath)
@ -137,7 +137,7 @@ func TestTruncate(t *testing.T) {
} }
_, err = file.Write([]byte("hello")) _, err = file.Write([]byte("hello"))
assert.NoError(t, err) 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) transfer := NewBaseTransfer(file, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 5, 100, false, fs)
err = conn.SetStat("/transfer_test_file", &StatAttributes{ err = conn.SetStat("/transfer_test_file", &StatAttributes{
@ -201,7 +201,7 @@ func TestTransferErrors(t *testing.T) {
if !assert.NoError(t, err) { if !assert.NoError(t, err) {
assert.FailNow(t, "unable to open test file") 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) transfer := NewBaseTransfer(file, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 0, 0, true, fs)
assert.Nil(t, transfer.cancelFn) assert.Nil(t, transfer.cancelFn)
assert.Equal(t, testFile, transfer.GetFsPath()) assert.Equal(t, testFile, transfer.GetFsPath())
@ -272,7 +272,7 @@ func TestRemovePartialCryptoFile(t *testing.T) {
HomeDir: os.TempDir(), 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 := NewBaseTransfer(nil, conn, nil, testFile, testFile, "/transfer_test_file", TransferUpload, 0, 0, 0, true, fs)
transfer.ErrTransfer = errors.New("test error") transfer.ErrTransfer = errors.New("test error")
_, err = transfer.getUploadFileSize() _, err = transfer.getUploadFileSize()

View file

@ -1532,7 +1532,6 @@ func isPasswordOK(user *User, password string) (bool, error) {
} }
} else if strings.HasPrefix(user.Password, bcryptPwdPrefix) { } else if strings.HasPrefix(user.Password, bcryptPwdPrefix) {
if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil { 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 return match, ErrInvalidCredentials
} }
match = true match = true
@ -1583,20 +1582,24 @@ func checkUserAndPass(user *User, password, ip, protocol string) (User, error) {
if !user.Filters.Hooks.CheckPasswordDisabled { if !user.Filters.Hooks.CheckPasswordDisabled {
hookResponse, err := executeCheckPasswordHook(user.Username, password, ip, protocol) hookResponse, err := executeCheckPasswordHook(user.Username, password, ip, protocol)
if err != nil { 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") return *user, errors.New("unable to check credentials")
} }
switch hookResponse.Status { switch hookResponse.Status {
case -1: case -1:
// no hook configured // no hook configured
case 1: 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 return *user, nil
case 2: 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 password = hookResponse.ToVerify
default: 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 return *user, ErrInvalidCredentials
} }
} }
@ -2116,7 +2119,8 @@ func executePreLoginHook(username, loginMethod, ip, protocol string) (User, erro
startTime := time.Now() startTime := time.Now()
out, err := getPreLoginHookResponse(loginMethod, ip, protocol, userAsJSON) out, err := getPreLoginHookResponse(loginMethod, ip, protocol, userAsJSON)
if err != nil { 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)) providerLog(logger.LevelDebug, "pre-login hook completed, elapsed: %v", time.Since(startTime))
if util.IsByteArrayEmpty(out) { if util.IsByteArrayEmpty(out) {
@ -2209,8 +2213,8 @@ func ExecutePostLoginHook(user *User, loginMethod, ip, protocol string, err erro
respCode = resp.StatusCode respCode = resp.StatusCode
resp.Body.Close() resp.Body.Close()
} }
providerLog(logger.LevelDebug, "post login hook executed, response code: %v, elapsed: %v err: %v", providerLog(logger.LevelDebug, "post login hook executed for user %#v, ip %v, protocol %v, response code: %v, elapsed: %v err: %v",
respCode, time.Since(startTime), err) user.Username, ip, protocol, respCode, time.Since(startTime), err)
return return
} }
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) 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)) fmt.Sprintf("SFTPGO_LOGIND_PROTOCOL=%v", protocol))
startTime := time.Now() startTime := time.Now()
err = cmd.Run() 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() startTime := time.Now()
out, err := getExternalAuthResponse(username, password, pkey, keyboardInteractive, ip, protocol, tlsCert, userAsJSON) out, err := getExternalAuthResponse(username, password, pkey, keyboardInteractive, ip, protocol, tlsCert, userAsJSON)
if err != nil { 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) { if util.IsByteArrayEmpty(out) {
providerLog(logger.LevelDebug, "empty response from external hook, no modification requested for user %#v id: %v", providerLog(logger.LevelDebug, "empty response from external hook, no modification requested for user %#v id: %v",
username, u.ID) username, u.ID)

View file

@ -13,6 +13,7 @@ The logs can be divided into the following categories:
- `sender` string. `Upload` or `Download` - `sender` string. `Upload` or `Download`
- `time` string. Date/time with millisecond precision - `time` string. Date/time with millisecond precision
- `level` string - `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` - `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 - `elapsed_ms`, int64. Elapsed time, as milliseconds, for the upload/download
- `size_bytes`, int64. Size, as bytes, of the download/upload - `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: - **"command logs"**, SFTP/SCP command logs:
- `sender` string. `Rename`, `Rmdir`, `Mkdir`, `Symlink`, `Remove`, `Chmod`, `Chown`, `Chtimes`, `Truncate`, `SSHCommand` - `sender` string. `Rename`, `Rmdir`, `Mkdir`, `Symlink`, `Remove`, `Chmod`, `Chown`, `Chtimes`, `Truncate`, `SSHCommand`
- `level` string - `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` - `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 - `username`, string
- `file_path` string - `file_path` string
@ -39,6 +41,7 @@ The logs can be divided into the following categories:
- **"http logs"**, REST API logs: - **"http logs"**, REST API logs:
- `sender` string. `httpd` - `sender` string. `httpd`
- `level` string - `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` - `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` - `proto` string, for example `HTTP/1.1`
- `method` string. HTTP method (`GET`, `POST`, `PUT`, `DELETE` etc.) - `method` string. HTTP method (`GET`, `POST`, `PUT`, `DELETE` etc.)

View file

@ -40,7 +40,12 @@ func (c *Connection) GetClientVersion() string {
return "Unknown" 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 { func (c *Connection) GetRemoteAddress() string {
return c.clientContext.RemoteAddr().String() return c.clientContext.RemoteAddr().String()
} }

View file

@ -516,7 +516,7 @@ func TestClientVersion(t *testing.T) {
connID := fmt.Sprintf("2_%v", mockCC.ID()) connID := fmt.Sprintf("2_%v", mockCC.ID())
user := dataprovider.User{} user := dataprovider.User{}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user),
clientContext: mockCC, clientContext: mockCC,
} }
common.Connections.Add(connection) common.Connections.Add(connection)
@ -533,7 +533,7 @@ func TestDriverMethodsNotImplemented(t *testing.T) {
connID := fmt.Sprintf("2_%v", mockCC.ID()) connID := fmt.Sprintf("2_%v", mockCC.ID())
user := dataprovider.User{} user := dataprovider.User{}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user),
clientContext: mockCC, clientContext: mockCC,
} }
_, err := connection.Create("") _, err := connection.Create("")
@ -560,7 +560,7 @@ func TestResolvePathErrors(t *testing.T) {
mockCC := mockFTPClientContext{} mockCC := mockFTPClientContext{}
connID := fmt.Sprintf("%v", mockCC.ID()) connID := fmt.Sprintf("%v", mockCC.ID())
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user),
clientContext: mockCC, clientContext: mockCC,
} }
err := connection.Mkdir("", os.ModePerm) err := connection.Mkdir("", os.ModePerm)
@ -625,7 +625,7 @@ func TestUploadFileStatError(t *testing.T) {
connID := fmt.Sprintf("%v", mockCC.ID()) connID := fmt.Sprintf("%v", mockCC.ID())
fs := vfs.NewOsFs(connID, user.HomeDir, "") fs := vfs.NewOsFs(connID, user.HomeDir, "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user),
clientContext: mockCC, clientContext: mockCC,
} }
testFile := filepath.Join(user.HomeDir, "test", "testfile") testFile := filepath.Join(user.HomeDir, "test", "testfile")
@ -655,7 +655,7 @@ func TestAVBLErrors(t *testing.T) {
mockCC := mockFTPClientContext{} mockCC := mockFTPClientContext{}
connID := fmt.Sprintf("%v", mockCC.ID()) connID := fmt.Sprintf("%v", mockCC.ID())
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user),
clientContext: mockCC, clientContext: mockCC,
} }
_, err := connection.GetAvailableSpace("/") _, err := connection.GetAvailableSpace("/")
@ -678,7 +678,7 @@ func TestUploadOverwriteErrors(t *testing.T) {
connID := fmt.Sprintf("%v", mockCC.ID()) connID := fmt.Sprintf("%v", mockCC.ID())
fs := newMockOsFs(nil, nil, false, connID, user.GetHomeDir()) fs := newMockOsFs(nil, nil, false, connID, user.GetHomeDir())
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user),
clientContext: mockCC, clientContext: mockCC,
} }
flags := 0 flags := 0
@ -734,7 +734,7 @@ func TestTransferErrors(t *testing.T) {
connID := fmt.Sprintf("%v", mockCC.ID()) connID := fmt.Sprintf("%v", mockCC.ID())
fs := newMockOsFs(nil, nil, false, connID, user.GetHomeDir()) fs := newMockOsFs(nil, nil, false, connID, user.GetHomeDir())
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, "", "", user),
clientContext: mockCC, clientContext: mockCC,
} }
baseTransfer := common.NewBaseTransfer(file, connection.BaseConnection, nil, file.Name(), file.Name(), testfile, baseTransfer := common.NewBaseTransfer(file, connection.BaseConnection, nil, file.Name(), file.Name(), testfile,

View file

@ -156,8 +156,9 @@ func (s *Server) ClientConnected(cc ftpserver.ClientContext) (string, error) {
connID := fmt.Sprintf("%v_%v", s.ID, cc.ID()) connID := fmt.Sprintf("%v_%v", s.ID, cc.ID())
user := dataprovider.User{} user := dataprovider.User{}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, cc.RemoteAddr().String(), user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolFTP, cc.LocalAddr().String(),
clientContext: cc, cc.RemoteAddr().String(), user),
clientContext: cc,
} }
common.Connections.Add(connection) common.Connections.Add(connection)
return s.initialMsg, nil return s.initialMsg, nil
@ -336,8 +337,9 @@ func (s *Server) validateUser(user dataprovider.User, cc ftpserver.ClientContext
return nil, common.ErrInternalFailure return nil, common.ErrInternalFailure
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(fmt.Sprintf("%v_%v", s.ID, cc.ID()), common.ProtocolFTP, remoteAddr, user), BaseConnection: common.NewBaseConnection(fmt.Sprintf("%v_%v", s.ID, cc.ID()), common.ProtocolFTP,
clientContext: cc, cc.LocalAddr().String(), remoteAddr, user),
clientContext: cc,
} }
err = common.Connections.Swap(connection) err = common.Connections.Swap(connection)
if err != nil { if err != nil {

View file

@ -37,8 +37,9 @@ func getUserConnection(w http.ResponseWriter, r *http.Request) (*Connection, err
return nil, err return nil, err
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, util.GetHTTPLocalAddress(r),
request: r, r.RemoteAddr, user),
request: r,
} }
return connection, nil return connection, nil
} }

View file

@ -28,7 +28,12 @@ func (c *Connection) GetClientVersion() string {
return "" 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 { func (c *Connection) GetRemoteAddress() string {
if c.request != nil { if c.request != nil {
return c.request.RemoteAddr return c.request.RemoteAddr

View file

@ -177,6 +177,10 @@ func (c *fakeConnection) GetCommand() string {
return c.command return c.command
} }
func (c *fakeConnection) GetLocalAddress() string {
return ""
}
func (c *fakeConnection) GetRemoteAddress() string { func (c *fakeConnection) GetRemoteAddress() string {
return "" return ""
} }
@ -2778,7 +2782,7 @@ func TestCloseActiveConnection(t *testing.T) {
_, err := httpdtest.CloseConnection("non_existent_id", http.StatusNotFound) _, err := httpdtest.CloseConnection("non_existent_id", http.StatusNotFound)
assert.NoError(t, err) assert.NoError(t, err)
user := getTestUser() user := getTestUser()
c := common.NewBaseConnection("connID", common.ProtocolSFTP, "", user) c := common.NewBaseConnection("connID", common.ProtocolSFTP, "", "", user)
fakeConn := &fakeConnection{ fakeConn := &fakeConnection{
BaseConnection: c, BaseConnection: c,
} }
@ -2791,12 +2795,12 @@ func TestCloseActiveConnection(t *testing.T) {
func TestCloseConnectionAfterUserUpdateDelete(t *testing.T) { func TestCloseConnectionAfterUserUpdateDelete(t *testing.T) {
user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated) user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
assert.NoError(t, err) assert.NoError(t, err)
c := common.NewBaseConnection("connID", common.ProtocolFTP, "", user) c := common.NewBaseConnection("connID", common.ProtocolFTP, "", "", user)
fakeConn := &fakeConnection{ fakeConn := &fakeConnection{
BaseConnection: c, BaseConnection: c,
} }
common.Connections.Add(fakeConn) common.Connections.Add(fakeConn)
c1 := common.NewBaseConnection("connID1", common.ProtocolSFTP, "", user) c1 := common.NewBaseConnection("connID1", common.ProtocolSFTP, "", "", user)
fakeConn1 := &fakeConnection{ fakeConn1 := &fakeConnection{
BaseConnection: c1, BaseConnection: c1,
} }
@ -3530,7 +3534,7 @@ func TestLoaddataMode(t *testing.T) {
assert.Equal(t, int64(789), folder.LastQuotaUpdate) assert.Equal(t, int64(789), folder.LastQuotaUpdate)
assert.Len(t, folder.Users, 0) assert.Len(t, folder.Users, 0)
c := common.NewBaseConnection("connID", common.ProtocolFTP, "", user) c := common.NewBaseConnection("connID", common.ProtocolFTP, "", "", user)
fakeConn := &fakeConnection{ fakeConn := &fakeConnection{
BaseConnection: c, BaseConnection: c,
} }
@ -5060,7 +5064,7 @@ func TestWebClientMaxConnections(t *testing.T) {
// now add a fake connection // now add a fake connection
fs := vfs.NewOsFs("id", os.TempDir(), "") fs := vfs.NewOsFs("id", os.TempDir(), "")
connection := &httpd.Connection{ connection := &httpd.Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolHTTP, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolHTTP, "", "", user),
} }
common.Connections.Add(connection) common.Connections.Add(connection)
@ -5198,7 +5202,7 @@ func TestMaxSessions(t *testing.T) {
// now add a fake connection // now add a fake connection
fs := vfs.NewOsFs("id", os.TempDir(), "") fs := vfs.NewOsFs("id", os.TempDir(), "")
connection := &httpd.Connection{ connection := &httpd.Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolHTTP, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolHTTP, "", "", user),
} }
common.Connections.Add(connection) common.Connections.Add(connection)
_, err = getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword) _, err = getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword)

View file

@ -1211,7 +1211,7 @@ func TestCompressorAbortHandler(t *testing.T) {
}() }()
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", dataprovider.User{}), BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", dataprovider.User{}),
request: nil, request: nil,
} }
renderCompressedFiles(&failingWriter{}, connection, "", nil) renderCompressedFiles(&failingWriter{}, connection, "", nil)
@ -1226,7 +1226,7 @@ func TestZipErrors(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user),
request: nil, request: nil,
} }
@ -1442,7 +1442,7 @@ func TestConnection(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user),
request: nil, request: nil,
} }
assert.Empty(t, connection.GetClientVersion()) assert.Empty(t, connection.GetClientVersion())
@ -1466,7 +1466,7 @@ func TestGetFileWriterErrors(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user),
request: nil, request: nil,
} }
_, err := connection.getFileWriter("name") _, err := connection.getFileWriter("name")
@ -1482,7 +1482,7 @@ func TestGetFileWriterErrors(t *testing.T) {
}, },
} }
connection = &Connection{ connection = &Connection{
BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user),
request: nil, request: nil,
} }
_, err = connection.getFileWriter("/path") _, err = connection.getFileWriter("/path")
@ -1499,7 +1499,7 @@ func TestHTTPDFile(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", user), BaseConnection: common.NewBaseConnection(xid.New().String(), common.ProtocolHTTP, "", "", user),
request: nil, request: nil,
} }

View file

@ -283,8 +283,9 @@ func handleWebClientDownloadZip(w http.ResponseWriter, r *http.Request) {
return return
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, util.GetHTTPLocalAddress(r),
request: r, r.RemoteAddr, user),
request: r,
} }
common.Connections.Add(connection) common.Connections.Add(connection)
defer common.Connections.Remove(connection.GetID()) defer common.Connections.Remove(connection.GetID())
@ -326,8 +327,9 @@ func handleClientGetDirContents(w http.ResponseWriter, r *http.Request) {
return return
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, util.GetHTTPLocalAddress(r),
request: r, r.RemoteAddr, user),
request: r,
} }
common.Connections.Add(connection) common.Connections.Add(connection)
defer common.Connections.Remove(connection.GetID()) defer common.Connections.Remove(connection.GetID())
@ -386,8 +388,9 @@ func handleClientGetFiles(w http.ResponseWriter, r *http.Request) {
return return
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, r.RemoteAddr, user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolHTTP, util.GetHTTPLocalAddress(r),
request: r, r.RemoteAddr, user),
request: r,
} }
common.Connections.Add(connection) common.Connections.Add(connection)
defer common.Connections.Remove(connection.GetID()) defer common.Connections.Remove(connection.GetID())

View file

@ -259,10 +259,11 @@ func ErrorToConsole(format string, v ...interface{}) {
} }
// TransferLog logs uploads or downloads // 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(). logger.Info().
Timestamp(). Timestamp().
Str("sender", operation). Str("sender", operation).
Str("local_addr", localAddr).
Str("remote_addr", remoteAddr). Str("remote_addr", remoteAddr).
Int64("elapsed_ms", elapsed). Int64("elapsed_ms", elapsed).
Int64("size_bytes", size). 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 // CommandLog logs an SFTP/SCP/SSH command
func CommandLog(command, path, target, user, fileMode, connectionID, protocol string, uid, gid int, atime, mtime, 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(). logger.Info().
Timestamp(). Timestamp().
Str("sender", command). Str("sender", command).

View file

@ -2,6 +2,7 @@ package logger
import ( import (
"fmt" "fmt"
"net"
"net/http" "net/http"
"time" "time"
@ -40,6 +41,7 @@ func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry {
} }
fields := map[string]interface{}{ fields := map[string]interface{}{
"local_addr": getLocalAddress(r),
"remote_addr": r.RemoteAddr, "remote_addr": r.RemoteAddr,
"proto": r.Proto, "proto": r.Proto,
"method": r.Method, "method": r.Method,
@ -77,3 +79,14 @@ func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) {
Str("panic", fmt.Sprintf("%+v", v)). Str("panic", fmt.Sprintf("%+v", v)).
Send() 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 ""
}

View file

@ -22,6 +22,7 @@ type Connection struct {
ClientVersion string ClientVersion string
// Remote address for this connection // Remote address for this connection
RemoteAddr net.Addr RemoteAddr net.Addr
LocalAddr net.Addr
channel io.ReadWriteCloser channel io.ReadWriteCloser
command string command string
} }
@ -31,7 +32,15 @@ func (c *Connection) GetClientVersion() string {
return c.ClientVersion 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 { func (c *Connection) GetRemoteAddress() string {
if c.RemoteAddr == nil { if c.RemoteAddr == nil {
return "" return ""

View file

@ -161,7 +161,7 @@ func TestUploadResumeInvalidOffset(t *testing.T) {
}, },
} }
fs := vfs.NewOsFs("", os.TempDir(), "") 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) baseTransfer := common.NewBaseTransfer(file, conn, nil, file.Name(), file.Name(), testfile, common.TransferUpload, 10, 0, 0, false, fs)
transfer := newTransfer(baseTransfer, nil, nil, nil) transfer := newTransfer(baseTransfer, nil, nil, nil)
_, err = transfer.WriteAt([]byte("test"), 0) _, err = transfer.WriteAt([]byte("test"), 0)
@ -191,7 +191,7 @@ func TestReadWriteErrors(t *testing.T) {
}, },
} }
fs := vfs.NewOsFs("", os.TempDir(), "") 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) baseTransfer := common.NewBaseTransfer(file, conn, nil, file.Name(), file.Name(), testfile, common.TransferDownload, 0, 0, 0, false, fs)
transfer := newTransfer(baseTransfer, nil, nil, nil) transfer := newTransfer(baseTransfer, nil, nil, nil)
err = file.Close() err = file.Close()
@ -239,7 +239,7 @@ func TestReadWriteErrors(t *testing.T) {
} }
func TestUnsupportedListOP(t *testing.T) { func TestUnsupportedListOP(t *testing.T) {
conn := common.NewBaseConnection("", common.ProtocolSFTP, "", dataprovider.User{}) conn := common.NewBaseConnection("", common.ProtocolSFTP, "", "", dataprovider.User{})
sftpConn := Connection{ sftpConn := Connection{
BaseConnection: conn, BaseConnection: conn,
} }
@ -262,7 +262,7 @@ func TestTransferCancelFn(t *testing.T) {
}, },
} }
fs := vfs.NewOsFs("", os.TempDir(), "") 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) baseTransfer := common.NewBaseTransfer(file, conn, cancelFn, file.Name(), file.Name(), testfile, common.TransferDownload, 0, 0, 0, false, fs)
transfer := newTransfer(baseTransfer, nil, nil, nil) transfer := newTransfer(baseTransfer, nil, nil, nil)
@ -286,7 +286,7 @@ func TestUploadFiles(t *testing.T) {
fs := vfs.NewOsFs("123", os.TempDir(), "") fs := vfs.NewOsFs("123", os.TempDir(), "")
u := dataprovider.User{} u := dataprovider.User{}
c := Connection{ c := Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", u), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", u),
} }
var flags sftp.FileOpenFlags var flags sftp.FileOpenFlags
flags.Write = true flags.Write = true
@ -338,7 +338,7 @@ func TestWithInvalidHome(t *testing.T) {
fs, err := u.GetFilesystem("123") fs, err := u.GetFilesystem("123")
assert.NoError(t, err) assert.NoError(t, err)
c := Connection{ c := Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", u), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", u),
} }
_, err = fs.ResolvePath("../upper_path") _, err = fs.ResolvePath("../upper_path")
assert.Error(t, err, "tested path is not a home subdir") 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 = make(map[string][]string)
u.Permissions["/"] = []string{dataprovider.PermAny} u.Permissions["/"] = []string{dataprovider.PermAny}
connection := Connection{ connection := Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", u), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", u),
} }
quotaResult := connection.HasSpace(false, false, "/") quotaResult := connection.HasSpace(false, false, "/")
assert.False(t, quotaResult.HasSpace) assert.False(t, quotaResult.HasSpace)
@ -470,7 +470,7 @@ func TestSSHCommandErrors(t *testing.T) {
user.Permissions = make(map[string][]string) user.Permissions = make(map[string][]string)
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
connection := Connection{ connection := Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", "", user),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
cmd := sshCommand{ cmd := sshCommand{
@ -610,7 +610,7 @@ func TestCommandsWithExtensionsFilter(t *testing.T) {
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSSH, "", "", user),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
cmd := sshCommand{ cmd := sshCommand{
@ -673,7 +673,7 @@ func TestSSHCommandsRemoteFs(t *testing.T) {
}, },
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
cmd := sshCommand{ cmd := sshCommand{
@ -720,7 +720,7 @@ func TestSSHCmdGetFsErrors(t *testing.T) {
user.Permissions = map[string][]string{} user.Permissions = map[string][]string{}
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
cmd := sshCommand{ cmd := sshCommand{
@ -773,7 +773,7 @@ func TestGitVirtualFolders(t *testing.T) {
}, },
} }
conn := &Connection{ conn := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
} }
cmd := sshCommand{ cmd := sshCommand{
command: "git-receive-pack", command: "git-receive-pack",
@ -821,7 +821,7 @@ func TestRsyncOptions(t *testing.T) {
}, },
} }
conn := &Connection{ conn := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
} }
sshCmd := sshCommand{ sshCmd := sshCommand{
command: "rsync", command: "rsync",
@ -838,7 +838,7 @@ func TestRsyncOptions(t *testing.T) {
user.Permissions = permissions user.Permissions = permissions
conn = &Connection{ conn = &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
} }
sshCmd = sshCommand{ sshCmd = sshCommand{
command: "rsync", command: "rsync",
@ -872,7 +872,7 @@ func TestSystemCommandSizeForPath(t *testing.T) {
fs, err := user.GetFilesystem("123") fs, err := user.GetFilesystem("123")
assert.NoError(t, err) assert.NoError(t, err)
conn := &Connection{ conn := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
} }
sshCmd := sshCommand{ sshCmd := sshCommand{
command: "rsync", command: "rsync",
@ -936,7 +936,7 @@ func TestSystemCommandErrors(t *testing.T) {
fs, err := user.GetFilesystem("123") fs, err := user.GetFilesystem("123")
assert.NoError(t, err) assert.NoError(t, err)
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
var sshCmd sshCommand var sshCmd sshCommand
@ -1012,7 +1012,7 @@ func TestCommandGetFsError(t *testing.T) {
}, },
} }
conn := &Connection{ conn := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
} }
sshCmd := sshCommand{ sshCmd := sshCommand{
command: "rsync", command: "rsync",
@ -1030,7 +1030,7 @@ func TestCommandGetFsError(t *testing.T) {
ReadError: nil, ReadError: nil,
} }
conn = &Connection{ conn = &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", user),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1124,7 +1124,7 @@ func TestSCPUploadError(t *testing.T) {
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1163,7 +1163,7 @@ func TestSCPInvalidEndDir(t *testing.T) {
StdErrBuffer: bytes.NewBuffer(stdErrBuf), StdErrBuffer: bytes.NewBuffer(stdErrBuf),
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", dataprovider.User{ BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", dataprovider.User{
BaseUser: sdk.BaseUser{ BaseUser: sdk.BaseUser{
HomeDir: os.TempDir(), HomeDir: os.TempDir(),
}, },
@ -1191,7 +1191,7 @@ func TestSCPParseUploadMessage(t *testing.T) {
} }
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", dataprovider.User{ BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", dataprovider.User{
BaseUser: sdk.BaseUser{ BaseUser: sdk.BaseUser{
HomeDir: os.TempDir(), HomeDir: os.TempDir(),
}, },
@ -1230,7 +1230,7 @@ func TestSCPProtocolMessages(t *testing.T) {
WriteError: writeErr, WriteError: writeErr,
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{}), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{}),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1291,7 +1291,7 @@ func TestSCPTestDownloadProtocolMessages(t *testing.T) {
WriteError: writeErr, WriteError: writeErr,
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{}), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{}),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1365,7 +1365,7 @@ func TestSCPCommandHandleErrors(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
}() }()
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{}), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{}),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1406,7 +1406,7 @@ func TestSCPErrorsMockFs(t *testing.T) {
}() }()
connection := &Connection{ connection := &Connection{
channel: &mockSSHChannel, channel: &mockSSHChannel,
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", u), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", u),
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
sshCommand: sshCommand{ sshCommand: sshCommand{
@ -1448,7 +1448,7 @@ func TestSCPRecursiveDownloadErrors(t *testing.T) {
}() }()
fs := vfs.NewOsFs("123", os.TempDir(), "") fs := vfs.NewOsFs("123", os.TempDir(), "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{ BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{
BaseUser: sdk.BaseUser{ BaseUser: sdk.BaseUser{
HomeDir: os.TempDir(), HomeDir: os.TempDir(),
}, },
@ -1496,7 +1496,7 @@ func TestSCPRecursiveUploadErrors(t *testing.T) {
WriteError: writeErr, WriteError: writeErr,
} }
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", dataprovider.User{}), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", dataprovider.User{}),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1537,7 +1537,7 @@ func TestSCPCreateDirs(t *testing.T) {
fs, err := u.GetFilesystem("123") fs, err := u.GetFilesystem("123")
assert.NoError(t, err) assert.NoError(t, err)
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", u), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", u),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1571,7 +1571,7 @@ func TestSCPDownloadFileData(t *testing.T) {
} }
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
connection := &Connection{ 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, channel: &mockSSHChannelReadErr,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1623,7 +1623,7 @@ func TestSCPUploadFiledata(t *testing.T) {
} }
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", user),
channel: &mockSSHChannel, channel: &mockSSHChannel,
} }
scpCommand := scpCommand{ scpCommand := scpCommand{
@ -1714,7 +1714,7 @@ func TestUploadError(t *testing.T) {
} }
fs := vfs.NewOsFs("", os.TempDir(), "") fs := vfs.NewOsFs("", os.TempDir(), "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSCP, "", "", user),
} }
testfile := "testfile" testfile := "testfile"
@ -1762,7 +1762,7 @@ func TestTransferFailingReader(t *testing.T) {
fs := newMockOsFs(nil, nil, true, "", os.TempDir()) fs := newMockOsFs(nil, nil, true, "", os.TempDir())
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
} }
request := sftp.NewRequest("Open", "afile.txt") request := sftp.NewRequest("Open", "afile.txt")
@ -1923,7 +1923,7 @@ func TestRecursiveCopyErrors(t *testing.T) {
fs, err := user.GetFilesystem("123") fs, err := user.GetFilesystem("123")
assert.NoError(t, err) assert.NoError(t, err)
conn := &Connection{ conn := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", user), BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
} }
sshCmd := sshCommand{ sshCmd := sshCommand{
command: "sftpgo-copy", command: "sftpgo-copy",
@ -1974,7 +1974,7 @@ func TestRecoverer(t *testing.T) {
c.AcceptInboundConnection(nil, nil) c.AcceptInboundConnection(nil, nil)
connID := "connectionID" connID := "connectionID"
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, "", dataprovider.User{}), BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, "", "", dataprovider.User{}),
} }
c.handleSftpConnection(nil, connection) c.handleSftpConnection(nil, connection)
sshCmd := sshCommand{ sshCmd := sshCommand{

View file

@ -437,20 +437,24 @@ func (c *Configuration) AcceptInboundConnection(conn net.Conn, config *ssh.Serve
if string(req.Payload[4:]) == "sftp" { if string(req.Payload[4:]) == "sftp" {
ok = true ok = true
connection := Connection{ connection := Connection{
BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, conn.RemoteAddr().String(), user), BaseConnection: common.NewBaseConnection(connID, common.ProtocolSFTP, conn.LocalAddr().String(),
ClientVersion: string(sconn.ClientVersion()), conn.RemoteAddr().String(), user),
RemoteAddr: conn.RemoteAddr(), ClientVersion: string(sconn.ClientVersion()),
channel: channel, RemoteAddr: conn.RemoteAddr(),
LocalAddr: conn.LocalAddr(),
channel: channel,
} }
go c.handleSftpConnection(channel, &connection) go c.handleSftpConnection(channel, &connection)
} }
case "exec": case "exec":
// protocol will be set later inside processSSHCommand it could be SSH or SCP // protocol will be set later inside processSSHCommand it could be SSH or SCP
connection := Connection{ connection := Connection{
BaseConnection: common.NewBaseConnection(connID, "sshd_exec", conn.RemoteAddr().String(), user), BaseConnection: common.NewBaseConnection(connID, "sshd_exec", conn.LocalAddr().String(),
ClientVersion: string(sconn.ClientVersion()), conn.RemoteAddr().String(), user),
RemoteAddr: conn.RemoteAddr(), ClientVersion: string(sconn.ClientVersion()),
channel: channel, RemoteAddr: conn.RemoteAddr(),
LocalAddr: conn.LocalAddr(),
channel: channel,
} }
ok = processSSHCommand(req.Payload, &connection, c.EnabledSSHCommands) ok = processSSHCommand(req.Payload, &connection, c.EnabledSSHCommands)
} }

View file

@ -753,7 +753,8 @@ func (c *sshCommand) sendExitStatus(err error) {
common.ProtocolSSH, 0, err) common.ProtocolSSH, 0, err)
if err == nil { if err == nil {
logger.CommandLog(sshCommandLogSender, cmdPath, targetPath, c.connection.User.Username, "", c.connection.ID, 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())
} }
} }
} }

View file

@ -46,9 +46,10 @@ func ServeSubSystemConnection(user *dataprovider.User, connectionID string, read
dataprovider.UpdateLastLogin(user) //nolint:errcheck dataprovider.UpdateLastLogin(user) //nolint:errcheck
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolSFTP, "", *user), BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolSFTP, "", "", *user),
ClientVersion: "", ClientVersion: "",
RemoteAddr: &net.IPAddr{}, RemoteAddr: &net.IPAddr{},
LocalAddr: &net.IPAddr{},
channel: newSubsystemChannel(reader, writer), channel: newSubsystemChannel(reader, writer),
} }
common.Connections.Add(connection) common.Connections.Add(connection)

View file

@ -563,6 +563,19 @@ func GetRealIP(r *http.Request) string {
return ip 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 // ParseAllowedIPAndRanges returns a list of functions that allow to find if a
func ParseAllowedIPAndRanges(allowed []string) ([]func(net.IP) bool, error) { func ParseAllowedIPAndRanges(allowed []string) ([]func(net.IP) bool, error) {
res := make([]func(net.IP) bool, len(allowed)) res := make([]func(net.IP) bool, len(allowed))

View file

@ -31,7 +31,12 @@ func (c *Connection) GetClientVersion() string {
return "" 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 { func (c *Connection) GetRemoteAddress() string {
if c.request != nil { if c.request != nil {
return c.request.RemoteAddr return c.request.RemoteAddr

View file

@ -335,7 +335,7 @@ func TestOrderDirsToRemove(t *testing.T) {
user := dataprovider.User{} user := dataprovider.User{}
fs := vfs.NewOsFs("id", os.TempDir(), "") fs := vfs.NewOsFs("id", os.TempDir(), "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
request: nil, request: nil,
} }
dirsToRemove := []objectMapping{} dirsToRemove := []objectMapping{}
@ -503,7 +503,7 @@ func TestResolvePathErrors(t *testing.T) {
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "") fs := vfs.NewOsFs("connID", user.HomeDir, "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
} }
err := connection.Mkdir(ctx, "", os.ModePerm) err := connection.Mkdir(ctx, "", os.ModePerm)
@ -574,7 +574,7 @@ func TestFileAccessErrors(t *testing.T) {
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "") fs := vfs.NewOsFs("connID", user.HomeDir, "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
} }
missingPath := "missing path" missingPath := "missing path"
fsMissingPath := filepath.Join(user.HomeDir, missingPath) fsMissingPath := filepath.Join(user.HomeDir, missingPath)
@ -637,7 +637,7 @@ func TestRemoveDirTree(t *testing.T) {
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "") fs := vfs.NewOsFs("connID", user.HomeDir, "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
} }
vpath := path.Join("adir", "missing") vpath := path.Join("adir", "missing")
@ -690,7 +690,7 @@ func TestContentType(t *testing.T) {
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "") fs := vfs.NewOsFs("connID", user.HomeDir, "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
} }
testFilePath := filepath.Join(user.HomeDir, testFile) testFilePath := filepath.Join(user.HomeDir, testFile)
ctx := context.Background() ctx := context.Background()
@ -741,7 +741,7 @@ func TestTransferReadWriteErrors(t *testing.T) {
user.Permissions["/"] = []string{dataprovider.PermAny} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "") fs := vfs.NewOsFs("connID", user.HomeDir, "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
} }
testFilePath := filepath.Join(user.HomeDir, testFile) testFilePath := filepath.Join(user.HomeDir, testFile)
baseTransfer := common.NewBaseTransfer(nil, connection.BaseConnection, nil, testFilePath, testFilePath, 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} user.Permissions["/"] = []string{dataprovider.PermAny}
fs := vfs.NewOsFs("connID", user.HomeDir, "") fs := vfs.NewOsFs("connID", user.HomeDir, "")
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
} }
testFilePath := filepath.Join(user.HomeDir, testFile) testFilePath := filepath.Join(user.HomeDir, testFile)
testFileContents := []byte("content") testFileContents := []byte("content")

View file

@ -201,8 +201,9 @@ func (s *webDavServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx = context.WithValue(ctx, requestStartKey, time.Now()) ctx = context.WithValue(ctx, requestStartKey, time.Now())
connection := &Connection{ connection := &Connection{
BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolWebDAV, r.RemoteAddr, user), BaseConnection: common.NewBaseConnection(connectionID, common.ProtocolWebDAV, util.GetHTTPLocalAddress(r),
request: r, r.RemoteAddr, user),
request: r,
} }
common.Connections.Add(connection) common.Connections.Add(connection)
defer common.Connections.Remove(connection.GetID()) defer common.Connections.Remove(connection.GetID())

View file

@ -1030,7 +1030,7 @@ func TestMaxConnections(t *testing.T) {
// now add a fake connection // now add a fake connection
fs := vfs.NewOsFs("id", os.TempDir(), "") fs := vfs.NewOsFs("id", os.TempDir(), "")
connection := &webdavd.Connection{ connection := &webdavd.Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
} }
common.Connections.Add(connection) common.Connections.Add(connection)
assert.Error(t, checkBasicFunc(client)) assert.Error(t, checkBasicFunc(client))
@ -1085,7 +1085,7 @@ func TestMaxSessions(t *testing.T) {
// now add a fake connection // now add a fake connection
fs := vfs.NewOsFs("id", os.TempDir(), "") fs := vfs.NewOsFs("id", os.TempDir(), "")
connection := &webdavd.Connection{ connection := &webdavd.Connection{
BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", user), BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, "", "", user),
} }
common.Connections.Add(connection) common.Connections.Add(connection)
assert.Error(t, checkBasicFunc(client)) assert.Error(t, checkBasicFunc(client))