def serve(cname, enable_repo_config=False, enable_repo_group=False, enable_user_repos=False, enable_mozreview_ldap_associate=False): ssh_command = os.getenv('SSH_ORIGINAL_COMMAND') if not ssh_command: sys.stderr.write(SUCCESSFUL_AUTH % os.environ['USER']) sys.stderr.write(NO_SSH_COMMAND) sys.exit(1) elif ssh_command.startswith('hg'): repo_expr = re.compile('(.*)\s+-R\s+([^\s]+\s+)(.*)') if repo_expr.search(ssh_command): [(hg_path, repo_path, hg_command)] = repo_expr.findall(ssh_command) if hg_command == 'serve --stdio' and check_repo_name(repo_path): hg_arg_string = HG + ' -R ' + DOC_ROOT + '/' + repo_path + hg_command hg_args = hg_arg_string.split() os.execv(HG, hg_args) else: sys.stderr.write("Thank you dchen! but.. I don't think so!\n") sys.exit(1) elif ssh_command.startswith('clone '): if not enable_user_repos: print('user repository management is not enabled') sys.exit(1) args = ssh_command.replace('clone', '').split() if check_repo_name(args[0]): if len(args) == 1: make_repo_clone(cname, args[0], None) elif len(args) == 2: make_repo_clone(cname, args[0], args[1]) sys.exit(0) sys.stderr.write('clone usage: ssh hg.mozilla.org clone newrepo ' '[srcrepo]\n') sys.exit(1) elif ssh_command.startswith('edit '): if not enable_user_repos: print('user repository management is not enabled') sys.exit(1) args = ssh_command.replace('edit', '', 1).split() if check_repo_name(args[0]): if len(args) == 1: edit_repo(cname, args[0], False) elif len(args) == 3 and args[1] == 'delete' and args[2] == 'YES': edit_repo(cname, args[0], True) else: sys.stderr.write('edit usage: ssh hg.mozilla.org edit ' '[userrepo delete] - WARNING: will not ' 'prompt!\n') sys.exit(1) elif ssh_command.startswith('repo-group'): if not enable_repo_group: print('repo-group command not available') sys.exit(1) args = ssh_command.replace('repo-group', '').split() if check_repo_name(args[0]): print(repo_group.repo_owner(args[0])) elif ssh_command.startswith('repo-config '): if not enable_repo_config: print('repo-config command not available') sys.exit(1) args = ssh_command.split()[1:] repo = args[0] if check_repo_name(repo): hgrc = '/repo/hg/mozilla/%s/.hg/hgrc' % repo if os.path.exists(hgrc): with open(hgrc, 'rb') as fh: sys.stdout.write(fh.read()) elif ssh_command.startswith('mozreview-ldap-associate'): if not enable_mozreview_ldap_associate: print('mozreview-ldap-associate command not available') sys.exit(1) args = ssh_command.split()[1:] sys.exit(mozreview_ldap_associate(args)) else: sys.stderr.write(SUCCESSFUL_AUTH % os.environ['USER']) sys.stderr.write(INVALID_SSH_COMMAND) sys.exit(1)
def serve(cname, enable_repo_config=False, enable_repo_group=False, enable_user_repos=False, enable_mozreview_ldap_associate=False): ssh_command = os.getenv('SSH_ORIGINAL_COMMAND') if not ssh_command: sys.stderr.write(SUCCESSFUL_AUTH % os.environ['USER']) sys.stderr.write(group_membership_message(os.environ['USER'])) sys.stderr.write('\n') sys.stderr.write(NO_SSH_COMMAND) sys.exit(1) args = shlex.split(ssh_command) if args[0] == 'hg': # SECURITY it is critical that invoked commands be limited to # `hg -R <path> serve --stdio`. If a user manages to pass arguments # to coerce Mercurial into say opening a debugger, that is effectively # giving them a remote shell. We require that command arguments match # an exact pattern and that the repo name is sanitized. if args[1] != '-R' or args[3:] != ['serve', '--stdio']: sys.stderr.write('invalid `hg` command executed; can only run ' 'serve --stdio\n') sys.exit(1) # At this point, the only argument not validated to match exact bytes # is the value for -R. We sanitize that through our repo name validator # *and* verify it exists on disk. repo_path = args[2] # This will ensure the repo path is essentially alphanumeric. So we # don't have to worry about ``..``, Unicode, spaces, etc. assert_valid_repo_name(repo_path) full_repo_path = '%s/%s' % (DOC_ROOT, repo_path) if not os.path.isdir('%s/.hg' % full_repo_path): sys.stderr.write('requested repo %s does not exist\n' % repo_path) sys.exit(1) os.execv(HG, [HG, '-R', full_repo_path, 'serve', '--stdio']) elif args[0] == 'clone': if not enable_user_repos: print('user repository management is not enabled') sys.exit(1) if len(args) == 1: sys.stderr.write('clone usage: ssh hg.mozilla.org clone newrepo ' '[srcrepo]\n') sys.exit(1) assert_valid_repo_name(args[1]) if len(args) == 2: make_repo_clone(cname, args[1], None) elif len(args) == 3: make_repo_clone(cname, args[1], args[2]) sys.exit(0) elif args[0] == 'edit': if not enable_user_repos: print('user repository management is not enabled') sys.exit(1) if len(args) == 2: assert_valid_repo_name(args[1]) edit_repo(cname, args[1], False) elif len(args) == 4 and args[2] == 'delete' and args[3] == 'YES': assert_valid_repo_name(args[1]) edit_repo(cname, args[1], True) else: sys.stderr.write('edit usage: ssh hg.mozilla.org edit ' '[userrepo delete] - WARNING: will not ' 'prompt!\n') sys.exit(1) elif args[0] == 'repo-group': if not enable_repo_group: print('repo-group command not available') sys.exit(1) assert_valid_repo_name(args[1]) print(repo_group.repo_owner(args[1])) elif args[0] == 'repo-config': if not enable_repo_config: print('repo-config command not available') sys.exit(1) repo = args[1] assert_valid_repo_name(repo) hgrc = '/repo/hg/mozilla/%s/.hg/hgrc' % repo if os.path.exists(hgrc): with open(hgrc, 'rb') as fh: sys.stdout.write(fh.read()) else: sys.stderr.write(SUCCESSFUL_AUTH % os.environ['USER']) sys.stderr.write(INVALID_SSH_COMMAND) sys.exit(1)