aclchecker.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. (c) 2014-2018 - Copyright Red Hat Inc
  5. Authors:
  6. Patrick Uiterwijk <puiterwijk@redhat.com>
  7. """
  8. from __future__ import unicode_literals, print_function, absolute_import
  9. import subprocess
  10. import sys
  11. import os
  12. import requests
  13. if "SSH_ORIGINAL_COMMAND" not in os.environ:
  14. print("Welcome %s. This server does not offer shell access." % sys.argv[1])
  15. sys.exit(0)
  16. # Since this is run by sshd, we don't have a way to set environment
  17. # variables ahead of time
  18. if "PAGURE_CONFIG" not in os.environ and os.path.exists(
  19. "/etc/pagure/pagure.cfg"
  20. ):
  21. os.environ["PAGURE_CONFIG"] = "/etc/pagure/pagure.cfg"
  22. # Here starts the code
  23. from pagure.config import config as pagure_config
  24. # Get the arguments
  25. if len(sys.argv) != 2:
  26. print("Invalid call, too few arguments", file=sys.stderr)
  27. sys.exit(1)
  28. remoteuser = sys.argv[1]
  29. args = os.environ["SSH_ORIGINAL_COMMAND"].split(" ")
  30. # Expects: <git-(receive|upload)-pack> <repopath>
  31. if len(args) != 2:
  32. print("Invalid call, too few inner arguments", file=sys.stderr)
  33. sys.exit(1)
  34. cmd = args[0]
  35. gitdir = args[1]
  36. if cmd not in ("git-receive-pack", "git-upload-pack"):
  37. print("Invalid call, invalid operation", file=sys.stderr)
  38. sys.exit(1)
  39. # Normalization of the gitdir
  40. # Git will encode the file path argument within single quotes
  41. if gitdir[0] != "'" or gitdir[-1] != "'":
  42. print("Invalid call: invalid path", file=sys.stderr)
  43. sys.exit(1)
  44. gitdir = gitdir[1:-1]
  45. # With the "ssh://hostname/repo.git", SSH sends "/repo.git"
  46. if gitdir[0] == "/":
  47. gitdir = gitdir[1:]
  48. # Always add .git for good measure
  49. if not gitdir.endswith(".git"):
  50. gitdir = gitdir + ".git"
  51. pagure_url = pagure_config["APP_URL"].rstrip("/")
  52. url = "%s/pv/ssh/checkaccess/" % pagure_url
  53. data = {"gitdir": gitdir, "username": remoteuser}
  54. headers = {}
  55. if pagure_config.get("SSH_ADMIN_TOKEN"):
  56. headers["Authorization"] = "token %s" % pagure_config["SSH_ADMIN_TOKEN"]
  57. resp = requests.post(url, data=data, headers=headers)
  58. if not resp.status_code == 200:
  59. print(
  60. "Error during lookup request: status: %s" % resp.status_code,
  61. file=sys.stderr,
  62. )
  63. sys.exit(1)
  64. result = resp.json()
  65. if not result["access"]:
  66. # The user does not have access to this repo, or project does
  67. # not exist. Whatever it is, no access.
  68. print("No such repository", file=sys.stderr)
  69. sys.exit(1)
  70. # Now go run the configured command
  71. # We verified that cmd is either "git-receive-pack" or "git-send-pack"
  72. # and "path" is a path that points to a valid Pagure repository.
  73. runner, env = pagure_config["SSH_COMMAND"]
  74. result.update({"username": remoteuser, "cmd": cmd})
  75. for key in result:
  76. if result[key] is None:
  77. result[key] = ""
  78. runargs = [arg % result for arg in runner]
  79. if env:
  80. for key in env:
  81. os.environ[key] = env[key] % result
  82. os.execvp(runargs[0], runargs)