StaticServerForbidSymlinks.coffee 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. Path = require("path")
  2. fs = require("fs")
  3. Settings = require("settings-sharelatex")
  4. logger = require("logger-sharelatex")
  5. url = require "url"
  6. module.exports = ForbidSymlinks = (staticFn, root, options) ->
  7. expressStatic = staticFn root, options
  8. basePath = Path.resolve(root)
  9. return (req, res, next) ->
  10. path = url.parse(req.url)?.pathname
  11. # check that the path is of the form /project_id_or_name/path/to/file.log
  12. if result = path.match(/^\/?([a-zA-Z0-9_-]+)\/(.*)/)
  13. project_id = result[1]
  14. file = result[2]
  15. else
  16. logger.warn path: path, "unrecognized file request"
  17. return res.sendStatus(404)
  18. # check that the file does not use a relative path
  19. for dir in file.split('/')
  20. if dir == '..'
  21. logger.warn path: path, "attempt to use a relative path"
  22. return res.sendStatus(404)
  23. # check that the requested path is normalized
  24. requestedFsPath = "#{basePath}/#{project_id}/#{file}"
  25. if requestedFsPath != Path.normalize(requestedFsPath)
  26. logger.error path: requestedFsPath, "requestedFsPath is not normalized"
  27. return res.sendStatus(404)
  28. # check that the requested path is not a symlink
  29. fs.realpath requestedFsPath, (err, realFsPath)->
  30. if err?
  31. if err.code == 'ENOENT'
  32. return res.sendStatus(404)
  33. else
  34. logger.error err:err, requestedFsPath:requestedFsPath, realFsPath:realFsPath, path: req.params[0], project_id: req.params.project_id, "error checking file access"
  35. return res.sendStatus(500)
  36. else if requestedFsPath != realFsPath
  37. logger.warn requestedFsPath:requestedFsPath, realFsPath:realFsPath, path: req.params[0], project_id: req.params.project_id, "trying to access a different file (symlink), aborting"
  38. return res.sendStatus(404)
  39. else
  40. expressStatic(req, res, next)