internal_test.go 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908
  1. package sftpd
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "net"
  9. "os"
  10. "os/exec"
  11. "path"
  12. "path/filepath"
  13. "runtime"
  14. "sync"
  15. "testing"
  16. "time"
  17. "github.com/eikenb/pipeat"
  18. "github.com/pkg/sftp"
  19. "github.com/stretchr/testify/assert"
  20. "golang.org/x/crypto/ssh"
  21. "github.com/drakkan/sftpgo/dataprovider"
  22. "github.com/drakkan/sftpgo/utils"
  23. "github.com/drakkan/sftpgo/vfs"
  24. )
  25. const osWindows = "windows"
  26. type MockChannel struct {
  27. Buffer *bytes.Buffer
  28. StdErrBuffer *bytes.Buffer
  29. ReadError error
  30. WriteError error
  31. ShortWriteErr bool
  32. }
  33. func (c *MockChannel) Read(data []byte) (int, error) {
  34. if c.ReadError != nil {
  35. return 0, c.ReadError
  36. }
  37. return c.Buffer.Read(data)
  38. }
  39. func (c *MockChannel) Write(data []byte) (int, error) {
  40. if c.WriteError != nil {
  41. return 0, c.WriteError
  42. }
  43. if c.ShortWriteErr {
  44. return 0, nil
  45. }
  46. return c.Buffer.Write(data)
  47. }
  48. func (c *MockChannel) Close() error {
  49. return nil
  50. }
  51. func (c *MockChannel) CloseWrite() error {
  52. return nil
  53. }
  54. func (c *MockChannel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
  55. return true, nil
  56. }
  57. func (c *MockChannel) Stderr() io.ReadWriter {
  58. return c.StdErrBuffer
  59. }
  60. // MockOsFs mockable OsFs
  61. type MockOsFs struct {
  62. vfs.Fs
  63. err error
  64. statErr error
  65. isAtomicUploadSupported bool
  66. }
  67. // Name returns the name for the Fs implementation
  68. func (fs MockOsFs) Name() string {
  69. return "mockOsFs"
  70. }
  71. // IsUploadResumeSupported returns true if upload resume is supported
  72. func (MockOsFs) IsUploadResumeSupported() bool {
  73. return false
  74. }
  75. // IsAtomicUploadSupported returns true if atomic upload is supported
  76. func (fs MockOsFs) IsAtomicUploadSupported() bool {
  77. return fs.isAtomicUploadSupported
  78. }
  79. // Stat returns a FileInfo describing the named file
  80. func (fs MockOsFs) Stat(name string) (os.FileInfo, error) {
  81. if fs.statErr != nil {
  82. return nil, fs.statErr
  83. }
  84. return os.Stat(name)
  85. }
  86. // Lstat returns a FileInfo describing the named file
  87. func (fs MockOsFs) Lstat(name string) (os.FileInfo, error) {
  88. if fs.statErr != nil {
  89. return nil, fs.statErr
  90. }
  91. return os.Lstat(name)
  92. }
  93. // Remove removes the named file or (empty) directory.
  94. func (fs MockOsFs) Remove(name string, isDir bool) error {
  95. if fs.err != nil {
  96. return fs.err
  97. }
  98. return os.Remove(name)
  99. }
  100. // Rename renames (moves) source to target
  101. func (fs MockOsFs) Rename(source, target string) error {
  102. if fs.err != nil {
  103. return fs.err
  104. }
  105. return os.Rename(source, target)
  106. }
  107. func newMockOsFs(err, statErr error, atomicUpload bool, connectionID, rootDir string) vfs.Fs {
  108. return &MockOsFs{
  109. Fs: vfs.NewOsFs(connectionID, rootDir, nil),
  110. err: err,
  111. statErr: statErr,
  112. isAtomicUploadSupported: atomicUpload,
  113. }
  114. }
  115. func TestNewActionNotification(t *testing.T) {
  116. user := dataprovider.User{
  117. Username: "username",
  118. }
  119. user.FsConfig.Provider = 0
  120. user.FsConfig.S3Config = vfs.S3FsConfig{
  121. Bucket: "s3bucket",
  122. Endpoint: "endpoint",
  123. }
  124. user.FsConfig.GCSConfig = vfs.GCSFsConfig{
  125. Bucket: "gcsbucket",
  126. }
  127. a := newActionNotification(user, operationDownload, "path", "target", "", 123, nil)
  128. assert.Equal(t, user.Username, a.Username)
  129. assert.Equal(t, 0, len(a.Bucket))
  130. assert.Equal(t, 0, len(a.Endpoint))
  131. user.FsConfig.Provider = 1
  132. a = newActionNotification(user, operationDownload, "path", "target", "", 123, nil)
  133. assert.Equal(t, "s3bucket", a.Bucket)
  134. assert.Equal(t, "endpoint", a.Endpoint)
  135. user.FsConfig.Provider = 2
  136. a = newActionNotification(user, operationDownload, "path", "target", "", 123, nil)
  137. assert.Equal(t, "gcsbucket", a.Bucket)
  138. assert.Equal(t, 0, len(a.Endpoint))
  139. }
  140. func TestWrongActions(t *testing.T) {
  141. actionsCopy := actions
  142. badCommand := "/bad/command"
  143. if runtime.GOOS == osWindows {
  144. badCommand = "C:\\bad\\command"
  145. }
  146. actions = Actions{
  147. ExecuteOn: []string{operationDownload},
  148. Hook: badCommand,
  149. }
  150. user := dataprovider.User{
  151. Username: "username",
  152. }
  153. err := executeAction(newActionNotification(user, operationDownload, "path", "", "", 0, nil))
  154. assert.Error(t, err, "action with bad command must fail")
  155. err = executeAction(newActionNotification(user, operationDelete, "path", "", "", 0, nil))
  156. assert.EqualError(t, err, errUnconfiguredAction.Error())
  157. actions.Hook = "http://foo\x7f.com/"
  158. err = executeAction(newActionNotification(user, operationDownload, "path", "", "", 0, nil))
  159. assert.Error(t, err, "action with bad url must fail")
  160. actions.Hook = ""
  161. err = executeAction(newActionNotification(user, operationDownload, "path", "", "", 0, nil))
  162. assert.Error(t, err, errNoHook.Error())
  163. actions.Hook = "relative path"
  164. err = executeNotificationCommand(newActionNotification(user, operationDownload, "path", "", "", 0, nil))
  165. assert.EqualError(t, err, fmt.Sprintf("invalid notification command %#v", actions.Hook))
  166. actions = actionsCopy
  167. }
  168. func TestActionHTTP(t *testing.T) {
  169. actionsCopy := actions
  170. actions = Actions{
  171. ExecuteOn: []string{operationDownload},
  172. Hook: "http://127.0.0.1:8080/",
  173. }
  174. user := dataprovider.User{
  175. Username: "username",
  176. }
  177. err := executeAction(newActionNotification(user, operationDownload, "path", "", "", 0, nil))
  178. assert.EqualError(t, err, errUnexpectedHTTResponse.Error())
  179. actions = actionsCopy
  180. }
  181. func TestPreDeleteAction(t *testing.T) {
  182. if runtime.GOOS == osWindows {
  183. t.Skip("this test is not available on Windows")
  184. }
  185. actionsCopy := actions
  186. hookCmd, err := exec.LookPath("true")
  187. assert.NoError(t, err)
  188. actions = Actions{
  189. ExecuteOn: []string{operationPreDelete},
  190. Hook: hookCmd,
  191. }
  192. homeDir := filepath.Join(os.TempDir(), "test_user")
  193. err = os.MkdirAll(homeDir, os.ModePerm)
  194. assert.NoError(t, err)
  195. user := dataprovider.User{
  196. Username: "username",
  197. HomeDir: homeDir,
  198. }
  199. user.Permissions = make(map[string][]string)
  200. user.Permissions["/"] = []string{dataprovider.PermAny}
  201. c := Connection{
  202. fs: vfs.NewOsFs("id", homeDir, nil),
  203. User: user,
  204. }
  205. testfile := filepath.Join(user.HomeDir, "testfile")
  206. request := sftp.NewRequest("Remove", "/testfile")
  207. err = ioutil.WriteFile(testfile, []byte("test"), 0666)
  208. assert.NoError(t, err)
  209. err = c.handleSFTPRemove(testfile, request)
  210. assert.EqualError(t, err, sftp.ErrSSHFxOk.Error())
  211. assert.FileExists(t, testfile)
  212. os.RemoveAll(homeDir)
  213. actions = actionsCopy
  214. }
  215. func TestRemoveNonexistentTransfer(t *testing.T) {
  216. transfer := Transfer{}
  217. err := removeTransfer(&transfer)
  218. assert.Error(t, err, "remove nonexistent transfer must fail")
  219. }
  220. func TestRemoveNonexistentQuotaScan(t *testing.T) {
  221. err := RemoveQuotaScan("username")
  222. assert.Error(t, err, "remove nonexistent quota scan must fail")
  223. }
  224. func TestGetOSOpenFlags(t *testing.T) {
  225. var flags sftp.FileOpenFlags
  226. flags.Write = true
  227. flags.Excl = true
  228. osFlags := getOSOpenFlags(flags)
  229. assert.NotEqual(t, 0, osFlags&os.O_WRONLY)
  230. assert.NotEqual(t, 0, osFlags&os.O_EXCL)
  231. flags.Append = true
  232. // append flag should be ignored to allow resume
  233. assert.NotEqual(t, 0, osFlags&os.O_WRONLY)
  234. assert.NotEqual(t, 0, osFlags&os.O_EXCL)
  235. }
  236. func TestUploadResumeInvalidOffset(t *testing.T) {
  237. testfile := "testfile" //nolint:goconst
  238. file, err := os.Create(testfile)
  239. assert.NoError(t, err)
  240. transfer := Transfer{
  241. file: file,
  242. path: file.Name(),
  243. start: time.Now(),
  244. bytesSent: 0,
  245. bytesReceived: 0,
  246. user: dataprovider.User{
  247. Username: "testuser",
  248. },
  249. connectionID: "",
  250. transferType: transferUpload,
  251. lastActivity: time.Now(),
  252. isNewFile: false,
  253. protocol: protocolSFTP,
  254. transferError: nil,
  255. isFinished: false,
  256. minWriteOffset: 10,
  257. lock: new(sync.Mutex),
  258. }
  259. _, err = transfer.WriteAt([]byte("test"), 0)
  260. assert.Error(t, err, "upload with invalid offset must fail")
  261. err = transfer.Close()
  262. if assert.Error(t, err) {
  263. assert.Contains(t, err.Error(), "Invalid write offset")
  264. }
  265. err = os.Remove(testfile)
  266. assert.NoError(t, err)
  267. }
  268. func TestReadWriteErrors(t *testing.T) {
  269. testfile := "testfile"
  270. file, err := os.Create(testfile)
  271. assert.NoError(t, err)
  272. transfer := Transfer{
  273. file: file,
  274. path: file.Name(),
  275. start: time.Now(),
  276. bytesSent: 0,
  277. bytesReceived: 0,
  278. user: dataprovider.User{
  279. Username: "testuser",
  280. },
  281. connectionID: "",
  282. transferType: transferDownload,
  283. lastActivity: time.Now(),
  284. isNewFile: false,
  285. protocol: protocolSFTP,
  286. transferError: nil,
  287. isFinished: false,
  288. minWriteOffset: 0,
  289. lock: new(sync.Mutex),
  290. }
  291. err = file.Close()
  292. assert.NoError(t, err)
  293. _, err = transfer.WriteAt([]byte("test"), 0)
  294. assert.Error(t, err, "writing to closed file must fail")
  295. buf := make([]byte, 32768)
  296. _, err = transfer.ReadAt(buf, 0)
  297. assert.Error(t, err, "reading from a closed file must fail")
  298. err = transfer.Close()
  299. assert.Error(t, err)
  300. r, _, err := pipeat.Pipe()
  301. assert.NoError(t, err)
  302. transfer = Transfer{
  303. readerAt: r,
  304. writerAt: nil,
  305. start: time.Now(),
  306. bytesSent: 0,
  307. bytesReceived: 0,
  308. user: dataprovider.User{
  309. Username: "testuser",
  310. },
  311. connectionID: "",
  312. transferType: transferDownload,
  313. lastActivity: time.Now(),
  314. isNewFile: false,
  315. protocol: protocolSFTP,
  316. transferError: nil,
  317. isFinished: false,
  318. lock: new(sync.Mutex),
  319. }
  320. err = transfer.closeIO()
  321. assert.NoError(t, err)
  322. _, err = transfer.ReadAt(buf, 0)
  323. assert.Error(t, err, "reading from a closed pipe must fail")
  324. r, w, err := pipeat.Pipe()
  325. assert.NoError(t, err)
  326. transfer = Transfer{
  327. readerAt: nil,
  328. writerAt: vfs.NewPipeWriter(w),
  329. start: time.Now(),
  330. bytesSent: 0,
  331. bytesReceived: 0,
  332. user: dataprovider.User{
  333. Username: "testuser",
  334. },
  335. connectionID: "",
  336. transferType: transferDownload,
  337. lastActivity: time.Now(),
  338. isNewFile: false,
  339. protocol: protocolSFTP,
  340. transferError: nil,
  341. isFinished: false,
  342. lock: new(sync.Mutex),
  343. }
  344. err = r.Close()
  345. assert.NoError(t, err)
  346. errFake := fmt.Errorf("fake upload error")
  347. go func() {
  348. time.Sleep(100 * time.Millisecond)
  349. transfer.writerAt.Done(errFake)
  350. }()
  351. err = transfer.closeIO()
  352. assert.EqualError(t, err, errFake.Error())
  353. _, err = transfer.WriteAt([]byte("test"), 0)
  354. assert.Error(t, err, "writing to closed pipe must fail")
  355. err = os.Remove(testfile)
  356. assert.NoError(t, err)
  357. }
  358. func TestTransferCancelFn(t *testing.T) {
  359. testfile := "testfile"
  360. file, err := os.Create(testfile)
  361. assert.NoError(t, err)
  362. isCancelled := false
  363. cancelFn := func() {
  364. isCancelled = true
  365. }
  366. transfer := Transfer{
  367. file: file,
  368. cancelFn: cancelFn,
  369. path: file.Name(),
  370. start: time.Now(),
  371. bytesSent: 0,
  372. bytesReceived: 0,
  373. user: dataprovider.User{
  374. Username: "testuser",
  375. },
  376. connectionID: "",
  377. transferType: transferDownload,
  378. lastActivity: time.Now(),
  379. isNewFile: false,
  380. protocol: protocolSFTP,
  381. transferError: nil,
  382. isFinished: false,
  383. minWriteOffset: 0,
  384. lock: new(sync.Mutex),
  385. }
  386. errFake := errors.New("fake error, this will trigger cancelFn")
  387. transfer.TransferError(errFake)
  388. err = transfer.Close()
  389. assert.EqualError(t, err, errFake.Error())
  390. assert.True(t, isCancelled, "cancelFn not called!")
  391. err = os.Remove(testfile)
  392. assert.NoError(t, err)
  393. }
  394. func TestMockFsErrors(t *testing.T) {
  395. errFake := errors.New("fake error")
  396. fs := newMockOsFs(errFake, errFake, false, "123", os.TempDir())
  397. u := dataprovider.User{}
  398. u.Username = "test_username"
  399. u.Permissions = make(map[string][]string)
  400. u.Permissions["/"] = []string{dataprovider.PermAny}
  401. u.HomeDir = os.TempDir()
  402. c := Connection{
  403. fs: fs,
  404. User: u,
  405. }
  406. testfile := filepath.Join(u.HomeDir, "testfile")
  407. request := sftp.NewRequest("Remove", testfile)
  408. err := ioutil.WriteFile(testfile, []byte("test"), 0666)
  409. assert.NoError(t, err)
  410. _, err = c.Filewrite(request)
  411. assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
  412. var flags sftp.FileOpenFlags
  413. flags.Write = true
  414. flags.Trunc = false
  415. flags.Append = true
  416. _, err = c.handleSFTPUploadToExistingFile(flags, testfile, testfile, 0, "/testfile")
  417. assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
  418. fs = newMockOsFs(errFake, nil, false, "123", os.TempDir())
  419. c.fs = fs
  420. err = c.handleSFTPRemove(testfile, request)
  421. assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
  422. err = os.Remove(testfile)
  423. assert.NoError(t, err)
  424. }
  425. func TestUploadFiles(t *testing.T) {
  426. oldUploadMode := uploadMode
  427. uploadMode = uploadModeAtomic
  428. c := Connection{
  429. fs: vfs.NewOsFs("123", os.TempDir(), nil),
  430. }
  431. var flags sftp.FileOpenFlags
  432. flags.Write = true
  433. flags.Trunc = true
  434. _, err := c.handleSFTPUploadToExistingFile(flags, "missing_path", "other_missing_path", 0, "/missing_path")
  435. assert.Error(t, err, "upload to existing file must fail if one or both paths are invalid")
  436. uploadMode = uploadModeStandard
  437. _, err = c.handleSFTPUploadToExistingFile(flags, "missing_path", "other_missing_path", 0, "/missing_path")
  438. assert.Error(t, err, "upload to existing file must fail if one or both paths are invalid")
  439. missingFile := "missing/relative/file.txt"
  440. if runtime.GOOS == osWindows {
  441. missingFile = "missing\\relative\\file.txt"
  442. }
  443. _, err = c.handleSFTPUploadToNewFile(".", missingFile, "/missing")
  444. assert.Error(t, err, "upload new file in missing path must fail")
  445. c.fs = newMockOsFs(nil, nil, false, "123", os.TempDir())
  446. f, err := ioutil.TempFile("", "temp")
  447. assert.NoError(t, err)
  448. err = f.Close()
  449. assert.NoError(t, err)
  450. _, err = c.handleSFTPUploadToExistingFile(flags, f.Name(), f.Name(), 123, f.Name())
  451. assert.NoError(t, err)
  452. if assert.Equal(t, 1, len(activeTransfers)) {
  453. transfer := activeTransfers[0]
  454. assert.Equal(t, int64(123), transfer.initialSize)
  455. err = transfer.Close()
  456. assert.NoError(t, err)
  457. assert.Equal(t, 0, len(activeTransfers))
  458. }
  459. err = os.Remove(f.Name())
  460. assert.NoError(t, err)
  461. uploadMode = oldUploadMode
  462. }
  463. func TestWithInvalidHome(t *testing.T) {
  464. u := dataprovider.User{}
  465. u.HomeDir = "home_rel_path" //nolint:goconst
  466. _, err := loginUser(u, dataprovider.SSHLoginMethodPassword, "", nil)
  467. assert.Error(t, err, "login a user with an invalid home_dir must fail")
  468. u.HomeDir = os.TempDir()
  469. fs, err := u.GetFilesystem("123")
  470. assert.NoError(t, err)
  471. c := Connection{
  472. User: u,
  473. fs: fs,
  474. }
  475. _, err = c.fs.ResolvePath("../upper_path")
  476. assert.Error(t, err, "tested path is not a home subdir")
  477. }
  478. func TestSFTPCmdTargetPath(t *testing.T) {
  479. u := dataprovider.User{}
  480. if runtime.GOOS == osWindows {
  481. u.HomeDir = "C:\\invalid_home"
  482. } else {
  483. u.HomeDir = "/invalid_home"
  484. }
  485. u.Username = "testuser"
  486. u.Permissions = make(map[string][]string)
  487. u.Permissions["/"] = []string{dataprovider.PermAny}
  488. fs, err := u.GetFilesystem("123")
  489. assert.NoError(t, err)
  490. connection := Connection{
  491. User: u,
  492. fs: fs,
  493. }
  494. _, err = connection.getSFTPCmdTargetPath("invalid_path")
  495. assert.EqualError(t, err, sftp.ErrSSHFxNoSuchFile.Error())
  496. }
  497. func TestGetSFTPErrorFromOSError(t *testing.T) {
  498. err := os.ErrNotExist
  499. fs := vfs.NewOsFs("", os.TempDir(), nil)
  500. err = vfs.GetSFTPError(fs, err)
  501. assert.EqualError(t, err, sftp.ErrSSHFxNoSuchFile.Error())
  502. err = os.ErrPermission
  503. err = vfs.GetSFTPError(fs, err)
  504. assert.EqualError(t, err, sftp.ErrSSHFxPermissionDenied.Error())
  505. err = vfs.GetSFTPError(fs, nil)
  506. assert.NoError(t, err)
  507. }
  508. func TestSetstatModeIgnore(t *testing.T) {
  509. originalMode := setstatMode
  510. setstatMode = 1
  511. connection := Connection{}
  512. err := connection.handleSFTPSetstat("invalid", nil)
  513. assert.NoError(t, err)
  514. setstatMode = originalMode
  515. }
  516. func TestSFTPGetUsedQuota(t *testing.T) {
  517. u := dataprovider.User{}
  518. u.HomeDir = "home_rel_path"
  519. u.Username = "test_invalid_user"
  520. u.QuotaSize = 4096
  521. u.QuotaFiles = 1
  522. u.Permissions = make(map[string][]string)
  523. u.Permissions["/"] = []string{dataprovider.PermAny}
  524. connection := Connection{
  525. User: u,
  526. }
  527. assert.False(t, connection.hasSpace(false, "/"))
  528. }
  529. func TestSupportedSSHCommands(t *testing.T) {
  530. cmds := GetSupportedSSHCommands()
  531. assert.Equal(t, len(supportedSSHCommands), len(cmds))
  532. for _, c := range cmds {
  533. assert.True(t, utils.IsStringInSlice(c, supportedSSHCommands))
  534. }
  535. }
  536. func TestSSHCommandPath(t *testing.T) {
  537. buf := make([]byte, 65535)
  538. stdErrBuf := make([]byte, 65535)
  539. mockSSHChannel := MockChannel{
  540. Buffer: bytes.NewBuffer(buf),
  541. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  542. ReadError: nil,
  543. }
  544. connection := Connection{
  545. channel: &mockSSHChannel,
  546. }
  547. sshCommand := sshCommand{
  548. command: "test",
  549. connection: connection,
  550. args: []string{},
  551. }
  552. assert.Equal(t, "", sshCommand.getDestPath())
  553. sshCommand.args = []string{"-t", "/tmp/../path"}
  554. assert.Equal(t, "/path", sshCommand.getDestPath())
  555. sshCommand.args = []string{"-t", "/tmp/"}
  556. assert.Equal(t, "/tmp/", sshCommand.getDestPath())
  557. sshCommand.args = []string{"-t", "tmp/"}
  558. assert.Equal(t, "/tmp/", sshCommand.getDestPath())
  559. sshCommand.args = []string{"-t", "/tmp/../../../path"}
  560. assert.Equal(t, "/path", sshCommand.getDestPath())
  561. sshCommand.args = []string{"-t", ".."}
  562. assert.Equal(t, "/", sshCommand.getDestPath())
  563. sshCommand.args = []string{"-t", "."}
  564. assert.Equal(t, "/", sshCommand.getDestPath())
  565. sshCommand.args = []string{"-t", "//"}
  566. assert.Equal(t, "/", sshCommand.getDestPath())
  567. sshCommand.args = []string{"-t", "../.."}
  568. assert.Equal(t, "/", sshCommand.getDestPath())
  569. sshCommand.args = []string{"-t", "/.."}
  570. assert.Equal(t, "/", sshCommand.getDestPath())
  571. sshCommand.args = []string{"-f", "/a space.txt"}
  572. assert.Equal(t, "/a space.txt", sshCommand.getDestPath())
  573. }
  574. func TestSSHParseCommandPayload(t *testing.T) {
  575. cmd := "command -a -f /ab\\ à/some\\ spaces\\ \\ \\(\\).txt"
  576. name, args, _ := parseCommandPayload(cmd)
  577. assert.Equal(t, "command", name)
  578. assert.Equal(t, 3, len(args))
  579. assert.Equal(t, "/ab à/some spaces ().txt", args[2])
  580. _, _, err := parseCommandPayload("")
  581. assert.Error(t, err, "parsing invalid command must fail")
  582. }
  583. func TestSSHCommandErrors(t *testing.T) {
  584. buf := make([]byte, 65535)
  585. stdErrBuf := make([]byte, 65535)
  586. readErr := fmt.Errorf("test read error")
  587. mockSSHChannel := MockChannel{
  588. Buffer: bytes.NewBuffer(buf),
  589. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  590. ReadError: readErr,
  591. }
  592. server, client := net.Pipe()
  593. defer func() {
  594. err := server.Close()
  595. assert.NoError(t, err)
  596. }()
  597. defer func() {
  598. err := client.Close()
  599. assert.NoError(t, err)
  600. }()
  601. user := dataprovider.User{}
  602. user.Permissions = make(map[string][]string)
  603. user.Permissions["/"] = []string{dataprovider.PermAny}
  604. fs, err := user.GetFilesystem("123")
  605. assert.NoError(t, err)
  606. connection := Connection{
  607. channel: &mockSSHChannel,
  608. netConn: client,
  609. User: user,
  610. fs: fs,
  611. }
  612. cmd := sshCommand{
  613. command: "md5sum",
  614. connection: connection,
  615. args: []string{},
  616. }
  617. err = cmd.handle()
  618. assert.Error(t, err, "ssh command must fail, we are sending a fake error")
  619. cmd = sshCommand{
  620. command: "md5sum",
  621. connection: connection,
  622. args: []string{"/../../test_file.dat"},
  623. }
  624. err = cmd.handle()
  625. assert.Error(t, err, "ssh command must fail, we are requesting an invalid path")
  626. cmd = sshCommand{
  627. command: "git-receive-pack",
  628. connection: connection,
  629. args: []string{"/../../testrepo"},
  630. }
  631. err = cmd.handle()
  632. assert.Error(t, err, "ssh command must fail, we are requesting an invalid path")
  633. cmd.connection.User.HomeDir = os.TempDir()
  634. cmd.connection.User.QuotaFiles = 1
  635. cmd.connection.User.UsedQuotaFiles = 2
  636. fs, err = cmd.connection.User.GetFilesystem("123")
  637. assert.NoError(t, err)
  638. cmd.connection.fs = fs
  639. err = cmd.handle()
  640. assert.EqualError(t, err, errQuotaExceeded.Error())
  641. cmd.connection.User.QuotaFiles = 0
  642. cmd.connection.User.UsedQuotaFiles = 0
  643. cmd.connection.User.Permissions = make(map[string][]string)
  644. cmd.connection.User.Permissions["/"] = []string{dataprovider.PermListItems}
  645. err = cmd.handle()
  646. assert.EqualError(t, err, errPermissionDenied.Error())
  647. cmd.connection.User.Permissions["/"] = []string{dataprovider.PermAny}
  648. cmd.command = "invalid_command"
  649. command, err := cmd.getSystemCommand()
  650. assert.NoError(t, err)
  651. err = cmd.executeSystemCommand(command)
  652. assert.Error(t, err, "invalid command must fail")
  653. command, err = cmd.getSystemCommand()
  654. assert.NoError(t, err)
  655. _, err = command.cmd.StderrPipe()
  656. assert.NoError(t, err)
  657. err = cmd.executeSystemCommand(command)
  658. assert.Error(t, err, "command must fail, pipe was already assigned")
  659. err = cmd.executeSystemCommand(command)
  660. assert.Error(t, err, "command must fail, pipe was already assigned")
  661. command, err = cmd.getSystemCommand()
  662. assert.NoError(t, err)
  663. _, err = command.cmd.StdoutPipe()
  664. assert.NoError(t, err)
  665. err = cmd.executeSystemCommand(command)
  666. assert.Error(t, err, "command must fail, pipe was already assigned")
  667. }
  668. func TestCommandsWithExtensionsFilter(t *testing.T) {
  669. buf := make([]byte, 65535)
  670. stdErrBuf := make([]byte, 65535)
  671. mockSSHChannel := MockChannel{
  672. Buffer: bytes.NewBuffer(buf),
  673. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  674. }
  675. server, client := net.Pipe()
  676. defer server.Close()
  677. defer client.Close()
  678. user := dataprovider.User{
  679. Username: "test",
  680. HomeDir: os.TempDir(),
  681. Status: 1,
  682. }
  683. user.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  684. {
  685. Path: "/subdir",
  686. AllowedExtensions: []string{".jpg"},
  687. DeniedExtensions: []string{},
  688. },
  689. }
  690. fs, err := user.GetFilesystem("123")
  691. assert.NoError(t, err)
  692. connection := Connection{
  693. channel: &mockSSHChannel,
  694. netConn: client,
  695. User: user,
  696. fs: fs,
  697. }
  698. cmd := sshCommand{
  699. command: "md5sum",
  700. connection: connection,
  701. args: []string{"subdir/test.png"},
  702. }
  703. err = cmd.handleHashCommands()
  704. assert.EqualError(t, err, errPermissionDenied.Error())
  705. cmd = sshCommand{
  706. command: "rsync",
  707. connection: connection,
  708. args: []string{"--server", "-vlogDtprze.iLsfxC", ".", "/"},
  709. }
  710. _, err = cmd.getSystemCommand()
  711. assert.EqualError(t, err, errUnsupportedConfig.Error())
  712. cmd = sshCommand{
  713. command: "git-receive-pack",
  714. connection: connection,
  715. args: []string{"/subdir"},
  716. }
  717. _, err = cmd.getSystemCommand()
  718. assert.EqualError(t, err, errUnsupportedConfig.Error())
  719. cmd = sshCommand{
  720. command: "git-receive-pack",
  721. connection: connection,
  722. args: []string{"/subdir/dir"},
  723. }
  724. _, err = cmd.getSystemCommand()
  725. assert.EqualError(t, err, errUnsupportedConfig.Error())
  726. cmd = sshCommand{
  727. command: "git-receive-pack",
  728. connection: connection,
  729. args: []string{"/adir/subdir"},
  730. }
  731. _, err = cmd.getSystemCommand()
  732. assert.NoError(t, err)
  733. }
  734. func TestSSHCommandsRemoteFs(t *testing.T) {
  735. buf := make([]byte, 65535)
  736. stdErrBuf := make([]byte, 65535)
  737. mockSSHChannel := MockChannel{
  738. Buffer: bytes.NewBuffer(buf),
  739. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  740. }
  741. server, client := net.Pipe()
  742. defer func() {
  743. err := server.Close()
  744. assert.NoError(t, err)
  745. }()
  746. defer func() {
  747. err := client.Close()
  748. assert.NoError(t, err)
  749. }()
  750. user := dataprovider.User{}
  751. user.FsConfig = dataprovider.Filesystem{
  752. Provider: 1,
  753. S3Config: vfs.S3FsConfig{
  754. Bucket: "s3bucket",
  755. Endpoint: "endpoint",
  756. Region: "eu-west-1",
  757. },
  758. }
  759. fs, err := user.GetFilesystem("123")
  760. assert.NoError(t, err)
  761. connection := Connection{
  762. channel: &mockSSHChannel,
  763. netConn: client,
  764. User: user,
  765. fs: fs,
  766. }
  767. cmd := sshCommand{
  768. command: "md5sum",
  769. connection: connection,
  770. args: []string{},
  771. }
  772. err = cmd.handleHashCommands()
  773. assert.Error(t, err, "command must fail for a non local filesystem")
  774. command, err := cmd.getSystemCommand()
  775. assert.NoError(t, err)
  776. err = cmd.executeSystemCommand(command)
  777. assert.Error(t, err, "command must fail for a non local filesystem")
  778. }
  779. func TestSSHCommandQuotaScan(t *testing.T) {
  780. buf := make([]byte, 65535)
  781. stdErrBuf := make([]byte, 65535)
  782. readErr := fmt.Errorf("test read error")
  783. mockSSHChannel := MockChannel{
  784. Buffer: bytes.NewBuffer(buf),
  785. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  786. ReadError: readErr,
  787. }
  788. server, client := net.Pipe()
  789. defer func() {
  790. err := server.Close()
  791. assert.NoError(t, err)
  792. }()
  793. defer func() {
  794. err := client.Close()
  795. assert.NoError(t, err)
  796. }()
  797. permissions := make(map[string][]string)
  798. permissions["/"] = []string{dataprovider.PermAny}
  799. user := dataprovider.User{
  800. Permissions: permissions,
  801. QuotaFiles: 1,
  802. HomeDir: "invalid_path",
  803. }
  804. fs, err := user.GetFilesystem("123")
  805. assert.NoError(t, err)
  806. connection := Connection{
  807. channel: &mockSSHChannel,
  808. netConn: client,
  809. User: user,
  810. fs: fs,
  811. }
  812. cmd := sshCommand{
  813. command: "git-receive-pack",
  814. connection: connection,
  815. args: []string{"/testrepo"},
  816. }
  817. err = cmd.rescanHomeDir()
  818. assert.Error(t, err, "scanning an invalid home dir must fail")
  819. }
  820. func TestGitVirtualFolders(t *testing.T) {
  821. permissions := make(map[string][]string)
  822. permissions["/"] = []string{dataprovider.PermAny}
  823. user := dataprovider.User{
  824. Permissions: permissions,
  825. HomeDir: os.TempDir(),
  826. }
  827. fs, err := user.GetFilesystem("123")
  828. assert.NoError(t, err)
  829. conn := Connection{
  830. User: user,
  831. fs: fs,
  832. }
  833. cmd := sshCommand{
  834. command: "git-receive-pack",
  835. connection: conn,
  836. args: []string{"/vdir"},
  837. }
  838. cmd.connection.User.VirtualFolders = append(cmd.connection.User.VirtualFolders, vfs.VirtualFolder{
  839. BaseVirtualFolder: vfs.BaseVirtualFolder{
  840. MappedPath: os.TempDir(),
  841. },
  842. VirtualPath: "/vdir",
  843. })
  844. _, err = cmd.getSystemCommand()
  845. assert.EqualError(t, err, errUnsupportedConfig.Error())
  846. cmd.connection.User.VirtualFolders = nil
  847. cmd.connection.User.VirtualFolders = append(cmd.connection.User.VirtualFolders, vfs.VirtualFolder{
  848. BaseVirtualFolder: vfs.BaseVirtualFolder{
  849. MappedPath: os.TempDir(),
  850. },
  851. VirtualPath: "/vdir",
  852. })
  853. cmd.args = []string{"/vdir/subdir"}
  854. _, err = cmd.getSystemCommand()
  855. assert.EqualError(t, err, errUnsupportedConfig.Error())
  856. cmd.args = []string{"/adir/subdir"}
  857. _, err = cmd.getSystemCommand()
  858. assert.NoError(t, err)
  859. }
  860. func TestRsyncOptions(t *testing.T) {
  861. permissions := make(map[string][]string)
  862. permissions["/"] = []string{dataprovider.PermAny}
  863. user := dataprovider.User{
  864. Permissions: permissions,
  865. HomeDir: os.TempDir(),
  866. }
  867. fs, err := user.GetFilesystem("123")
  868. assert.NoError(t, err)
  869. conn := Connection{
  870. User: user,
  871. fs: fs,
  872. }
  873. sshCmd := sshCommand{
  874. command: "rsync",
  875. connection: conn,
  876. args: []string{"--server", "-vlogDtprze.iLsfxC", ".", "/"},
  877. }
  878. cmd, err := sshCmd.getSystemCommand()
  879. assert.NoError(t, err)
  880. assert.True(t, utils.IsStringInSlice("--safe-links", cmd.cmd.Args),
  881. "--safe-links must be added if the user has the create symlinks permission")
  882. permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermCreateDirs,
  883. dataprovider.PermListItems, dataprovider.PermOverwrite, dataprovider.PermDelete, dataprovider.PermRename}
  884. user.Permissions = permissions
  885. fs, err = user.GetFilesystem("123")
  886. assert.NoError(t, err)
  887. conn = Connection{
  888. User: user,
  889. fs: fs,
  890. }
  891. sshCmd = sshCommand{
  892. command: "rsync",
  893. connection: conn,
  894. args: []string{"--server", "-vlogDtprze.iLsfxC", ".", "/"},
  895. }
  896. cmd, err = sshCmd.getSystemCommand()
  897. assert.NoError(t, err)
  898. assert.True(t, utils.IsStringInSlice("--munge-links", cmd.cmd.Args),
  899. "--munge-links must be added if the user has the create symlinks permission")
  900. sshCmd.connection.User.VirtualFolders = append(sshCmd.connection.User.VirtualFolders, vfs.VirtualFolder{
  901. BaseVirtualFolder: vfs.BaseVirtualFolder{
  902. MappedPath: os.TempDir(),
  903. },
  904. VirtualPath: "/vdir",
  905. })
  906. _, err = sshCmd.getSystemCommand()
  907. assert.EqualError(t, err, errUnsupportedConfig.Error())
  908. }
  909. func TestSystemCommandErrors(t *testing.T) {
  910. buf := make([]byte, 65535)
  911. stdErrBuf := make([]byte, 65535)
  912. readErr := fmt.Errorf("test read error")
  913. writeErr := fmt.Errorf("test write error")
  914. mockSSHChannel := MockChannel{
  915. Buffer: bytes.NewBuffer(buf),
  916. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  917. ReadError: nil,
  918. WriteError: writeErr,
  919. }
  920. server, client := net.Pipe()
  921. defer func() {
  922. err := server.Close()
  923. assert.NoError(t, err)
  924. }()
  925. defer func() {
  926. err := client.Close()
  927. assert.NoError(t, err)
  928. }()
  929. permissions := make(map[string][]string)
  930. permissions["/"] = []string{dataprovider.PermAny}
  931. user := dataprovider.User{
  932. Permissions: permissions,
  933. HomeDir: os.TempDir(),
  934. }
  935. fs, err := user.GetFilesystem("123")
  936. assert.NoError(t, err)
  937. connection := Connection{
  938. channel: &mockSSHChannel,
  939. netConn: client,
  940. User: user,
  941. fs: fs,
  942. }
  943. sshCmd := sshCommand{
  944. command: "ls",
  945. connection: connection,
  946. args: []string{"/"},
  947. }
  948. systemCmd, err := sshCmd.getSystemCommand()
  949. assert.NoError(t, err)
  950. systemCmd.cmd.Dir = os.TempDir()
  951. // FIXME: the command completes but the fake client was unable to read the response
  952. // no error is reported in this case. We can see that the expected code is executed
  953. // reading the test coverage
  954. sshCmd.executeSystemCommand(systemCmd) //nolint:errcheck
  955. mockSSHChannel = MockChannel{
  956. Buffer: bytes.NewBuffer(buf),
  957. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  958. ReadError: readErr,
  959. WriteError: nil,
  960. }
  961. sshCmd.connection.channel = &mockSSHChannel
  962. transfer := Transfer{
  963. transferType: transferDownload,
  964. lock: new(sync.Mutex)}
  965. destBuff := make([]byte, 65535)
  966. dst := bytes.NewBuffer(destBuff)
  967. _, err = transfer.copyFromReaderToWriter(dst, sshCmd.connection.channel, 0)
  968. assert.EqualError(t, err, readErr.Error())
  969. mockSSHChannel = MockChannel{
  970. Buffer: bytes.NewBuffer(buf),
  971. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  972. ReadError: nil,
  973. WriteError: nil,
  974. }
  975. sshCmd.connection.channel = &mockSSHChannel
  976. _, err = transfer.copyFromReaderToWriter(dst, sshCmd.connection.channel, 1)
  977. assert.EqualError(t, err, errQuotaExceeded.Error())
  978. mockSSHChannel = MockChannel{
  979. Buffer: bytes.NewBuffer(buf),
  980. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  981. ReadError: nil,
  982. WriteError: nil,
  983. ShortWriteErr: true,
  984. }
  985. sshCmd.connection.channel = &mockSSHChannel
  986. _, err = transfer.copyFromReaderToWriter(sshCmd.connection.channel, dst, 0)
  987. assert.EqualError(t, err, io.ErrShortWrite.Error())
  988. }
  989. func TestTransferUpdateQuota(t *testing.T) {
  990. transfer := Transfer{
  991. transferType: transferUpload,
  992. bytesReceived: 123,
  993. lock: new(sync.Mutex)}
  994. transfer.TransferError(errors.New("fake error"))
  995. assert.False(t, transfer.updateQuota(1))
  996. }
  997. func TestGetConnectionInfo(t *testing.T) {
  998. c := ConnectionStatus{
  999. Username: "test_user",
  1000. ConnectionID: "123",
  1001. ClientVersion: "client",
  1002. RemoteAddress: "127.0.0.1:1234",
  1003. Protocol: protocolSSH,
  1004. SSHCommand: "sha1sum /test_file.dat",
  1005. }
  1006. info := c.GetConnectionInfo()
  1007. assert.Contains(t, info, "sha1sum /test_file.dat")
  1008. }
  1009. func TestSCPFileMode(t *testing.T) {
  1010. mode := getFileModeAsString(0, true)
  1011. assert.Equal(t, "0755", mode)
  1012. mode = getFileModeAsString(0700, true)
  1013. assert.Equal(t, "0700", mode)
  1014. mode = getFileModeAsString(0750, true)
  1015. assert.Equal(t, "0750", mode)
  1016. mode = getFileModeAsString(0777, true)
  1017. assert.Equal(t, "0777", mode)
  1018. mode = getFileModeAsString(0640, false)
  1019. assert.Equal(t, "0640", mode)
  1020. mode = getFileModeAsString(0600, false)
  1021. assert.Equal(t, "0600", mode)
  1022. mode = getFileModeAsString(0, false)
  1023. assert.Equal(t, "0644", mode)
  1024. fileMode := uint32(0777)
  1025. fileMode = fileMode | uint32(os.ModeSetgid)
  1026. fileMode = fileMode | uint32(os.ModeSetuid)
  1027. fileMode = fileMode | uint32(os.ModeSticky)
  1028. mode = getFileModeAsString(os.FileMode(fileMode), false)
  1029. assert.Equal(t, "7777", mode)
  1030. fileMode = uint32(0644)
  1031. fileMode = fileMode | uint32(os.ModeSetgid)
  1032. mode = getFileModeAsString(os.FileMode(fileMode), false)
  1033. assert.Equal(t, "4644", mode)
  1034. fileMode = uint32(0600)
  1035. fileMode = fileMode | uint32(os.ModeSetuid)
  1036. mode = getFileModeAsString(os.FileMode(fileMode), false)
  1037. assert.Equal(t, "2600", mode)
  1038. fileMode = uint32(0044)
  1039. fileMode = fileMode | uint32(os.ModeSticky)
  1040. mode = getFileModeAsString(os.FileMode(fileMode), false)
  1041. assert.Equal(t, "1044", mode)
  1042. }
  1043. func TestSCPParseUploadMessage(t *testing.T) {
  1044. buf := make([]byte, 65535)
  1045. stdErrBuf := make([]byte, 65535)
  1046. mockSSHChannel := MockChannel{
  1047. Buffer: bytes.NewBuffer(buf),
  1048. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1049. ReadError: nil,
  1050. }
  1051. connection := Connection{
  1052. channel: &mockSSHChannel,
  1053. fs: vfs.NewOsFs("", os.TempDir(), nil),
  1054. }
  1055. scpCommand := scpCommand{
  1056. sshCommand: sshCommand{
  1057. command: "scp",
  1058. connection: connection,
  1059. args: []string{"-t", "/tmp"},
  1060. },
  1061. }
  1062. _, _, err := scpCommand.parseUploadMessage("invalid")
  1063. assert.Error(t, err, "parsing invalid upload message must fail")
  1064. _, _, err = scpCommand.parseUploadMessage("D0755 0")
  1065. assert.Error(t, err, "parsing incomplete upload message must fail")
  1066. _, _, err = scpCommand.parseUploadMessage("D0755 invalidsize testdir")
  1067. assert.Error(t, err, "parsing upload message with invalid size must fail")
  1068. _, _, err = scpCommand.parseUploadMessage("D0755 0 ")
  1069. assert.Error(t, err, "parsing upload message with invalid name must fail")
  1070. }
  1071. func TestSCPProtocolMessages(t *testing.T) {
  1072. buf := make([]byte, 65535)
  1073. stdErrBuf := make([]byte, 65535)
  1074. readErr := fmt.Errorf("test read error")
  1075. writeErr := fmt.Errorf("test write error")
  1076. mockSSHChannel := MockChannel{
  1077. Buffer: bytes.NewBuffer(buf),
  1078. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1079. ReadError: readErr,
  1080. WriteError: writeErr,
  1081. }
  1082. connection := Connection{
  1083. channel: &mockSSHChannel,
  1084. }
  1085. scpCommand := scpCommand{
  1086. sshCommand: sshCommand{
  1087. command: "scp",
  1088. connection: connection,
  1089. args: []string{"-t", "/tmp"},
  1090. },
  1091. }
  1092. _, err := scpCommand.readProtocolMessage()
  1093. assert.EqualError(t, err, readErr.Error())
  1094. err = scpCommand.sendConfirmationMessage()
  1095. assert.EqualError(t, err, writeErr.Error())
  1096. err = scpCommand.sendProtocolMessage("E\n")
  1097. assert.EqualError(t, err, writeErr.Error())
  1098. _, err = scpCommand.getNextUploadProtocolMessage()
  1099. assert.EqualError(t, err, readErr.Error())
  1100. mockSSHChannel = MockChannel{
  1101. Buffer: bytes.NewBuffer([]byte("T1183832947 0 1183833773 0\n")),
  1102. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1103. ReadError: nil,
  1104. WriteError: writeErr,
  1105. }
  1106. scpCommand.connection.channel = &mockSSHChannel
  1107. _, err = scpCommand.getNextUploadProtocolMessage()
  1108. assert.EqualError(t, err, writeErr.Error())
  1109. respBuffer := []byte{0x02}
  1110. protocolErrorMsg := "protocol error msg"
  1111. respBuffer = append(respBuffer, protocolErrorMsg...)
  1112. respBuffer = append(respBuffer, 0x0A)
  1113. mockSSHChannel = MockChannel{
  1114. Buffer: bytes.NewBuffer(respBuffer),
  1115. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1116. ReadError: nil,
  1117. WriteError: nil,
  1118. }
  1119. scpCommand.connection.channel = &mockSSHChannel
  1120. err = scpCommand.readConfirmationMessage()
  1121. if assert.Error(t, err) {
  1122. assert.Equal(t, protocolErrorMsg, err.Error())
  1123. }
  1124. }
  1125. func TestSCPTestDownloadProtocolMessages(t *testing.T) {
  1126. buf := make([]byte, 65535)
  1127. stdErrBuf := make([]byte, 65535)
  1128. readErr := fmt.Errorf("test read error")
  1129. writeErr := fmt.Errorf("test write error")
  1130. mockSSHChannel := MockChannel{
  1131. Buffer: bytes.NewBuffer(buf),
  1132. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1133. ReadError: readErr,
  1134. WriteError: writeErr,
  1135. }
  1136. connection := Connection{
  1137. channel: &mockSSHChannel,
  1138. }
  1139. scpCommand := scpCommand{
  1140. sshCommand: sshCommand{
  1141. command: "scp",
  1142. connection: connection,
  1143. args: []string{"-f", "-p", "/tmp"},
  1144. },
  1145. }
  1146. path := "testDir"
  1147. err := os.Mkdir(path, os.ModePerm)
  1148. assert.NoError(t, err)
  1149. stat, err := os.Stat(path)
  1150. assert.NoError(t, err)
  1151. err = scpCommand.sendDownloadProtocolMessages(path, stat)
  1152. assert.EqualError(t, err, writeErr.Error())
  1153. mockSSHChannel = MockChannel{
  1154. Buffer: bytes.NewBuffer(buf),
  1155. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1156. ReadError: readErr,
  1157. WriteError: nil,
  1158. }
  1159. err = scpCommand.sendDownloadProtocolMessages(path, stat)
  1160. assert.EqualError(t, err, readErr.Error())
  1161. mockSSHChannel = MockChannel{
  1162. Buffer: bytes.NewBuffer(buf),
  1163. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1164. ReadError: readErr,
  1165. WriteError: writeErr,
  1166. }
  1167. scpCommand.args = []string{"-f", "/tmp"}
  1168. scpCommand.connection.channel = &mockSSHChannel
  1169. err = scpCommand.sendDownloadProtocolMessages(path, stat)
  1170. assert.EqualError(t, err, writeErr.Error())
  1171. mockSSHChannel = MockChannel{
  1172. Buffer: bytes.NewBuffer(buf),
  1173. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1174. ReadError: readErr,
  1175. WriteError: nil,
  1176. }
  1177. scpCommand.connection.channel = &mockSSHChannel
  1178. err = scpCommand.sendDownloadProtocolMessages(path, stat)
  1179. assert.EqualError(t, err, readErr.Error())
  1180. err = os.Remove(path)
  1181. assert.NoError(t, err)
  1182. }
  1183. func TestSCPCommandHandleErrors(t *testing.T) {
  1184. buf := make([]byte, 65535)
  1185. stdErrBuf := make([]byte, 65535)
  1186. readErr := fmt.Errorf("test read error")
  1187. writeErr := fmt.Errorf("test write error")
  1188. mockSSHChannel := MockChannel{
  1189. Buffer: bytes.NewBuffer(buf),
  1190. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1191. ReadError: readErr,
  1192. WriteError: writeErr,
  1193. }
  1194. server, client := net.Pipe()
  1195. defer func() {
  1196. err := server.Close()
  1197. assert.NoError(t, err)
  1198. }()
  1199. defer func() {
  1200. err := client.Close()
  1201. assert.NoError(t, err)
  1202. }()
  1203. connection := Connection{
  1204. channel: &mockSSHChannel,
  1205. netConn: client,
  1206. }
  1207. scpCommand := scpCommand{
  1208. sshCommand: sshCommand{
  1209. command: "scp",
  1210. connection: connection,
  1211. args: []string{"-f", "/tmp"},
  1212. },
  1213. }
  1214. err := scpCommand.handle()
  1215. assert.EqualError(t, err, readErr.Error())
  1216. scpCommand.args = []string{"-i", "/tmp"}
  1217. err = scpCommand.handle()
  1218. assert.Error(t, err, "invalid scp command must fail")
  1219. }
  1220. func TestSCPErrorsMockFs(t *testing.T) {
  1221. errFake := errors.New("fake error")
  1222. fs := newMockOsFs(errFake, errFake, false, "1234", os.TempDir())
  1223. u := dataprovider.User{}
  1224. u.Username = "test"
  1225. u.Permissions = make(map[string][]string)
  1226. u.Permissions["/"] = []string{dataprovider.PermAny}
  1227. u.HomeDir = os.TempDir()
  1228. buf := make([]byte, 65535)
  1229. stdErrBuf := make([]byte, 65535)
  1230. mockSSHChannel := MockChannel{
  1231. Buffer: bytes.NewBuffer(buf),
  1232. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1233. }
  1234. server, client := net.Pipe()
  1235. defer func() {
  1236. err := server.Close()
  1237. assert.NoError(t, err)
  1238. }()
  1239. defer func() {
  1240. err := client.Close()
  1241. assert.NoError(t, err)
  1242. }()
  1243. connection := Connection{
  1244. channel: &mockSSHChannel,
  1245. netConn: client,
  1246. fs: fs,
  1247. User: u,
  1248. }
  1249. scpCommand := scpCommand{
  1250. sshCommand: sshCommand{
  1251. command: "scp",
  1252. connection: connection,
  1253. args: []string{"-r", "-t", "/tmp"},
  1254. },
  1255. }
  1256. err := scpCommand.handleUpload("test", 0)
  1257. assert.EqualError(t, err, errFake.Error())
  1258. testfile := filepath.Join(u.HomeDir, "testfile")
  1259. err = ioutil.WriteFile(testfile, []byte("test"), 0666)
  1260. assert.NoError(t, err)
  1261. stat, err := os.Stat(u.HomeDir)
  1262. assert.NoError(t, err)
  1263. err = scpCommand.handleRecursiveDownload(u.HomeDir, stat)
  1264. assert.EqualError(t, err, errFake.Error())
  1265. scpCommand.sshCommand.connection.fs = newMockOsFs(errFake, nil, true, "123", os.TempDir())
  1266. err = scpCommand.handleUpload(filepath.Base(testfile), 0)
  1267. assert.EqualError(t, err, errFake.Error())
  1268. err = scpCommand.handleUploadFile(testfile, testfile, 0, false, 4, "/testfile")
  1269. assert.NoError(t, err)
  1270. err = os.Remove(testfile)
  1271. assert.NoError(t, err)
  1272. }
  1273. func TestSCPRecursiveDownloadErrors(t *testing.T) {
  1274. buf := make([]byte, 65535)
  1275. stdErrBuf := make([]byte, 65535)
  1276. readErr := fmt.Errorf("test read error")
  1277. writeErr := fmt.Errorf("test write error")
  1278. mockSSHChannel := MockChannel{
  1279. Buffer: bytes.NewBuffer(buf),
  1280. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1281. ReadError: readErr,
  1282. WriteError: writeErr,
  1283. }
  1284. server, client := net.Pipe()
  1285. defer func() {
  1286. err := server.Close()
  1287. assert.NoError(t, err)
  1288. }()
  1289. defer func() {
  1290. err := client.Close()
  1291. assert.NoError(t, err)
  1292. }()
  1293. connection := Connection{
  1294. channel: &mockSSHChannel,
  1295. netConn: client,
  1296. fs: vfs.NewOsFs("123", os.TempDir(), nil),
  1297. }
  1298. scpCommand := scpCommand{
  1299. sshCommand: sshCommand{
  1300. command: "scp",
  1301. connection: connection,
  1302. args: []string{"-r", "-f", "/tmp"},
  1303. },
  1304. }
  1305. path := "testDir"
  1306. err := os.Mkdir(path, os.ModePerm)
  1307. assert.NoError(t, err)
  1308. stat, err := os.Stat(path)
  1309. assert.NoError(t, err)
  1310. err = scpCommand.handleRecursiveDownload("invalid_dir", stat)
  1311. assert.EqualError(t, err, writeErr.Error())
  1312. mockSSHChannel = MockChannel{
  1313. Buffer: bytes.NewBuffer(buf),
  1314. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1315. ReadError: nil,
  1316. WriteError: nil,
  1317. }
  1318. scpCommand.connection.channel = &mockSSHChannel
  1319. err = scpCommand.handleRecursiveDownload("invalid_dir", stat)
  1320. assert.Error(t, err, "recursive upload download must fail for a non existing dir")
  1321. err = os.Remove(path)
  1322. assert.NoError(t, err)
  1323. }
  1324. func TestSCPRecursiveUploadErrors(t *testing.T) {
  1325. buf := make([]byte, 65535)
  1326. stdErrBuf := make([]byte, 65535)
  1327. readErr := fmt.Errorf("test read error")
  1328. writeErr := fmt.Errorf("test write error")
  1329. mockSSHChannel := MockChannel{
  1330. Buffer: bytes.NewBuffer(buf),
  1331. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1332. ReadError: readErr,
  1333. WriteError: writeErr,
  1334. }
  1335. connection := Connection{
  1336. channel: &mockSSHChannel,
  1337. }
  1338. scpCommand := scpCommand{
  1339. sshCommand: sshCommand{
  1340. command: "scp",
  1341. connection: connection,
  1342. args: []string{"-r", "-t", "/tmp"},
  1343. },
  1344. }
  1345. err := scpCommand.handleRecursiveUpload()
  1346. assert.Error(t, err, "recursive upload must fail, we send a fake error message")
  1347. mockSSHChannel = MockChannel{
  1348. Buffer: bytes.NewBuffer(buf),
  1349. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1350. ReadError: readErr,
  1351. WriteError: nil,
  1352. }
  1353. scpCommand.connection.channel = &mockSSHChannel
  1354. err = scpCommand.handleRecursiveUpload()
  1355. assert.Error(t, err, "recursive upload must fail, we send a fake error message")
  1356. }
  1357. func TestSCPCreateDirs(t *testing.T) {
  1358. buf := make([]byte, 65535)
  1359. stdErrBuf := make([]byte, 65535)
  1360. u := dataprovider.User{}
  1361. u.HomeDir = "home_rel_path"
  1362. u.Username = "test"
  1363. u.Permissions = make(map[string][]string)
  1364. u.Permissions["/"] = []string{dataprovider.PermAny}
  1365. mockSSHChannel := MockChannel{
  1366. Buffer: bytes.NewBuffer(buf),
  1367. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1368. ReadError: nil,
  1369. WriteError: nil,
  1370. }
  1371. fs, err := u.GetFilesystem("123")
  1372. assert.NoError(t, err)
  1373. connection := Connection{
  1374. User: u,
  1375. channel: &mockSSHChannel,
  1376. fs: fs,
  1377. }
  1378. scpCommand := scpCommand{
  1379. sshCommand: sshCommand{
  1380. command: "scp",
  1381. connection: connection,
  1382. args: []string{"-r", "-t", "/tmp"},
  1383. },
  1384. }
  1385. err = scpCommand.handleCreateDir("invalid_dir")
  1386. assert.Error(t, err, "create invalid dir must fail")
  1387. }
  1388. func TestSCPDownloadFileData(t *testing.T) {
  1389. testfile := "testfile"
  1390. buf := make([]byte, 65535)
  1391. readErr := fmt.Errorf("test read error")
  1392. writeErr := fmt.Errorf("test write error")
  1393. stdErrBuf := make([]byte, 65535)
  1394. mockSSHChannelReadErr := MockChannel{
  1395. Buffer: bytes.NewBuffer(buf),
  1396. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1397. ReadError: readErr,
  1398. WriteError: nil,
  1399. }
  1400. mockSSHChannelWriteErr := MockChannel{
  1401. Buffer: bytes.NewBuffer(buf),
  1402. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1403. ReadError: nil,
  1404. WriteError: writeErr,
  1405. }
  1406. connection := Connection{
  1407. channel: &mockSSHChannelReadErr,
  1408. }
  1409. scpCommand := scpCommand{
  1410. sshCommand: sshCommand{
  1411. command: "scp",
  1412. connection: connection,
  1413. args: []string{"-r", "-f", "/tmp"},
  1414. },
  1415. }
  1416. err := ioutil.WriteFile(testfile, []byte("test"), 0666)
  1417. assert.NoError(t, err)
  1418. stat, err := os.Stat(testfile)
  1419. assert.NoError(t, err)
  1420. err = scpCommand.sendDownloadFileData(testfile, stat, nil)
  1421. assert.EqualError(t, err, readErr.Error())
  1422. scpCommand.connection.channel = &mockSSHChannelWriteErr
  1423. err = scpCommand.sendDownloadFileData(testfile, stat, nil)
  1424. assert.EqualError(t, err, writeErr.Error())
  1425. scpCommand.args = []string{"-r", "-p", "-f", "/tmp"}
  1426. err = scpCommand.sendDownloadFileData(testfile, stat, nil)
  1427. assert.EqualError(t, err, writeErr.Error())
  1428. scpCommand.connection.channel = &mockSSHChannelReadErr
  1429. err = scpCommand.sendDownloadFileData(testfile, stat, nil)
  1430. assert.EqualError(t, err, readErr.Error())
  1431. err = os.Remove(testfile)
  1432. assert.NoError(t, err)
  1433. }
  1434. func TestSCPUploadFiledata(t *testing.T) {
  1435. testfile := "testfile"
  1436. buf := make([]byte, 65535)
  1437. stdErrBuf := make([]byte, 65535)
  1438. readErr := fmt.Errorf("test read error")
  1439. writeErr := fmt.Errorf("test write error")
  1440. mockSSHChannel := MockChannel{
  1441. Buffer: bytes.NewBuffer(buf),
  1442. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1443. ReadError: readErr,
  1444. WriteError: writeErr,
  1445. }
  1446. connection := Connection{
  1447. User: dataprovider.User{
  1448. Username: "testuser",
  1449. },
  1450. protocol: protocolSCP,
  1451. channel: &mockSSHChannel,
  1452. fs: vfs.NewOsFs("", os.TempDir(), nil),
  1453. }
  1454. scpCommand := scpCommand{
  1455. sshCommand: sshCommand{
  1456. command: "scp",
  1457. connection: connection,
  1458. args: []string{"-r", "-t", "/tmp"},
  1459. },
  1460. }
  1461. file, err := os.Create(testfile)
  1462. assert.NoError(t, err)
  1463. transfer := Transfer{
  1464. file: file,
  1465. path: file.Name(),
  1466. start: time.Now(),
  1467. bytesSent: 0,
  1468. bytesReceived: 0,
  1469. user: scpCommand.connection.User,
  1470. connectionID: "",
  1471. transferType: transferDownload,
  1472. lastActivity: time.Now(),
  1473. isNewFile: true,
  1474. protocol: connection.protocol,
  1475. transferError: nil,
  1476. isFinished: false,
  1477. minWriteOffset: 0,
  1478. lock: new(sync.Mutex),
  1479. }
  1480. addTransfer(&transfer)
  1481. err = scpCommand.getUploadFileData(2, &transfer)
  1482. assert.Error(t, err, "upload must fail, we send a fake write error message")
  1483. mockSSHChannel = MockChannel{
  1484. Buffer: bytes.NewBuffer(buf),
  1485. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1486. ReadError: readErr,
  1487. WriteError: nil,
  1488. }
  1489. scpCommand.connection.channel = &mockSSHChannel
  1490. file, err = os.Create(testfile)
  1491. assert.NoError(t, err)
  1492. transfer.file = file
  1493. transfer.isFinished = false
  1494. addTransfer(&transfer)
  1495. err = scpCommand.getUploadFileData(2, &transfer)
  1496. assert.Error(t, err, "upload must fail, we send a fake read error message")
  1497. respBuffer := []byte("12")
  1498. respBuffer = append(respBuffer, 0x02)
  1499. mockSSHChannel = MockChannel{
  1500. Buffer: bytes.NewBuffer(respBuffer),
  1501. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1502. ReadError: nil,
  1503. WriteError: nil,
  1504. }
  1505. scpCommand.connection.channel = &mockSSHChannel
  1506. file, err = os.Create(testfile)
  1507. assert.NoError(t, err)
  1508. transfer.file = file
  1509. transfer.isFinished = false
  1510. addTransfer(&transfer)
  1511. err = scpCommand.getUploadFileData(2, &transfer)
  1512. assert.Error(t, err, "upload must fail, we have not enough data to read")
  1513. // the file is already closed so we have an error on trasfer closing
  1514. mockSSHChannel = MockChannel{
  1515. Buffer: bytes.NewBuffer(buf),
  1516. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1517. ReadError: nil,
  1518. WriteError: nil,
  1519. }
  1520. addTransfer(&transfer)
  1521. err = scpCommand.getUploadFileData(0, &transfer)
  1522. assert.EqualError(t, err, errTransferClosed.Error())
  1523. mockSSHChannel = MockChannel{
  1524. Buffer: bytes.NewBuffer(buf),
  1525. StdErrBuffer: bytes.NewBuffer(stdErrBuf),
  1526. ReadError: nil,
  1527. WriteError: nil,
  1528. }
  1529. addTransfer(&transfer)
  1530. err = scpCommand.getUploadFileData(2, &transfer)
  1531. assert.True(t, errors.Is(err, os.ErrClosed))
  1532. err = os.Remove(testfile)
  1533. assert.NoError(t, err)
  1534. }
  1535. func TestUploadError(t *testing.T) {
  1536. oldUploadMode := uploadMode
  1537. uploadMode = uploadModeAtomic
  1538. connection := Connection{
  1539. User: dataprovider.User{
  1540. Username: "testuser",
  1541. },
  1542. protocol: protocolSCP,
  1543. }
  1544. testfile := "testfile"
  1545. fileTempName := "temptestfile"
  1546. file, err := os.Create(fileTempName)
  1547. assert.NoError(t, err)
  1548. transfer := Transfer{
  1549. file: file,
  1550. path: testfile,
  1551. start: time.Now(),
  1552. bytesSent: 0,
  1553. bytesReceived: 100,
  1554. user: connection.User,
  1555. connectionID: "",
  1556. transferType: transferUpload,
  1557. lastActivity: time.Now(),
  1558. isNewFile: true,
  1559. protocol: connection.protocol,
  1560. transferError: nil,
  1561. isFinished: false,
  1562. minWriteOffset: 0,
  1563. lock: new(sync.Mutex),
  1564. }
  1565. addTransfer(&transfer)
  1566. errFake := errors.New("fake error")
  1567. transfer.TransferError(errFake)
  1568. err = transfer.Close()
  1569. assert.EqualError(t, err, errFake.Error())
  1570. assert.Equal(t, int64(0), transfer.bytesReceived)
  1571. assert.NoFileExists(t, testfile)
  1572. assert.NoFileExists(t, fileTempName)
  1573. uploadMode = oldUploadMode
  1574. }
  1575. func TestConnectionStatusStruct(t *testing.T) {
  1576. var transfers []connectionTransfer
  1577. transferUL := connectionTransfer{
  1578. OperationType: operationUpload,
  1579. StartTime: utils.GetTimeAsMsSinceEpoch(time.Now()),
  1580. Size: 123,
  1581. LastActivity: utils.GetTimeAsMsSinceEpoch(time.Now()),
  1582. Path: "/test.upload",
  1583. }
  1584. transferDL := connectionTransfer{
  1585. OperationType: operationDownload,
  1586. StartTime: utils.GetTimeAsMsSinceEpoch(time.Now()),
  1587. Size: 123,
  1588. LastActivity: utils.GetTimeAsMsSinceEpoch(time.Now()),
  1589. Path: "/test.download",
  1590. }
  1591. transfers = append(transfers, transferUL)
  1592. transfers = append(transfers, transferDL)
  1593. c := ConnectionStatus{
  1594. Username: "test",
  1595. ConnectionID: "123",
  1596. ClientVersion: "fakeClient-1.0.0",
  1597. RemoteAddress: "127.0.0.1:1234",
  1598. ConnectionTime: utils.GetTimeAsMsSinceEpoch(time.Now()),
  1599. LastActivity: utils.GetTimeAsMsSinceEpoch(time.Now()),
  1600. Protocol: "SFTP",
  1601. Transfers: transfers,
  1602. }
  1603. durationString := c.GetConnectionDuration()
  1604. assert.NotEqual(t, 0, len(durationString))
  1605. transfersString := c.GetTransfersAsString()
  1606. assert.NotEqual(t, 0, len(transfersString))
  1607. connInfo := c.GetConnectionInfo()
  1608. assert.NotEqual(t, 0, len(connInfo))
  1609. }
  1610. func TestProxyProtocolVersion(t *testing.T) {
  1611. c := Configuration{
  1612. ProxyProtocol: 1,
  1613. }
  1614. proxyListener, err := c.getProxyListener(nil)
  1615. assert.NoError(t, err)
  1616. assert.Nil(t, proxyListener.Policy)
  1617. c.ProxyProtocol = 2
  1618. proxyListener, _ = c.getProxyListener(nil)
  1619. assert.NoError(t, err)
  1620. assert.NotNil(t, proxyListener.Policy)
  1621. c.ProxyProtocol = 1
  1622. c.ProxyAllowed = []string{"invalid"}
  1623. _, err = c.getProxyListener(nil)
  1624. assert.Error(t, err)
  1625. c.ProxyProtocol = 2
  1626. _, err = c.getProxyListener(nil)
  1627. assert.Error(t, err)
  1628. }
  1629. func TestLoadHostKeys(t *testing.T) {
  1630. configDir := ".."
  1631. serverConfig := &ssh.ServerConfig{}
  1632. c := Configuration{}
  1633. c.HostKeys = []string{".", "missing file"}
  1634. err := c.checkAndLoadHostKeys(configDir, serverConfig)
  1635. assert.Error(t, err)
  1636. testfile := filepath.Join(os.TempDir(), "invalidkey")
  1637. err = ioutil.WriteFile(testfile, []byte("some bytes"), 0666)
  1638. assert.NoError(t, err)
  1639. c.HostKeys = []string{testfile}
  1640. err = c.checkAndLoadHostKeys(configDir, serverConfig)
  1641. assert.Error(t, err)
  1642. err = os.Remove(testfile)
  1643. assert.NoError(t, err)
  1644. keysDir := filepath.Join(os.TempDir(), "keys")
  1645. err = os.MkdirAll(keysDir, os.ModePerm)
  1646. assert.NoError(t, err)
  1647. rsaKeyName := filepath.Join(keysDir, defaultPrivateRSAKeyName)
  1648. ecdsaKeyName := filepath.Join(keysDir, defaultPrivateECDSAKeyName)
  1649. nonDefaultKeyName := filepath.Join(keysDir, "akey")
  1650. c.HostKeys = []string{nonDefaultKeyName, rsaKeyName, ecdsaKeyName}
  1651. err = c.checkAndLoadHostKeys(configDir, serverConfig)
  1652. assert.Error(t, err)
  1653. assert.FileExists(t, rsaKeyName)
  1654. assert.FileExists(t, ecdsaKeyName)
  1655. assert.NoFileExists(t, nonDefaultKeyName)
  1656. err = os.Remove(rsaKeyName)
  1657. assert.NoError(t, err)
  1658. err = os.Remove(ecdsaKeyName)
  1659. assert.NoError(t, err)
  1660. if runtime.GOOS != osWindows {
  1661. err = os.Chmod(keysDir, 0551)
  1662. assert.NoError(t, err)
  1663. c.HostKeys = nil
  1664. err = c.checkAndLoadHostKeys(keysDir, serverConfig)
  1665. assert.Error(t, err)
  1666. c.HostKeys = []string{rsaKeyName, ecdsaKeyName}
  1667. err = c.checkAndLoadHostKeys(configDir, serverConfig)
  1668. assert.Error(t, err)
  1669. c.HostKeys = []string{ecdsaKeyName, rsaKeyName}
  1670. err = c.checkAndLoadHostKeys(configDir, serverConfig)
  1671. assert.Error(t, err)
  1672. err = os.Chmod(keysDir, 0755)
  1673. assert.NoError(t, err)
  1674. }
  1675. err = os.RemoveAll(keysDir)
  1676. assert.NoError(t, err)
  1677. }
  1678. func TestCertCheckerInitErrors(t *testing.T) {
  1679. c := Configuration{}
  1680. c.TrustedUserCAKeys = []string{".", "missing file"}
  1681. err := c.initializeCertChecker("")
  1682. assert.Error(t, err)
  1683. testfile := filepath.Join(os.TempDir(), "invalidkey")
  1684. err = ioutil.WriteFile(testfile, []byte("some bytes"), 0666)
  1685. assert.NoError(t, err)
  1686. c.TrustedUserCAKeys = []string{testfile}
  1687. err = c.initializeCertChecker("")
  1688. assert.Error(t, err)
  1689. err = os.Remove(testfile)
  1690. assert.NoError(t, err)
  1691. }
  1692. func TestUpdateQuotaAfterRenameMissingFile(t *testing.T) {
  1693. user := dataprovider.User{
  1694. Username: "username",
  1695. HomeDir: filepath.Join(os.TempDir(), "home"),
  1696. }
  1697. mappedPath := filepath.Join(os.TempDir(), "vdir")
  1698. user.Permissions = make(map[string][]string)
  1699. user.Permissions["/"] = []string{dataprovider.PermAny}
  1700. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  1701. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1702. MappedPath: mappedPath,
  1703. },
  1704. VirtualPath: "/vdir",
  1705. })
  1706. c := Connection{
  1707. fs: vfs.NewOsFs("id", os.TempDir(), nil),
  1708. User: user,
  1709. }
  1710. request := sftp.NewRequest("Rename", "/testfile")
  1711. request.Filepath = "/dir"
  1712. request.Target = path.Join("vdir", "dir")
  1713. if runtime.GOOS != osWindows {
  1714. testDirPath := filepath.Join(mappedPath, "dir")
  1715. err := os.MkdirAll(testDirPath, os.ModePerm)
  1716. assert.NoError(t, err)
  1717. err = os.Chmod(testDirPath, 0001)
  1718. assert.NoError(t, err)
  1719. err = c.updateQuotaAfterRename(request, testDirPath, 0)
  1720. assert.Error(t, err)
  1721. err = os.Chmod(testDirPath, os.ModePerm)
  1722. assert.NoError(t, err)
  1723. err = os.RemoveAll(testDirPath)
  1724. assert.NoError(t, err)
  1725. }
  1726. request.Target = "/testfile1"
  1727. request.Filepath = path.Join("vdir", "file")
  1728. err := c.updateQuotaAfterRename(request, filepath.Join(os.TempDir(), "vdir", "file"), 0)
  1729. assert.Error(t, err)
  1730. }