common_test.go 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468
  1. // Copyright (C) 2019-2022 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package common
  15. import (
  16. "crypto/tls"
  17. "encoding/json"
  18. "fmt"
  19. "net"
  20. "os"
  21. "os/exec"
  22. "path/filepath"
  23. "runtime"
  24. "strings"
  25. "sync"
  26. "testing"
  27. "time"
  28. "github.com/alexedwards/argon2id"
  29. "github.com/sftpgo/sdk"
  30. "github.com/stretchr/testify/assert"
  31. "github.com/stretchr/testify/require"
  32. "golang.org/x/crypto/bcrypt"
  33. "github.com/drakkan/sftpgo/v2/internal/dataprovider"
  34. "github.com/drakkan/sftpgo/v2/internal/kms"
  35. "github.com/drakkan/sftpgo/v2/internal/plugin"
  36. "github.com/drakkan/sftpgo/v2/internal/util"
  37. "github.com/drakkan/sftpgo/v2/internal/vfs"
  38. )
  39. const (
  40. logSenderTest = "common_test"
  41. httpAddr = "127.0.0.1:9999"
  42. osWindows = "windows"
  43. userTestUsername = "common_test_username"
  44. )
  45. var (
  46. configDir = filepath.Join(".", "..", "..")
  47. )
  48. type fakeConnection struct {
  49. *BaseConnection
  50. command string
  51. }
  52. func (c *fakeConnection) AddUser(user dataprovider.User) error {
  53. _, err := user.GetFilesystem(c.GetID())
  54. if err != nil {
  55. return err
  56. }
  57. c.BaseConnection.User = user
  58. return nil
  59. }
  60. func (c *fakeConnection) Disconnect() error {
  61. Connections.Remove(c.GetID())
  62. return nil
  63. }
  64. func (c *fakeConnection) GetClientVersion() string {
  65. return ""
  66. }
  67. func (c *fakeConnection) GetCommand() string {
  68. return c.command
  69. }
  70. func (c *fakeConnection) GetLocalAddress() string {
  71. return ""
  72. }
  73. func (c *fakeConnection) GetRemoteAddress() string {
  74. return ""
  75. }
  76. type customNetConn struct {
  77. net.Conn
  78. id string
  79. isClosed bool
  80. }
  81. func (c *customNetConn) Close() error {
  82. Connections.RemoveSSHConnection(c.id)
  83. c.isClosed = true
  84. return c.Conn.Close()
  85. }
  86. func TestConnections(t *testing.T) {
  87. c1 := &fakeConnection{
  88. BaseConnection: NewBaseConnection("id1", ProtocolSFTP, "", "", dataprovider.User{
  89. BaseUser: sdk.BaseUser{
  90. Username: userTestUsername,
  91. },
  92. }),
  93. }
  94. c2 := &fakeConnection{
  95. BaseConnection: NewBaseConnection("id2", ProtocolSFTP, "", "", dataprovider.User{
  96. BaseUser: sdk.BaseUser{
  97. Username: userTestUsername,
  98. },
  99. }),
  100. }
  101. c3 := &fakeConnection{
  102. BaseConnection: NewBaseConnection("id3", ProtocolSFTP, "", "", dataprovider.User{
  103. BaseUser: sdk.BaseUser{
  104. Username: userTestUsername,
  105. },
  106. }),
  107. }
  108. c4 := &fakeConnection{
  109. BaseConnection: NewBaseConnection("id4", ProtocolSFTP, "", "", dataprovider.User{
  110. BaseUser: sdk.BaseUser{
  111. Username: userTestUsername,
  112. },
  113. }),
  114. }
  115. assert.Equal(t, "SFTP_id1", c1.GetID())
  116. assert.Equal(t, "SFTP_id2", c2.GetID())
  117. assert.Equal(t, "SFTP_id3", c3.GetID())
  118. assert.Equal(t, "SFTP_id4", c4.GetID())
  119. err := Connections.Add(c1)
  120. assert.NoError(t, err)
  121. err = Connections.Add(c2)
  122. assert.NoError(t, err)
  123. err = Connections.Add(c3)
  124. assert.NoError(t, err)
  125. err = Connections.Add(c4)
  126. assert.NoError(t, err)
  127. Connections.RLock()
  128. assert.Len(t, Connections.connections, 4)
  129. assert.Len(t, Connections.mapping, 4)
  130. _, ok := Connections.mapping[c1.GetID()]
  131. assert.True(t, ok)
  132. assert.Equal(t, 0, Connections.mapping[c1.GetID()])
  133. assert.Equal(t, 1, Connections.mapping[c2.GetID()])
  134. assert.Equal(t, 2, Connections.mapping[c3.GetID()])
  135. assert.Equal(t, 3, Connections.mapping[c4.GetID()])
  136. Connections.RUnlock()
  137. c2 = &fakeConnection{
  138. BaseConnection: NewBaseConnection("id2", ProtocolSFTP, "", "", dataprovider.User{
  139. BaseUser: sdk.BaseUser{
  140. Username: userTestUsername + "_mod",
  141. },
  142. }),
  143. }
  144. err = Connections.Swap(c2)
  145. assert.NoError(t, err)
  146. Connections.RLock()
  147. assert.Len(t, Connections.connections, 4)
  148. assert.Len(t, Connections.mapping, 4)
  149. _, ok = Connections.mapping[c1.GetID()]
  150. assert.True(t, ok)
  151. assert.Equal(t, 0, Connections.mapping[c1.GetID()])
  152. assert.Equal(t, 1, Connections.mapping[c2.GetID()])
  153. assert.Equal(t, 2, Connections.mapping[c3.GetID()])
  154. assert.Equal(t, 3, Connections.mapping[c4.GetID()])
  155. assert.Equal(t, userTestUsername+"_mod", Connections.connections[1].GetUsername())
  156. Connections.RUnlock()
  157. Connections.Remove(c2.GetID())
  158. Connections.RLock()
  159. assert.Len(t, Connections.connections, 3)
  160. assert.Len(t, Connections.mapping, 3)
  161. _, ok = Connections.mapping[c1.GetID()]
  162. assert.True(t, ok)
  163. assert.Equal(t, 0, Connections.mapping[c1.GetID()])
  164. assert.Equal(t, 1, Connections.mapping[c4.GetID()])
  165. assert.Equal(t, 2, Connections.mapping[c3.GetID()])
  166. Connections.RUnlock()
  167. Connections.Remove(c3.GetID())
  168. Connections.RLock()
  169. assert.Len(t, Connections.connections, 2)
  170. assert.Len(t, Connections.mapping, 2)
  171. _, ok = Connections.mapping[c1.GetID()]
  172. assert.True(t, ok)
  173. assert.Equal(t, 0, Connections.mapping[c1.GetID()])
  174. assert.Equal(t, 1, Connections.mapping[c4.GetID()])
  175. Connections.RUnlock()
  176. Connections.Remove(c1.GetID())
  177. Connections.RLock()
  178. assert.Len(t, Connections.connections, 1)
  179. assert.Len(t, Connections.mapping, 1)
  180. _, ok = Connections.mapping[c4.GetID()]
  181. assert.True(t, ok)
  182. assert.Equal(t, 0, Connections.mapping[c4.GetID()])
  183. Connections.RUnlock()
  184. Connections.Remove(c4.GetID())
  185. Connections.RLock()
  186. assert.Len(t, Connections.connections, 0)
  187. assert.Len(t, Connections.mapping, 0)
  188. Connections.RUnlock()
  189. }
  190. func TestSSHConnections(t *testing.T) {
  191. conn1, conn2 := net.Pipe()
  192. now := time.Now()
  193. sshConn1 := NewSSHConnection("id1", conn1)
  194. sshConn2 := NewSSHConnection("id2", conn2)
  195. sshConn3 := NewSSHConnection("id3", conn2)
  196. assert.Equal(t, "id1", sshConn1.GetID())
  197. assert.Equal(t, "id2", sshConn2.GetID())
  198. assert.Equal(t, "id3", sshConn3.GetID())
  199. sshConn1.UpdateLastActivity()
  200. assert.GreaterOrEqual(t, sshConn1.GetLastActivity().UnixNano(), now.UnixNano())
  201. Connections.AddSSHConnection(sshConn1)
  202. Connections.AddSSHConnection(sshConn2)
  203. Connections.AddSSHConnection(sshConn3)
  204. Connections.RLock()
  205. assert.Len(t, Connections.sshConnections, 3)
  206. _, ok := Connections.sshMapping[sshConn1.GetID()]
  207. assert.True(t, ok)
  208. assert.Equal(t, 0, Connections.sshMapping[sshConn1.GetID()])
  209. assert.Equal(t, 1, Connections.sshMapping[sshConn2.GetID()])
  210. assert.Equal(t, 2, Connections.sshMapping[sshConn3.GetID()])
  211. Connections.RUnlock()
  212. Connections.RemoveSSHConnection(sshConn1.id)
  213. Connections.RLock()
  214. assert.Len(t, Connections.sshConnections, 2)
  215. assert.Equal(t, sshConn3.id, Connections.sshConnections[0].id)
  216. assert.Equal(t, sshConn2.id, Connections.sshConnections[1].id)
  217. _, ok = Connections.sshMapping[sshConn3.GetID()]
  218. assert.True(t, ok)
  219. assert.Equal(t, 0, Connections.sshMapping[sshConn3.GetID()])
  220. assert.Equal(t, 1, Connections.sshMapping[sshConn2.GetID()])
  221. Connections.RUnlock()
  222. Connections.RemoveSSHConnection(sshConn1.id)
  223. Connections.RLock()
  224. assert.Len(t, Connections.sshConnections, 2)
  225. assert.Equal(t, sshConn3.id, Connections.sshConnections[0].id)
  226. assert.Equal(t, sshConn2.id, Connections.sshConnections[1].id)
  227. _, ok = Connections.sshMapping[sshConn3.GetID()]
  228. assert.True(t, ok)
  229. assert.Equal(t, 0, Connections.sshMapping[sshConn3.GetID()])
  230. assert.Equal(t, 1, Connections.sshMapping[sshConn2.GetID()])
  231. Connections.RUnlock()
  232. Connections.RemoveSSHConnection(sshConn2.id)
  233. Connections.RLock()
  234. assert.Len(t, Connections.sshConnections, 1)
  235. assert.Equal(t, sshConn3.id, Connections.sshConnections[0].id)
  236. _, ok = Connections.sshMapping[sshConn3.GetID()]
  237. assert.True(t, ok)
  238. assert.Equal(t, 0, Connections.sshMapping[sshConn3.GetID()])
  239. Connections.RUnlock()
  240. Connections.RemoveSSHConnection(sshConn3.id)
  241. Connections.RLock()
  242. assert.Len(t, Connections.sshConnections, 0)
  243. assert.Len(t, Connections.sshMapping, 0)
  244. Connections.RUnlock()
  245. assert.NoError(t, sshConn1.Close())
  246. assert.NoError(t, sshConn2.Close())
  247. assert.NoError(t, sshConn3.Close())
  248. }
  249. func TestDefenderIntegration(t *testing.T) {
  250. // by default defender is nil
  251. configCopy := Config
  252. wdPath, err := os.Getwd()
  253. require.NoError(t, err)
  254. pluginsConfig := []plugin.Config{
  255. {
  256. Type: "ipfilter",
  257. Cmd: filepath.Join(wdPath, "..", "..", "tests", "ipfilter", "ipfilter"),
  258. AutoMTLS: true,
  259. },
  260. }
  261. if runtime.GOOS == osWindows {
  262. pluginsConfig[0].Cmd += ".exe"
  263. }
  264. err = plugin.Initialize(pluginsConfig, "debug")
  265. require.NoError(t, err)
  266. ip := "127.1.1.1"
  267. assert.Nil(t, Reload())
  268. // 192.168.1.12 is banned from the ipfilter plugin
  269. assert.True(t, IsBanned("192.168.1.12"))
  270. AddDefenderEvent(ip, HostEventNoLoginTried)
  271. assert.False(t, IsBanned(ip))
  272. banTime, err := GetDefenderBanTime(ip)
  273. assert.NoError(t, err)
  274. assert.Nil(t, banTime)
  275. assert.False(t, DeleteDefenderHost(ip))
  276. score, err := GetDefenderScore(ip)
  277. assert.NoError(t, err)
  278. assert.Equal(t, 0, score)
  279. _, err = GetDefenderHost(ip)
  280. assert.Error(t, err)
  281. hosts, err := GetDefenderHosts()
  282. assert.NoError(t, err)
  283. assert.Nil(t, hosts)
  284. Config.DefenderConfig = DefenderConfig{
  285. Enabled: true,
  286. Driver: DefenderDriverProvider,
  287. BanTime: 10,
  288. BanTimeIncrement: 50,
  289. Threshold: 0,
  290. ScoreInvalid: 2,
  291. ScoreValid: 1,
  292. ScoreNoAuth: 2,
  293. ObservationTime: 15,
  294. EntriesSoftLimit: 100,
  295. EntriesHardLimit: 150,
  296. }
  297. err = Initialize(Config, 0)
  298. // ScoreInvalid cannot be greater than threshold
  299. assert.Error(t, err)
  300. Config.DefenderConfig.Driver = "unsupported"
  301. err = Initialize(Config, 0)
  302. if assert.Error(t, err) {
  303. assert.Contains(t, err.Error(), "unsupported defender driver")
  304. }
  305. Config.DefenderConfig.Driver = DefenderDriverMemory
  306. err = Initialize(Config, 0)
  307. // ScoreInvalid cannot be greater than threshold
  308. assert.Error(t, err)
  309. Config.DefenderConfig.Threshold = 3
  310. Config.DefenderConfig.SafeListFile = filepath.Join(os.TempDir(), "sl.json")
  311. err = os.WriteFile(Config.DefenderConfig.SafeListFile, []byte(`{}`), 0644)
  312. assert.NoError(t, err)
  313. defer os.Remove(Config.DefenderConfig.SafeListFile)
  314. err = Initialize(Config, 0)
  315. assert.NoError(t, err)
  316. assert.Nil(t, Reload())
  317. err = os.WriteFile(Config.DefenderConfig.SafeListFile, []byte(`{`), 0644)
  318. assert.NoError(t, err)
  319. err = Reload()
  320. assert.Error(t, err)
  321. AddDefenderEvent(ip, HostEventNoLoginTried)
  322. assert.False(t, IsBanned(ip))
  323. score, err = GetDefenderScore(ip)
  324. assert.NoError(t, err)
  325. assert.Equal(t, 2, score)
  326. entry, err := GetDefenderHost(ip)
  327. assert.NoError(t, err)
  328. asJSON, err := json.Marshal(&entry)
  329. assert.NoError(t, err)
  330. assert.Equal(t, `{"id":"3132372e312e312e31","ip":"127.1.1.1","score":2}`, string(asJSON), "entry %v", entry)
  331. assert.True(t, DeleteDefenderHost(ip))
  332. banTime, err = GetDefenderBanTime(ip)
  333. assert.NoError(t, err)
  334. assert.Nil(t, banTime)
  335. AddDefenderEvent(ip, HostEventLoginFailed)
  336. AddDefenderEvent(ip, HostEventNoLoginTried)
  337. assert.True(t, IsBanned(ip))
  338. score, err = GetDefenderScore(ip)
  339. assert.NoError(t, err)
  340. assert.Equal(t, 0, score)
  341. banTime, err = GetDefenderBanTime(ip)
  342. assert.NoError(t, err)
  343. assert.NotNil(t, banTime)
  344. hosts, err = GetDefenderHosts()
  345. assert.NoError(t, err)
  346. assert.Len(t, hosts, 1)
  347. entry, err = GetDefenderHost(ip)
  348. assert.NoError(t, err)
  349. assert.False(t, entry.BanTime.IsZero())
  350. assert.True(t, DeleteDefenderHost(ip))
  351. hosts, err = GetDefenderHosts()
  352. assert.NoError(t, err)
  353. assert.Len(t, hosts, 0)
  354. banTime, err = GetDefenderBanTime(ip)
  355. assert.NoError(t, err)
  356. assert.Nil(t, banTime)
  357. assert.False(t, DeleteDefenderHost(ip))
  358. Config = configCopy
  359. }
  360. func TestRateLimitersIntegration(t *testing.T) {
  361. // by default defender is nil
  362. configCopy := Config
  363. Config.RateLimitersConfig = []RateLimiterConfig{
  364. {
  365. Average: 100,
  366. Period: 10,
  367. Burst: 5,
  368. Type: int(rateLimiterTypeGlobal),
  369. Protocols: rateLimiterProtocolValues,
  370. },
  371. {
  372. Average: 1,
  373. Period: 1000,
  374. Burst: 1,
  375. Type: int(rateLimiterTypeSource),
  376. Protocols: []string{ProtocolWebDAV, ProtocolWebDAV, ProtocolFTP},
  377. GenerateDefenderEvents: true,
  378. EntriesSoftLimit: 100,
  379. EntriesHardLimit: 150,
  380. },
  381. }
  382. err := Initialize(Config, 0)
  383. assert.Error(t, err)
  384. Config.RateLimitersConfig[0].Period = 1000
  385. Config.RateLimitersConfig[0].AllowList = []string{"1.1.1", "1.1.1.2"}
  386. err = Initialize(Config, 0)
  387. if assert.Error(t, err) {
  388. assert.Contains(t, err.Error(), "unable to parse rate limiter allow list")
  389. }
  390. Config.RateLimitersConfig[0].AllowList = []string{"172.16.24.7"}
  391. Config.RateLimitersConfig[1].AllowList = []string{"172.16.0.0/16"}
  392. err = Initialize(Config, 0)
  393. assert.NoError(t, err)
  394. assert.Len(t, rateLimiters, 4)
  395. assert.Len(t, rateLimiters[ProtocolSSH], 1)
  396. assert.Len(t, rateLimiters[ProtocolFTP], 2)
  397. assert.Len(t, rateLimiters[ProtocolWebDAV], 2)
  398. assert.Len(t, rateLimiters[ProtocolHTTP], 1)
  399. source1 := "127.1.1.1"
  400. source2 := "127.1.1.2"
  401. source3 := "172.16.24.7" // whitelisted
  402. _, err = LimitRate(ProtocolSSH, source1)
  403. assert.NoError(t, err)
  404. _, err = LimitRate(ProtocolFTP, source1)
  405. assert.NoError(t, err)
  406. // sleep to allow the add configured burst to the token.
  407. // This sleep is not enough to add the per-source burst
  408. time.Sleep(20 * time.Millisecond)
  409. _, err = LimitRate(ProtocolWebDAV, source2)
  410. assert.NoError(t, err)
  411. _, err = LimitRate(ProtocolFTP, source1)
  412. assert.Error(t, err)
  413. _, err = LimitRate(ProtocolWebDAV, source2)
  414. assert.Error(t, err)
  415. _, err = LimitRate(ProtocolSSH, source1)
  416. assert.NoError(t, err)
  417. _, err = LimitRate(ProtocolSSH, source2)
  418. assert.NoError(t, err)
  419. for i := 0; i < 10; i++ {
  420. _, err = LimitRate(ProtocolWebDAV, source3)
  421. assert.NoError(t, err)
  422. }
  423. Config = configCopy
  424. }
  425. func TestWhitelist(t *testing.T) {
  426. configCopy := Config
  427. Config.whitelist = &whitelist{}
  428. err := Config.whitelist.reload()
  429. if assert.Error(t, err) {
  430. assert.Contains(t, err.Error(), "cannot accept a nil whitelist")
  431. }
  432. wlFile := filepath.Join(os.TempDir(), "wl.json")
  433. Config.WhiteListFile = wlFile
  434. err = os.WriteFile(wlFile, []byte(`invalid list file`), 0664)
  435. assert.NoError(t, err)
  436. err = Initialize(Config, 0)
  437. assert.Error(t, err)
  438. wl := HostListFile{
  439. IPAddresses: []string{"172.18.1.1", "172.18.1.2"},
  440. CIDRNetworks: []string{"10.8.7.0/24"},
  441. }
  442. data, err := json.Marshal(wl)
  443. assert.NoError(t, err)
  444. err = os.WriteFile(wlFile, data, 0664)
  445. assert.NoError(t, err)
  446. defer os.Remove(wlFile)
  447. err = Initialize(Config, 0)
  448. assert.NoError(t, err)
  449. assert.NoError(t, Connections.IsNewConnectionAllowed("172.18.1.1"))
  450. assert.Error(t, Connections.IsNewConnectionAllowed("172.18.1.3"))
  451. assert.NoError(t, Connections.IsNewConnectionAllowed("10.8.7.3"))
  452. assert.Error(t, Connections.IsNewConnectionAllowed("10.8.8.2"))
  453. wl.IPAddresses = append(wl.IPAddresses, "172.18.1.3")
  454. wl.CIDRNetworks = append(wl.CIDRNetworks, "10.8.8.0/24")
  455. data, err = json.Marshal(wl)
  456. assert.NoError(t, err)
  457. err = os.WriteFile(wlFile, data, 0664)
  458. assert.NoError(t, err)
  459. assert.Error(t, Connections.IsNewConnectionAllowed("10.8.8.3"))
  460. err = Reload()
  461. assert.NoError(t, err)
  462. assert.NoError(t, Connections.IsNewConnectionAllowed("10.8.8.3"))
  463. assert.NoError(t, Connections.IsNewConnectionAllowed("172.18.1.3"))
  464. assert.NoError(t, Connections.IsNewConnectionAllowed("172.18.1.2"))
  465. assert.Error(t, Connections.IsNewConnectionAllowed("172.18.1.12"))
  466. Config = configCopy
  467. }
  468. func TestUserMaxSessions(t *testing.T) {
  469. c := NewBaseConnection("id", ProtocolSFTP, "", "", dataprovider.User{
  470. BaseUser: sdk.BaseUser{
  471. Username: userTestUsername,
  472. MaxSessions: 1,
  473. },
  474. })
  475. fakeConn := &fakeConnection{
  476. BaseConnection: c,
  477. }
  478. err := Connections.Add(fakeConn)
  479. assert.NoError(t, err)
  480. err = Connections.Add(fakeConn)
  481. assert.Error(t, err)
  482. err = Connections.Swap(fakeConn)
  483. assert.NoError(t, err)
  484. Connections.Remove(fakeConn.GetID())
  485. Connections.Lock()
  486. Connections.removeUserConnection(userTestUsername)
  487. Connections.Unlock()
  488. assert.Len(t, Connections.GetStats(), 0)
  489. }
  490. func TestMaxConnections(t *testing.T) {
  491. oldValue := Config.MaxTotalConnections
  492. perHost := Config.MaxPerHostConnections
  493. Config.MaxPerHostConnections = 0
  494. ipAddr := "192.168.7.8"
  495. assert.NoError(t, Connections.IsNewConnectionAllowed(ipAddr))
  496. Config.MaxTotalConnections = 1
  497. Config.MaxPerHostConnections = perHost
  498. assert.NoError(t, Connections.IsNewConnectionAllowed(ipAddr))
  499. c := NewBaseConnection("id", ProtocolSFTP, "", "", dataprovider.User{})
  500. fakeConn := &fakeConnection{
  501. BaseConnection: c,
  502. }
  503. err := Connections.Add(fakeConn)
  504. assert.NoError(t, err)
  505. assert.Len(t, Connections.GetStats(), 1)
  506. assert.Error(t, Connections.IsNewConnectionAllowed(ipAddr))
  507. res := Connections.Close(fakeConn.GetID())
  508. assert.True(t, res)
  509. assert.Eventually(t, func() bool { return len(Connections.GetStats()) == 0 }, 300*time.Millisecond, 50*time.Millisecond)
  510. assert.NoError(t, Connections.IsNewConnectionAllowed(ipAddr))
  511. Connections.AddClientConnection(ipAddr)
  512. Connections.AddClientConnection(ipAddr)
  513. assert.Error(t, Connections.IsNewConnectionAllowed(ipAddr))
  514. Connections.RemoveClientConnection(ipAddr)
  515. assert.NoError(t, Connections.IsNewConnectionAllowed(ipAddr))
  516. Connections.RemoveClientConnection(ipAddr)
  517. Config.MaxTotalConnections = oldValue
  518. }
  519. func TestMaxConnectionPerHost(t *testing.T) {
  520. oldValue := Config.MaxPerHostConnections
  521. Config.MaxPerHostConnections = 2
  522. ipAddr := "192.168.9.9"
  523. Connections.AddClientConnection(ipAddr)
  524. assert.NoError(t, Connections.IsNewConnectionAllowed(ipAddr))
  525. Connections.AddClientConnection(ipAddr)
  526. assert.NoError(t, Connections.IsNewConnectionAllowed(ipAddr))
  527. Connections.AddClientConnection(ipAddr)
  528. assert.Error(t, Connections.IsNewConnectionAllowed(ipAddr))
  529. assert.Equal(t, int32(3), Connections.GetClientConnections())
  530. Connections.RemoveClientConnection(ipAddr)
  531. Connections.RemoveClientConnection(ipAddr)
  532. Connections.RemoveClientConnection(ipAddr)
  533. assert.Equal(t, int32(0), Connections.GetClientConnections())
  534. Config.MaxPerHostConnections = oldValue
  535. }
  536. func TestIdleConnections(t *testing.T) {
  537. configCopy := Config
  538. Config.IdleTimeout = 1
  539. err := Initialize(Config, 0)
  540. assert.NoError(t, err)
  541. conn1, conn2 := net.Pipe()
  542. customConn1 := &customNetConn{
  543. Conn: conn1,
  544. id: "id1",
  545. }
  546. customConn2 := &customNetConn{
  547. Conn: conn2,
  548. id: "id2",
  549. }
  550. sshConn1 := NewSSHConnection(customConn1.id, customConn1)
  551. sshConn2 := NewSSHConnection(customConn2.id, customConn2)
  552. username := "test_user"
  553. user := dataprovider.User{
  554. BaseUser: sdk.BaseUser{
  555. Username: username,
  556. },
  557. }
  558. c := NewBaseConnection(sshConn1.id+"_1", ProtocolSFTP, "", "", user)
  559. c.lastActivity.Store(time.Now().Add(-24 * time.Hour).UnixNano())
  560. fakeConn := &fakeConnection{
  561. BaseConnection: c,
  562. }
  563. // both ssh connections are expired but they should get removed only
  564. // if there is no associated connection
  565. sshConn1.lastActivity.Store(c.lastActivity.Load())
  566. sshConn2.lastActivity.Store(c.lastActivity.Load())
  567. Connections.AddSSHConnection(sshConn1)
  568. err = Connections.Add(fakeConn)
  569. assert.NoError(t, err)
  570. assert.Equal(t, Connections.GetActiveSessions(username), 1)
  571. c = NewBaseConnection(sshConn2.id+"_1", ProtocolSSH, "", "", user)
  572. fakeConn = &fakeConnection{
  573. BaseConnection: c,
  574. }
  575. Connections.AddSSHConnection(sshConn2)
  576. err = Connections.Add(fakeConn)
  577. assert.NoError(t, err)
  578. assert.Equal(t, Connections.GetActiveSessions(username), 2)
  579. cFTP := NewBaseConnection("id2", ProtocolFTP, "", "", dataprovider.User{})
  580. cFTP.lastActivity.Store(time.Now().UnixNano())
  581. fakeConn = &fakeConnection{
  582. BaseConnection: cFTP,
  583. }
  584. err = Connections.Add(fakeConn)
  585. assert.NoError(t, err)
  586. assert.Equal(t, Connections.GetActiveSessions(username), 2)
  587. assert.Len(t, Connections.GetStats(), 3)
  588. Connections.RLock()
  589. assert.Len(t, Connections.sshConnections, 2)
  590. Connections.RUnlock()
  591. startPeriodicChecks(100 * time.Millisecond)
  592. assert.Eventually(t, func() bool { return Connections.GetActiveSessions(username) == 1 }, 2*time.Second, 200*time.Millisecond)
  593. assert.Eventually(t, func() bool {
  594. Connections.RLock()
  595. defer Connections.RUnlock()
  596. return len(Connections.sshConnections) == 1
  597. }, 1*time.Second, 200*time.Millisecond)
  598. stopEventScheduler()
  599. assert.Len(t, Connections.GetStats(), 2)
  600. c.lastActivity.Store(time.Now().Add(-24 * time.Hour).UnixNano())
  601. cFTP.lastActivity.Store(time.Now().Add(-24 * time.Hour).UnixNano())
  602. sshConn2.lastActivity.Store(c.lastActivity.Load())
  603. startPeriodicChecks(100 * time.Millisecond)
  604. assert.Eventually(t, func() bool { return len(Connections.GetStats()) == 0 }, 2*time.Second, 200*time.Millisecond)
  605. assert.Eventually(t, func() bool {
  606. Connections.RLock()
  607. defer Connections.RUnlock()
  608. return len(Connections.sshConnections) == 0
  609. }, 1*time.Second, 200*time.Millisecond)
  610. assert.Equal(t, int32(0), Connections.GetClientConnections())
  611. stopEventScheduler()
  612. assert.True(t, customConn1.isClosed)
  613. assert.True(t, customConn2.isClosed)
  614. Config = configCopy
  615. }
  616. func TestCloseConnection(t *testing.T) {
  617. c := NewBaseConnection("id", ProtocolSFTP, "", "", dataprovider.User{})
  618. fakeConn := &fakeConnection{
  619. BaseConnection: c,
  620. }
  621. assert.NoError(t, Connections.IsNewConnectionAllowed("127.0.0.1"))
  622. err := Connections.Add(fakeConn)
  623. assert.NoError(t, err)
  624. assert.Len(t, Connections.GetStats(), 1)
  625. res := Connections.Close(fakeConn.GetID())
  626. assert.True(t, res)
  627. assert.Eventually(t, func() bool { return len(Connections.GetStats()) == 0 }, 300*time.Millisecond, 50*time.Millisecond)
  628. res = Connections.Close(fakeConn.GetID())
  629. assert.False(t, res)
  630. Connections.Remove(fakeConn.GetID())
  631. }
  632. func TestSwapConnection(t *testing.T) {
  633. c := NewBaseConnection("id", ProtocolFTP, "", "", dataprovider.User{})
  634. fakeConn := &fakeConnection{
  635. BaseConnection: c,
  636. }
  637. err := Connections.Add(fakeConn)
  638. assert.NoError(t, err)
  639. if assert.Len(t, Connections.GetStats(), 1) {
  640. assert.Equal(t, "", Connections.GetStats()[0].Username)
  641. }
  642. c = NewBaseConnection("id", ProtocolFTP, "", "", dataprovider.User{
  643. BaseUser: sdk.BaseUser{
  644. Username: userTestUsername,
  645. MaxSessions: 1,
  646. },
  647. })
  648. fakeConn = &fakeConnection{
  649. BaseConnection: c,
  650. }
  651. c1 := NewBaseConnection("id1", ProtocolFTP, "", "", dataprovider.User{
  652. BaseUser: sdk.BaseUser{
  653. Username: userTestUsername,
  654. },
  655. })
  656. fakeConn1 := &fakeConnection{
  657. BaseConnection: c1,
  658. }
  659. err = Connections.Add(fakeConn1)
  660. assert.NoError(t, err)
  661. err = Connections.Swap(fakeConn)
  662. assert.Error(t, err)
  663. Connections.Remove(fakeConn1.ID)
  664. err = Connections.Swap(fakeConn)
  665. assert.NoError(t, err)
  666. if assert.Len(t, Connections.GetStats(), 1) {
  667. assert.Equal(t, userTestUsername, Connections.GetStats()[0].Username)
  668. }
  669. res := Connections.Close(fakeConn.GetID())
  670. assert.True(t, res)
  671. assert.Eventually(t, func() bool { return len(Connections.GetStats()) == 0 }, 300*time.Millisecond, 50*time.Millisecond)
  672. err = Connections.Swap(fakeConn)
  673. assert.Error(t, err)
  674. }
  675. func TestAtomicUpload(t *testing.T) {
  676. configCopy := Config
  677. Config.UploadMode = UploadModeStandard
  678. assert.False(t, Config.IsAtomicUploadEnabled())
  679. Config.UploadMode = UploadModeAtomic
  680. assert.True(t, Config.IsAtomicUploadEnabled())
  681. Config.UploadMode = UploadModeAtomicWithResume
  682. assert.True(t, Config.IsAtomicUploadEnabled())
  683. Config = configCopy
  684. }
  685. func TestConnectionStatus(t *testing.T) {
  686. username := "test_user"
  687. user := dataprovider.User{
  688. BaseUser: sdk.BaseUser{
  689. Username: username,
  690. },
  691. }
  692. fs := vfs.NewOsFs("", os.TempDir(), "")
  693. c1 := NewBaseConnection("id1", ProtocolSFTP, "", "", user)
  694. fakeConn1 := &fakeConnection{
  695. BaseConnection: c1,
  696. }
  697. t1 := NewBaseTransfer(nil, c1, nil, "/p1", "/p1", "/r1", TransferUpload, 0, 0, 0, 0, true, fs, dataprovider.TransferQuota{})
  698. t1.BytesReceived.Store(123)
  699. t2 := NewBaseTransfer(nil, c1, nil, "/p2", "/p2", "/r2", TransferDownload, 0, 0, 0, 0, true, fs, dataprovider.TransferQuota{})
  700. t2.BytesSent.Store(456)
  701. c2 := NewBaseConnection("id2", ProtocolSSH, "", "", user)
  702. fakeConn2 := &fakeConnection{
  703. BaseConnection: c2,
  704. command: "md5sum",
  705. }
  706. c3 := NewBaseConnection("id3", ProtocolWebDAV, "", "", user)
  707. fakeConn3 := &fakeConnection{
  708. BaseConnection: c3,
  709. command: "PROPFIND",
  710. }
  711. t3 := NewBaseTransfer(nil, c3, nil, "/p2", "/p2", "/r2", TransferDownload, 0, 0, 0, 0, true, fs, dataprovider.TransferQuota{})
  712. err := Connections.Add(fakeConn1)
  713. assert.NoError(t, err)
  714. err = Connections.Add(fakeConn2)
  715. assert.NoError(t, err)
  716. err = Connections.Add(fakeConn3)
  717. assert.NoError(t, err)
  718. stats := Connections.GetStats()
  719. assert.Len(t, stats, 3)
  720. for _, stat := range stats {
  721. assert.Equal(t, stat.Username, username)
  722. assert.True(t, strings.HasPrefix(stat.GetConnectionInfo(), stat.Protocol))
  723. assert.True(t, strings.HasPrefix(stat.GetConnectionDuration(), "00:"))
  724. if stat.ConnectionID == "SFTP_id1" {
  725. assert.Len(t, stat.Transfers, 2)
  726. assert.Greater(t, len(stat.GetTransfersAsString()), 0)
  727. for _, tr := range stat.Transfers {
  728. if tr.OperationType == operationDownload {
  729. assert.True(t, strings.HasPrefix(tr.getConnectionTransferAsString(), "DL"))
  730. } else if tr.OperationType == operationUpload {
  731. assert.True(t, strings.HasPrefix(tr.getConnectionTransferAsString(), "UL"))
  732. }
  733. }
  734. } else if stat.ConnectionID == "DAV_id3" {
  735. assert.Len(t, stat.Transfers, 1)
  736. assert.Greater(t, len(stat.GetTransfersAsString()), 0)
  737. } else {
  738. assert.Equal(t, 0, len(stat.GetTransfersAsString()))
  739. }
  740. }
  741. err = t1.Close()
  742. assert.NoError(t, err)
  743. err = t2.Close()
  744. assert.NoError(t, err)
  745. err = fakeConn3.SignalTransfersAbort()
  746. assert.NoError(t, err)
  747. assert.True(t, t3.AbortTransfer.Load())
  748. err = t3.Close()
  749. assert.NoError(t, err)
  750. err = fakeConn3.SignalTransfersAbort()
  751. assert.Error(t, err)
  752. Connections.Remove(fakeConn1.GetID())
  753. stats = Connections.GetStats()
  754. assert.Len(t, stats, 2)
  755. assert.Equal(t, fakeConn3.GetID(), stats[0].ConnectionID)
  756. assert.Equal(t, fakeConn2.GetID(), stats[1].ConnectionID)
  757. Connections.Remove(fakeConn2.GetID())
  758. stats = Connections.GetStats()
  759. assert.Len(t, stats, 1)
  760. assert.Equal(t, fakeConn3.GetID(), stats[0].ConnectionID)
  761. Connections.Remove(fakeConn3.GetID())
  762. stats = Connections.GetStats()
  763. assert.Len(t, stats, 0)
  764. }
  765. func TestQuotaScans(t *testing.T) {
  766. username := "username"
  767. assert.True(t, QuotaScans.AddUserQuotaScan(username))
  768. assert.False(t, QuotaScans.AddUserQuotaScan(username))
  769. usersScans := QuotaScans.GetUsersQuotaScans()
  770. if assert.Len(t, usersScans, 1) {
  771. assert.Equal(t, usersScans[0].Username, username)
  772. assert.Equal(t, QuotaScans.UserScans[0].StartTime, usersScans[0].StartTime)
  773. QuotaScans.UserScans[0].StartTime = 0
  774. assert.NotEqual(t, QuotaScans.UserScans[0].StartTime, usersScans[0].StartTime)
  775. }
  776. assert.True(t, QuotaScans.RemoveUserQuotaScan(username))
  777. assert.False(t, QuotaScans.RemoveUserQuotaScan(username))
  778. assert.Len(t, QuotaScans.GetUsersQuotaScans(), 0)
  779. assert.Len(t, usersScans, 1)
  780. folderName := "folder"
  781. assert.True(t, QuotaScans.AddVFolderQuotaScan(folderName))
  782. assert.False(t, QuotaScans.AddVFolderQuotaScan(folderName))
  783. if assert.Len(t, QuotaScans.GetVFoldersQuotaScans(), 1) {
  784. assert.Equal(t, QuotaScans.GetVFoldersQuotaScans()[0].Name, folderName)
  785. }
  786. assert.True(t, QuotaScans.RemoveVFolderQuotaScan(folderName))
  787. assert.False(t, QuotaScans.RemoveVFolderQuotaScan(folderName))
  788. assert.Len(t, QuotaScans.GetVFoldersQuotaScans(), 0)
  789. }
  790. func TestProxyProtocolVersion(t *testing.T) {
  791. c := Configuration{
  792. ProxyProtocol: 0,
  793. }
  794. _, err := c.GetProxyListener(nil)
  795. if assert.Error(t, err) {
  796. assert.Contains(t, err.Error(), "proxy protocol not configured")
  797. }
  798. c.ProxyProtocol = 1
  799. proxyListener, err := c.GetProxyListener(nil)
  800. assert.NoError(t, err)
  801. assert.Nil(t, proxyListener.Policy)
  802. c.ProxyProtocol = 2
  803. proxyListener, err = c.GetProxyListener(nil)
  804. assert.NoError(t, err)
  805. assert.NotNil(t, proxyListener.Policy)
  806. c.ProxyProtocol = 1
  807. c.ProxyAllowed = []string{"invalid"}
  808. _, err = c.GetProxyListener(nil)
  809. assert.Error(t, err)
  810. c.ProxyProtocol = 2
  811. _, err = c.GetProxyListener(nil)
  812. assert.Error(t, err)
  813. }
  814. func TestStartupHook(t *testing.T) {
  815. Config.StartupHook = ""
  816. assert.NoError(t, Config.ExecuteStartupHook())
  817. Config.StartupHook = "http://foo\x7f.com/startup"
  818. assert.Error(t, Config.ExecuteStartupHook())
  819. Config.StartupHook = "http://invalid:5678/"
  820. assert.Error(t, Config.ExecuteStartupHook())
  821. Config.StartupHook = fmt.Sprintf("http://%v", httpAddr)
  822. assert.NoError(t, Config.ExecuteStartupHook())
  823. Config.StartupHook = "invalidhook"
  824. assert.Error(t, Config.ExecuteStartupHook())
  825. if runtime.GOOS != osWindows {
  826. hookCmd, err := exec.LookPath("true")
  827. assert.NoError(t, err)
  828. Config.StartupHook = hookCmd
  829. assert.NoError(t, Config.ExecuteStartupHook())
  830. }
  831. Config.StartupHook = ""
  832. }
  833. func TestPostDisconnectHook(t *testing.T) {
  834. Config.PostDisconnectHook = "http://127.0.0.1/"
  835. remoteAddr := "127.0.0.1:80"
  836. Config.checkPostDisconnectHook(remoteAddr, ProtocolHTTP, "", "", time.Now())
  837. Config.checkPostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())
  838. Config.PostDisconnectHook = "http://bar\x7f.com/"
  839. Config.executePostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())
  840. Config.PostDisconnectHook = fmt.Sprintf("http://%v", httpAddr)
  841. Config.executePostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())
  842. Config.PostDisconnectHook = "relativePath"
  843. Config.executePostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())
  844. if runtime.GOOS == osWindows {
  845. Config.PostDisconnectHook = "C:\\a\\bad\\command"
  846. Config.executePostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())
  847. } else {
  848. Config.PostDisconnectHook = "/invalid/path"
  849. Config.executePostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())
  850. hookCmd, err := exec.LookPath("true")
  851. assert.NoError(t, err)
  852. Config.PostDisconnectHook = hookCmd
  853. Config.executePostDisconnectHook(remoteAddr, ProtocolSFTP, "", "", time.Now())
  854. }
  855. Config.PostDisconnectHook = ""
  856. }
  857. func TestPostConnectHook(t *testing.T) {
  858. Config.PostConnectHook = ""
  859. ipAddr := "127.0.0.1"
  860. assert.NoError(t, Config.ExecutePostConnectHook(ipAddr, ProtocolFTP))
  861. Config.PostConnectHook = "http://foo\x7f.com/"
  862. assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolSFTP))
  863. Config.PostConnectHook = "http://invalid:1234/"
  864. assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolSFTP))
  865. Config.PostConnectHook = fmt.Sprintf("http://%v/404", httpAddr)
  866. assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolFTP))
  867. Config.PostConnectHook = fmt.Sprintf("http://%v", httpAddr)
  868. assert.NoError(t, Config.ExecutePostConnectHook(ipAddr, ProtocolFTP))
  869. Config.PostConnectHook = "invalid"
  870. assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolFTP))
  871. if runtime.GOOS == osWindows {
  872. Config.PostConnectHook = "C:\\bad\\command"
  873. assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolSFTP))
  874. } else {
  875. Config.PostConnectHook = "/invalid/path"
  876. assert.Error(t, Config.ExecutePostConnectHook(ipAddr, ProtocolSFTP))
  877. hookCmd, err := exec.LookPath("true")
  878. assert.NoError(t, err)
  879. Config.PostConnectHook = hookCmd
  880. assert.NoError(t, Config.ExecutePostConnectHook(ipAddr, ProtocolSFTP))
  881. }
  882. Config.PostConnectHook = ""
  883. }
  884. func TestCryptoConvertFileInfo(t *testing.T) {
  885. name := "name"
  886. fs, err := vfs.NewCryptFs("connID1", os.TempDir(), "", vfs.CryptFsConfig{
  887. Passphrase: kms.NewPlainSecret("secret"),
  888. })
  889. require.NoError(t, err)
  890. cryptFs := fs.(*vfs.CryptFs)
  891. info := vfs.NewFileInfo(name, true, 48, time.Now(), false)
  892. assert.Equal(t, info, cryptFs.ConvertFileInfo(info))
  893. info = vfs.NewFileInfo(name, false, 48, time.Now(), false)
  894. assert.NotEqual(t, info.Size(), cryptFs.ConvertFileInfo(info).Size())
  895. info = vfs.NewFileInfo(name, false, 33, time.Now(), false)
  896. assert.Equal(t, int64(0), cryptFs.ConvertFileInfo(info).Size())
  897. info = vfs.NewFileInfo(name, false, 1, time.Now(), false)
  898. assert.Equal(t, int64(0), cryptFs.ConvertFileInfo(info).Size())
  899. }
  900. func TestFolderCopy(t *testing.T) {
  901. folder := vfs.BaseVirtualFolder{
  902. ID: 1,
  903. Name: "name",
  904. MappedPath: filepath.Clean(os.TempDir()),
  905. UsedQuotaSize: 4096,
  906. UsedQuotaFiles: 2,
  907. LastQuotaUpdate: util.GetTimeAsMsSinceEpoch(time.Now()),
  908. Users: []string{"user1", "user2"},
  909. }
  910. folderCopy := folder.GetACopy()
  911. folder.ID = 2
  912. folder.Users = []string{"user3"}
  913. require.Len(t, folderCopy.Users, 2)
  914. require.True(t, util.Contains(folderCopy.Users, "user1"))
  915. require.True(t, util.Contains(folderCopy.Users, "user2"))
  916. require.Equal(t, int64(1), folderCopy.ID)
  917. require.Equal(t, folder.Name, folderCopy.Name)
  918. require.Equal(t, folder.MappedPath, folderCopy.MappedPath)
  919. require.Equal(t, folder.UsedQuotaSize, folderCopy.UsedQuotaSize)
  920. require.Equal(t, folder.UsedQuotaFiles, folderCopy.UsedQuotaFiles)
  921. require.Equal(t, folder.LastQuotaUpdate, folderCopy.LastQuotaUpdate)
  922. folder.FsConfig = vfs.Filesystem{
  923. CryptConfig: vfs.CryptFsConfig{
  924. Passphrase: kms.NewPlainSecret("crypto secret"),
  925. },
  926. }
  927. folderCopy = folder.GetACopy()
  928. folder.FsConfig.CryptConfig.Passphrase = kms.NewEmptySecret()
  929. require.Len(t, folderCopy.Users, 1)
  930. require.True(t, util.Contains(folderCopy.Users, "user3"))
  931. require.Equal(t, int64(2), folderCopy.ID)
  932. require.Equal(t, folder.Name, folderCopy.Name)
  933. require.Equal(t, folder.MappedPath, folderCopy.MappedPath)
  934. require.Equal(t, folder.UsedQuotaSize, folderCopy.UsedQuotaSize)
  935. require.Equal(t, folder.UsedQuotaFiles, folderCopy.UsedQuotaFiles)
  936. require.Equal(t, folder.LastQuotaUpdate, folderCopy.LastQuotaUpdate)
  937. require.Equal(t, "crypto secret", folderCopy.FsConfig.CryptConfig.Passphrase.GetPayload())
  938. }
  939. func TestCachedFs(t *testing.T) {
  940. user := dataprovider.User{
  941. BaseUser: sdk.BaseUser{
  942. HomeDir: filepath.Clean(os.TempDir()),
  943. },
  944. }
  945. conn := NewBaseConnection("id", ProtocolSFTP, "", "", user)
  946. // changing the user should not affect the connection
  947. user.HomeDir = filepath.Join(os.TempDir(), "temp")
  948. err := os.Mkdir(user.HomeDir, os.ModePerm)
  949. assert.NoError(t, err)
  950. fs, err := user.GetFilesystem("")
  951. assert.NoError(t, err)
  952. p, err := fs.ResolvePath("/")
  953. assert.NoError(t, err)
  954. assert.Equal(t, user.GetHomeDir(), p)
  955. _, p, err = conn.GetFsAndResolvedPath("/")
  956. assert.NoError(t, err)
  957. assert.Equal(t, filepath.Clean(os.TempDir()), p)
  958. // the filesystem is cached changing the provider will not affect the connection
  959. conn.User.FsConfig.Provider = sdk.S3FilesystemProvider
  960. _, p, err = conn.GetFsAndResolvedPath("/")
  961. assert.NoError(t, err)
  962. assert.Equal(t, filepath.Clean(os.TempDir()), p)
  963. user = dataprovider.User{}
  964. user.HomeDir = filepath.Join(os.TempDir(), "temp")
  965. user.FsConfig.Provider = sdk.S3FilesystemProvider
  966. _, err = user.GetFilesystem("")
  967. assert.Error(t, err)
  968. err = os.Remove(user.HomeDir)
  969. assert.NoError(t, err)
  970. }
  971. func TestParseAllowedIPAndRanges(t *testing.T) {
  972. _, err := util.ParseAllowedIPAndRanges([]string{"1.1.1.1", "not an ip"})
  973. assert.Error(t, err)
  974. _, err = util.ParseAllowedIPAndRanges([]string{"1.1.1.5", "192.168.1.0/240"})
  975. assert.Error(t, err)
  976. allow, err := util.ParseAllowedIPAndRanges([]string{"192.168.1.2", "172.16.0.0/24"})
  977. assert.NoError(t, err)
  978. assert.True(t, allow[0](net.ParseIP("192.168.1.2")))
  979. assert.False(t, allow[0](net.ParseIP("192.168.2.2")))
  980. assert.True(t, allow[1](net.ParseIP("172.16.0.1")))
  981. assert.False(t, allow[1](net.ParseIP("172.16.1.1")))
  982. }
  983. func TestHideConfidentialData(t *testing.T) {
  984. for _, provider := range []sdk.FilesystemProvider{sdk.LocalFilesystemProvider,
  985. sdk.CryptedFilesystemProvider, sdk.S3FilesystemProvider, sdk.GCSFilesystemProvider,
  986. sdk.AzureBlobFilesystemProvider, sdk.SFTPFilesystemProvider,
  987. } {
  988. u := dataprovider.User{
  989. FsConfig: vfs.Filesystem{
  990. Provider: provider,
  991. },
  992. }
  993. u.PrepareForRendering()
  994. f := vfs.BaseVirtualFolder{
  995. FsConfig: vfs.Filesystem{
  996. Provider: provider,
  997. },
  998. }
  999. f.PrepareForRendering()
  1000. }
  1001. a := dataprovider.Admin{}
  1002. a.HideConfidentialData()
  1003. }
  1004. func TestUserPerms(t *testing.T) {
  1005. u := dataprovider.User{}
  1006. u.Permissions = make(map[string][]string)
  1007. u.Permissions["/"] = []string{dataprovider.PermUpload, dataprovider.PermDelete}
  1008. assert.True(t, u.HasAnyPerm([]string{dataprovider.PermRename, dataprovider.PermDelete}, "/"))
  1009. assert.False(t, u.HasAnyPerm([]string{dataprovider.PermRename, dataprovider.PermCreateDirs}, "/"))
  1010. u.Permissions["/"] = []string{dataprovider.PermDelete, dataprovider.PermCreateDirs}
  1011. assert.True(t, u.HasPermsDeleteAll("/"))
  1012. assert.False(t, u.HasPermsRenameAll("/"))
  1013. u.Permissions["/"] = []string{dataprovider.PermDeleteDirs, dataprovider.PermDeleteFiles, dataprovider.PermRenameDirs}
  1014. assert.True(t, u.HasPermsDeleteAll("/"))
  1015. assert.False(t, u.HasPermsRenameAll("/"))
  1016. u.Permissions["/"] = []string{dataprovider.PermDeleteDirs, dataprovider.PermRenameFiles, dataprovider.PermRenameDirs}
  1017. assert.False(t, u.HasPermsDeleteAll("/"))
  1018. assert.True(t, u.HasPermsRenameAll("/"))
  1019. }
  1020. func TestGetTLSVersion(t *testing.T) {
  1021. tlsVer := util.GetTLSVersion(0)
  1022. assert.Equal(t, uint16(tls.VersionTLS12), tlsVer)
  1023. tlsVer = util.GetTLSVersion(12)
  1024. assert.Equal(t, uint16(tls.VersionTLS12), tlsVer)
  1025. tlsVer = util.GetTLSVersion(2)
  1026. assert.Equal(t, uint16(tls.VersionTLS12), tlsVer)
  1027. tlsVer = util.GetTLSVersion(13)
  1028. assert.Equal(t, uint16(tls.VersionTLS13), tlsVer)
  1029. }
  1030. func TestCleanPath(t *testing.T) {
  1031. assert.Equal(t, "/", util.CleanPath("/"))
  1032. assert.Equal(t, "/", util.CleanPath("."))
  1033. assert.Equal(t, "/", util.CleanPath(""))
  1034. assert.Equal(t, "/", util.CleanPath("/."))
  1035. assert.Equal(t, "/", util.CleanPath("/a/.."))
  1036. assert.Equal(t, "/a", util.CleanPath("/a/"))
  1037. assert.Equal(t, "/a", util.CleanPath("a/"))
  1038. // filepath.ToSlash does not touch \ as char on unix systems
  1039. // so os.PathSeparator is used for windows compatible tests
  1040. bslash := string(os.PathSeparator)
  1041. assert.Equal(t, "/", util.CleanPath(bslash))
  1042. assert.Equal(t, "/", util.CleanPath(bslash+bslash))
  1043. assert.Equal(t, "/a", util.CleanPath(bslash+"a"+bslash))
  1044. assert.Equal(t, "/a", util.CleanPath("a"+bslash))
  1045. assert.Equal(t, "/a/b/c", util.CleanPath(bslash+"a"+bslash+bslash+"b"+bslash+bslash+"c"+bslash))
  1046. assert.Equal(t, "/C:/a", util.CleanPath("C:"+bslash+"a"))
  1047. }
  1048. func TestUserRecentActivity(t *testing.T) {
  1049. u := dataprovider.User{}
  1050. res := u.HasRecentActivity()
  1051. assert.False(t, res)
  1052. u.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
  1053. res = u.HasRecentActivity()
  1054. assert.True(t, res)
  1055. u.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now().Add(1 * time.Minute))
  1056. res = u.HasRecentActivity()
  1057. assert.False(t, res)
  1058. u.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now().Add(1 * time.Second))
  1059. res = u.HasRecentActivity()
  1060. assert.True(t, res)
  1061. }
  1062. func TestVfsSameResource(t *testing.T) {
  1063. fs := vfs.Filesystem{}
  1064. other := vfs.Filesystem{}
  1065. res := fs.IsSameResource(other)
  1066. assert.True(t, res)
  1067. fs = vfs.Filesystem{
  1068. Provider: sdk.S3FilesystemProvider,
  1069. S3Config: vfs.S3FsConfig{
  1070. BaseS3FsConfig: sdk.BaseS3FsConfig{
  1071. Bucket: "a",
  1072. Region: "b",
  1073. },
  1074. },
  1075. }
  1076. other = vfs.Filesystem{
  1077. Provider: sdk.S3FilesystemProvider,
  1078. S3Config: vfs.S3FsConfig{
  1079. BaseS3FsConfig: sdk.BaseS3FsConfig{
  1080. Bucket: "a",
  1081. Region: "c",
  1082. },
  1083. },
  1084. }
  1085. res = fs.IsSameResource(other)
  1086. assert.False(t, res)
  1087. other = vfs.Filesystem{
  1088. Provider: sdk.S3FilesystemProvider,
  1089. S3Config: vfs.S3FsConfig{
  1090. BaseS3FsConfig: sdk.BaseS3FsConfig{
  1091. Bucket: "a",
  1092. Region: "b",
  1093. },
  1094. },
  1095. }
  1096. res = fs.IsSameResource(other)
  1097. assert.True(t, res)
  1098. fs = vfs.Filesystem{
  1099. Provider: sdk.GCSFilesystemProvider,
  1100. GCSConfig: vfs.GCSFsConfig{
  1101. BaseGCSFsConfig: sdk.BaseGCSFsConfig{
  1102. Bucket: "b",
  1103. },
  1104. },
  1105. }
  1106. other = vfs.Filesystem{
  1107. Provider: sdk.GCSFilesystemProvider,
  1108. GCSConfig: vfs.GCSFsConfig{
  1109. BaseGCSFsConfig: sdk.BaseGCSFsConfig{
  1110. Bucket: "c",
  1111. },
  1112. },
  1113. }
  1114. res = fs.IsSameResource(other)
  1115. assert.False(t, res)
  1116. other = vfs.Filesystem{
  1117. Provider: sdk.GCSFilesystemProvider,
  1118. GCSConfig: vfs.GCSFsConfig{
  1119. BaseGCSFsConfig: sdk.BaseGCSFsConfig{
  1120. Bucket: "b",
  1121. },
  1122. },
  1123. }
  1124. res = fs.IsSameResource(other)
  1125. assert.True(t, res)
  1126. sasURL := kms.NewPlainSecret("http://127.0.0.1/sasurl")
  1127. fs = vfs.Filesystem{
  1128. Provider: sdk.AzureBlobFilesystemProvider,
  1129. AzBlobConfig: vfs.AzBlobFsConfig{
  1130. BaseAzBlobFsConfig: sdk.BaseAzBlobFsConfig{
  1131. AccountName: "a",
  1132. },
  1133. SASURL: sasURL,
  1134. },
  1135. }
  1136. err := fs.Validate("data1")
  1137. assert.NoError(t, err)
  1138. other = vfs.Filesystem{
  1139. Provider: sdk.AzureBlobFilesystemProvider,
  1140. AzBlobConfig: vfs.AzBlobFsConfig{
  1141. BaseAzBlobFsConfig: sdk.BaseAzBlobFsConfig{
  1142. AccountName: "a",
  1143. },
  1144. SASURL: sasURL,
  1145. },
  1146. }
  1147. err = other.Validate("data2")
  1148. assert.NoError(t, err)
  1149. err = fs.AzBlobConfig.SASURL.TryDecrypt()
  1150. assert.NoError(t, err)
  1151. err = other.AzBlobConfig.SASURL.TryDecrypt()
  1152. assert.NoError(t, err)
  1153. res = fs.IsSameResource(other)
  1154. assert.True(t, res)
  1155. fs.AzBlobConfig.AccountName = "b"
  1156. res = fs.IsSameResource(other)
  1157. assert.False(t, res)
  1158. fs.AzBlobConfig.AccountName = "a"
  1159. other.AzBlobConfig.SASURL = kms.NewPlainSecret("http://127.1.1.1/sasurl")
  1160. err = other.Validate("data2")
  1161. assert.NoError(t, err)
  1162. err = other.AzBlobConfig.SASURL.TryDecrypt()
  1163. assert.NoError(t, err)
  1164. res = fs.IsSameResource(other)
  1165. assert.False(t, res)
  1166. fs = vfs.Filesystem{
  1167. Provider: sdk.HTTPFilesystemProvider,
  1168. HTTPConfig: vfs.HTTPFsConfig{
  1169. BaseHTTPFsConfig: sdk.BaseHTTPFsConfig{
  1170. Endpoint: "http://127.0.0.1/httpfs",
  1171. Username: "a",
  1172. },
  1173. },
  1174. }
  1175. other = vfs.Filesystem{
  1176. Provider: sdk.HTTPFilesystemProvider,
  1177. HTTPConfig: vfs.HTTPFsConfig{
  1178. BaseHTTPFsConfig: sdk.BaseHTTPFsConfig{
  1179. Endpoint: "http://127.0.0.1/httpfs",
  1180. Username: "b",
  1181. },
  1182. },
  1183. }
  1184. res = fs.IsSameResource(other)
  1185. assert.True(t, res)
  1186. fs.HTTPConfig.EqualityCheckMode = 1
  1187. res = fs.IsSameResource(other)
  1188. assert.False(t, res)
  1189. }
  1190. func TestUpdateTransferTimestamps(t *testing.T) {
  1191. username := "user_test_timestamps"
  1192. user := &dataprovider.User{
  1193. BaseUser: sdk.BaseUser{
  1194. Username: username,
  1195. HomeDir: filepath.Join(os.TempDir(), username),
  1196. Status: 1,
  1197. Permissions: map[string][]string{
  1198. "/": {dataprovider.PermAny},
  1199. },
  1200. },
  1201. }
  1202. err := dataprovider.AddUser(user, "", "")
  1203. assert.NoError(t, err)
  1204. assert.Equal(t, int64(0), user.FirstUpload)
  1205. assert.Equal(t, int64(0), user.FirstDownload)
  1206. err = dataprovider.UpdateUserTransferTimestamps(username, true)
  1207. assert.NoError(t, err)
  1208. userGet, err := dataprovider.UserExists(username)
  1209. assert.NoError(t, err)
  1210. assert.Greater(t, userGet.FirstUpload, int64(0))
  1211. assert.Equal(t, int64(0), user.FirstDownload)
  1212. err = dataprovider.UpdateUserTransferTimestamps(username, false)
  1213. assert.NoError(t, err)
  1214. userGet, err = dataprovider.UserExists(username)
  1215. assert.NoError(t, err)
  1216. assert.Greater(t, userGet.FirstUpload, int64(0))
  1217. assert.Greater(t, userGet.FirstDownload, int64(0))
  1218. // updating again must fail
  1219. err = dataprovider.UpdateUserTransferTimestamps(username, true)
  1220. assert.Error(t, err)
  1221. err = dataprovider.UpdateUserTransferTimestamps(username, false)
  1222. assert.Error(t, err)
  1223. // cleanup
  1224. err = dataprovider.DeleteUser(username, "", "")
  1225. assert.NoError(t, err)
  1226. }
  1227. func TestMetadataAPI(t *testing.T) {
  1228. username := "metadatauser"
  1229. require.False(t, ActiveMetadataChecks.Remove(username))
  1230. require.True(t, ActiveMetadataChecks.Add(username))
  1231. require.False(t, ActiveMetadataChecks.Add(username))
  1232. checks := ActiveMetadataChecks.Get()
  1233. require.Len(t, checks, 1)
  1234. checks[0].Username = username + "a"
  1235. checks = ActiveMetadataChecks.Get()
  1236. require.Len(t, checks, 1)
  1237. require.Equal(t, username, checks[0].Username)
  1238. require.True(t, ActiveMetadataChecks.Remove(username))
  1239. require.Len(t, ActiveMetadataChecks.Get(), 0)
  1240. }
  1241. func BenchmarkBcryptHashing(b *testing.B) {
  1242. bcryptPassword := "bcryptpassword"
  1243. for i := 0; i < b.N; i++ {
  1244. _, err := bcrypt.GenerateFromPassword([]byte(bcryptPassword), 10)
  1245. if err != nil {
  1246. panic(err)
  1247. }
  1248. }
  1249. }
  1250. func BenchmarkCompareBcryptPassword(b *testing.B) {
  1251. bcryptPassword := "$2a$10$lPDdnDimJZ7d5/GwL6xDuOqoZVRXok6OHHhivCnanWUtcgN0Zafki"
  1252. for i := 0; i < b.N; i++ {
  1253. err := bcrypt.CompareHashAndPassword([]byte(bcryptPassword), []byte("password"))
  1254. if err != nil {
  1255. panic(err)
  1256. }
  1257. }
  1258. }
  1259. func BenchmarkArgon2Hashing(b *testing.B) {
  1260. argonPassword := "argon2password"
  1261. for i := 0; i < b.N; i++ {
  1262. _, err := argon2id.CreateHash(argonPassword, argon2id.DefaultParams)
  1263. if err != nil {
  1264. panic(err)
  1265. }
  1266. }
  1267. }
  1268. func BenchmarkCompareArgon2Password(b *testing.B) {
  1269. argon2Password := "$argon2id$v=19$m=65536,t=1,p=2$aOoAOdAwvzhOgi7wUFjXlw$wn/y37dBWdKHtPXHR03nNaKHWKPXyNuVXOknaU+YZ+s"
  1270. for i := 0; i < b.N; i++ {
  1271. _, err := argon2id.ComparePasswordAndHash("password", argon2Password)
  1272. if err != nil {
  1273. panic(err)
  1274. }
  1275. }
  1276. }
  1277. func BenchmarkAddRemoveConnections(b *testing.B) {
  1278. var conns []ActiveConnection
  1279. for i := 0; i < 100; i++ {
  1280. conns = append(conns, &fakeConnection{
  1281. BaseConnection: NewBaseConnection(fmt.Sprintf("id%d", i), ProtocolSFTP, "", "", dataprovider.User{
  1282. BaseUser: sdk.BaseUser{
  1283. Username: userTestUsername,
  1284. },
  1285. }),
  1286. })
  1287. }
  1288. b.ResetTimer()
  1289. for i := 0; i < b.N; i++ {
  1290. for _, c := range conns {
  1291. if err := Connections.Add(c); err != nil {
  1292. panic(err)
  1293. }
  1294. }
  1295. var wg sync.WaitGroup
  1296. for idx := len(conns) - 1; idx >= 0; idx-- {
  1297. wg.Add(1)
  1298. go func(index int) {
  1299. defer wg.Done()
  1300. Connections.Remove(conns[index].GetID())
  1301. }(idx)
  1302. }
  1303. wg.Wait()
  1304. }
  1305. }
  1306. func BenchmarkAddRemoveSSHConnections(b *testing.B) {
  1307. conn1, conn2 := net.Pipe()
  1308. var conns []*SSHConnection
  1309. for i := 0; i < 2000; i++ {
  1310. conns = append(conns, NewSSHConnection(fmt.Sprintf("id%d", i), conn1))
  1311. }
  1312. b.ResetTimer()
  1313. for i := 0; i < b.N; i++ {
  1314. for _, c := range conns {
  1315. Connections.AddSSHConnection(c)
  1316. }
  1317. for idx := len(conns) - 1; idx >= 0; idx-- {
  1318. Connections.RemoveSSHConnection(conns[idx].GetID())
  1319. }
  1320. }
  1321. conn1.Close()
  1322. conn2.Close()
  1323. }