mirror of https://git.sr.ht/~sircmpwn/git.sr.ht
Implement authorized keys command
This commit is contained in:
parent
cb938b7fca
commit
0decd5a1db
|
@ -13,3 +13,4 @@ pip-selfcheck.json
|
|||
.sass-cache/
|
||||
overrides/
|
||||
.pgp
|
||||
build
|
||||
|
|
1
Makefile
1
Makefile
|
@ -1,2 +1,3 @@
|
|||
SRHT_PATH?=/usr/lib/python3.6/site-packages/srht
|
||||
MODULE=gitsrht/
|
||||
include ${SRHT_PATH}/Makefile
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
#!/usr/bin/env python3
|
||||
# AuthorizedKeysCommand=/usr/bin/git-srht-keys "%u" "%h" "%k"
|
||||
# AuthorizedKeysUser=root
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from pwd import getpwnam
|
||||
from grp import getgrnam
|
||||
from srht.config import cfg, cfgi, load_config
|
||||
load_config("git")
|
||||
|
||||
_log = None
|
||||
try:
|
||||
_log = open("/var/log/git-srht-keys", "a")
|
||||
except:
|
||||
pass
|
||||
|
||||
def log(s, *args):
|
||||
if isinstance(s, str):
|
||||
s = s.format(*args)
|
||||
else:
|
||||
s = str(s)
|
||||
s = "{} {}".format(datetime.now().isoformat(), s)
|
||||
if _log:
|
||||
_log.write(s + "\n")
|
||||
else:
|
||||
sys.stderr.write(s + "\n")
|
||||
|
||||
def auth_keys_error():
|
||||
log("This command should be run by sshd's AuthorizedKeysCommand")
|
||||
log('AuthorizedKeysCommand={} "%u" "%h" "%k"\nAuthorizedKeysUser=root',
|
||||
os.path.abspath(sys.argv[0]))
|
||||
sys.exit(1)
|
||||
|
||||
def drop_root():
|
||||
if os.getuid() != git_uid or os.getgid() != git_gid:
|
||||
log("setuid to {}", git_user)
|
||||
os.setgid(git_gid)
|
||||
os.setuid(git_uid)
|
||||
|
||||
git_user = cfg("git.sr.ht", "git-user").split(':')
|
||||
git_uid, git_gid = getpwnam(git_user[0]).pw_uid, getgrnam(git_user[-1]).gr_gid
|
||||
repos = cfg("cgit", "repos")
|
||||
|
||||
def auth_keys():
|
||||
if len(sys.argv) != 5:
|
||||
auth_keys_error()
|
||||
|
||||
user = sys.argv[2]
|
||||
uid = getpwnam(user).pw_uid
|
||||
homedir = sys.argv[3]
|
||||
b64key = sys.argv[4]
|
||||
authorized_keys_file = "{}/.ssh/authorized_keys".format(homedir)
|
||||
|
||||
log("user={} home={} b64key={}", user, homedir, b64key)
|
||||
|
||||
if user != git_user[0]:
|
||||
log("Falling back to existing authorized keys file")
|
||||
if not os.path.exists(authorized_keys_file):
|
||||
sys.exit(0)
|
||||
with open(authorized_keys_file, "r") as f:
|
||||
authorized_keys = f.read()
|
||||
print(authorized_keys)
|
||||
sys.exit(0)
|
||||
|
||||
drop_root()
|
||||
|
||||
from srht.database import DbSession
|
||||
db = DbSession(cfg("sr.ht", "connection-string"))
|
||||
from gitsrht.types import User
|
||||
db.init()
|
||||
|
||||
r = requests.get("{}/api/ssh-key/{}".format(
|
||||
cfg("network", "meta"), b64key))
|
||||
if r.status_code != 200:
|
||||
log("meta.sr.ht returned 404 for this key")
|
||||
sys.exit(0)
|
||||
j = r.json()
|
||||
username = j["user"]["username"]
|
||||
u = User.query.filter(User.username == username).first()
|
||||
if not u:
|
||||
log("Unknown user {}", username)
|
||||
log("Authorized user for login")
|
||||
keys = "command=\"{} shell '{}' '{}'\",".format(sys.argv[0], u.id, b64key) + \
|
||||
"no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty " + \
|
||||
"ssh-rsa {} {}".format(b64key, username)
|
||||
print(keys)
|
||||
log(keys)
|
||||
sys.exit(0)
|
||||
|
||||
def shell():
|
||||
log("Starting up git.sr.ht shell")
|
||||
drop_root()
|
||||
|
||||
_cmd = os.environ.get("SSH_ORIGINAL_COMMAND")
|
||||
if not _cmd:
|
||||
_cmd = ""
|
||||
if len(sys.argv) < 3:
|
||||
log("Error: expected 2 arguments from SSH")
|
||||
user_id = sys.argv[2]
|
||||
ssh_key = sys.argv[3]
|
||||
|
||||
from srht.database import DbSession
|
||||
db = DbSession(cfg("sr.ht", "connection-string"))
|
||||
from gitsrht.types import User
|
||||
db.init()
|
||||
|
||||
user = User.query.filter(User.id == user_id).first()
|
||||
if not user:
|
||||
log("Unknown user ID {}", user_id)
|
||||
log("User: {}", user.username)
|
||||
|
||||
log("Executing {}", _cmd)
|
||||
cmd = shlex.split(_cmd)
|
||||
valid_commands = ["git-receive-pack", "git-upload-pack", "git-upload-archive"]
|
||||
if len(cmd) < 1 or not cmd[0] in valid_commands:
|
||||
log("Not permitting unacceptable command")
|
||||
print("Hi {}! You've successfully authenticated, ".format(user.username) +
|
||||
"but I do not provide an interactive shell. Bye!")
|
||||
sys.exit(128)
|
||||
os.chdir(repos)
|
||||
os.execv("/usr/bin/git-shell", ["/usr/bin/git-shell", "-c", _cmd])
|
||||
|
||||
with _log or sys.stdout:
|
||||
if len(sys.argv) < 2:
|
||||
auth_keys_error()
|
||||
if sys.argv[1] == "auth":
|
||||
auth_keys()
|
||||
if sys.argv[1] == "shell":
|
||||
shell()
|
|
@ -37,7 +37,10 @@ def user_index(username):
|
|||
if search:
|
||||
repos = repos.filter(Repository.name.ilike("%" + search + "%"))
|
||||
repos = repos.order_by(Repository.updated.desc())
|
||||
total_repos = repos.count()
|
||||
total_pages = repos.count() // 5 + 1
|
||||
if total_repos % 5 == 0:
|
||||
total_pages -= 1
|
||||
if page:
|
||||
try:
|
||||
page = int(page) - 1
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
from distutils.core import setup
|
||||
import subprocess
|
||||
import glob
|
||||
|
||||
subprocess.call(["make"])
|
||||
|
||||
setup(
|
||||
name = 'gitsrht',
|
||||
packages = [
|
||||
'gitsrht',
|
||||
'gitsrht.types',
|
||||
'gitsrht.blueprints',
|
||||
],
|
||||
version = subprocess.run(['git', 'describe', '--tags'],
|
||||
stdout=subprocess.PIPE).stdout.decode().strip(),
|
||||
description = 'git.sr.ht website',
|
||||
author = 'Drew DeVault',
|
||||
author_email = 'sir@cmpwn.com',
|
||||
url = 'https://git.sr.ht/~sircmpwn/git.sr.ht',
|
||||
requires = ['srht'],
|
||||
license = 'GPL-2.0',
|
||||
package_data={
|
||||
'gitsrht': [
|
||||
'templates/*.html',
|
||||
'static/*',
|
||||
]
|
||||
},
|
||||
scripts = ['git-srht-keys']
|
||||
)
|
Loading…
Reference in New Issue