contrib/hg-ssh
author Augie Fackler <augie@google.com>
Fri, 13 Apr 2018 23:11:46 -0400
changeset 37747 2d5b5bcc3b9f
parent 33891 42bc7f39376b
child 37944 dc1ed7fe33e4
permissions -rwxr-xr-x
wsgicgi: un-do some prior porting work that is now wrong The Python 3 WSGI behavior is that the environ dict should be full of unicodes. We previously tried Too Hard here, so we unwind that bit of porting. Also add some bytesurl() encodes on status and headers. test-clone-cgi.t now passes. Differential Revision: https://phab.mercurial-scm.org/D3356
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
     1
#!/usr/bin/env python
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
     2
#
5191
831ebc408ffb Adjust contrib/hg-ssh for moved dispatch() function.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1640
diff changeset
     3
# Copyright 2005-2007 by Intevation GmbH <intevation@intevation.de>
8228
eee2319c5895 add blank line after copyright notices and after header
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     4
#
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
     5
# Author(s):
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
     6
# Thomas Arendsen Hein <thomas@intevation.de>
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
     7
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 5197
diff changeset
     8
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 8228
diff changeset
     9
# GNU General Public License version 2 or any later version.
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    10
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    11
"""
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    12
hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    13
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    14
To be used in ~/.ssh/authorized_keys with the "command" option, see sshd(8):
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    15
command="hg-ssh path/to/repo1 /path/to/repo2 ~/repo3 ~user/repo4" ssh-dss ...
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    16
(probably together with these other useful options:
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    17
 no-port-forwarding,no-X11-forwarding,no-agent-forwarding)
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    18
13996
1cafa0426a1a hg-ssh: fix duplicate word in docstring
Andreas Freimuth <andreas.freimuth@united-bits.de>
parents: 10263
diff changeset
    19
This allows pull/push over ssh from/to the repositories given as arguments.
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    20
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    21
If all your repositories are subdirectories of a common directory, you can
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    22
allow shorter paths with:
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    23
command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2"
1640
9a5b778f7e2d Added hint to hg-ssh that you can use shell pattern matching.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1537
diff changeset
    24
9a5b778f7e2d Added hint to hg-ssh that you can use shell pattern matching.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1537
diff changeset
    25
You can use pattern matching of your normal shell, e.g.:
9a5b778f7e2d Added hint to hg-ssh that you can use shell pattern matching.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1537
diff changeset
    26
command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}"
16836
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    27
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    28
You can also add a --read-only flag to allow read-only access to a key, e.g.:
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    29
command="hg-ssh --read-only repos/*"
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    30
"""
33891
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    31
from __future__ import absolute_import
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    32
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    33
import os
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    34
import shlex
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    35
import sys
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    36
5197
55860a45bbf2 Enable demandimport only in scripts, not in importable modules (issue605)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5191
diff changeset
    37
# enable importing on demand to reduce startup time
33891
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    38
import hgdemandimport ; hgdemandimport.enable()
5197
55860a45bbf2 Enable demandimport only in scripts, not in importable modules (issue605)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5191
diff changeset
    39
33891
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    40
from mercurial import (
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    41
    dispatch,
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    42
    ui as uimod,
42bc7f39376b contrib: update hg-ssh to conform with import style checks
Augie Fackler <raf@durin42.com>
parents: 32050
diff changeset
    43
)
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    44
16779
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    45
def main():
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    46
    cwd = os.getcwd()
16836
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    47
    readonly = False
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    48
    args = sys.argv[1:]
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    49
    while len(args):
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    50
        if args[0] == '--read-only':
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    51
            readonly = True
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    52
            args.pop(0)
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    53
        else:
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    54
            break
16779
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    55
    allowed_paths = [os.path.normpath(os.path.join(cwd,
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    56
                                                   os.path.expanduser(path)))
16836
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    57
                     for path in args]
16779
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    58
    orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?')
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    59
    try:
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    60
        cmdargv = shlex.split(orig_cmd)
28047
863075fd4cd0 misc: use modern exception syntax
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28045
diff changeset
    61
    except ValueError as e:
16779
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    62
        sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e))
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    63
        sys.exit(255)
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    64
16779
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    65
    if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']:
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    66
        path = cmdargv[2]
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    67
        repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path)))
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    68
        if repo in allowed_paths:
16836
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    69
            cmd = ['-R', repo, 'serve', '--stdio']
32050
77eaf9539499 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Augie Fackler <augie@google.com>
parents: 28047
diff changeset
    70
            req = dispatch.request(cmd)
16836
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    71
            if readonly:
32050
77eaf9539499 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Augie Fackler <augie@google.com>
parents: 28047
diff changeset
    72
                if not req.ui:
77eaf9539499 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Augie Fackler <augie@google.com>
parents: 28047
diff changeset
    73
                    req.ui = uimod.ui.load()
77eaf9539499 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Augie Fackler <augie@google.com>
parents: 28047
diff changeset
    74
                req.ui.setconfig('hooks', 'pretxnopen.hg-ssh',
77eaf9539499 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Augie Fackler <augie@google.com>
parents: 28047
diff changeset
    75
                                 'python:__main__.rejectpush', 'hg-ssh')
77eaf9539499 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Augie Fackler <augie@google.com>
parents: 28047
diff changeset
    76
                req.ui.setconfig('hooks', 'prepushkey.hg-ssh',
77eaf9539499 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Augie Fackler <augie@google.com>
parents: 28047
diff changeset
    77
                                 'python:__main__.rejectpush', 'hg-ssh')
77eaf9539499 dispatch: protect against malicious 'hg serve --stdio' invocations (sec)
Augie Fackler <augie@google.com>
parents: 28047
diff changeset
    78
            dispatch.dispatch(req)
16779
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    79
        else:
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    80
            sys.stderr.write('Illegal repository "%s"\n' % repo)
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    81
            sys.exit(255)
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    82
    else:
16779
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    83
        sys.stderr.write('Illegal command "%s"\n' % orig_cmd)
16607
feb1fd2d13a9 hg-ssh: exit with 255 instead of -1 on error
Mads Kiilerich <mads@kiilerich.com>
parents: 16606
diff changeset
    84
        sys.exit(255)
1537
583b3696d24d Added hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
Thomas Arendsen Hein <thomas@intevation.de>
parents:
diff changeset
    85
16836
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    86
def rejectpush(ui, **kwargs):
28045
f68ded00cae5 hg-ssh: parenthesize non-translated message
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25127
diff changeset
    87
    ui.warn(("Permission denied\n"))
16836
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    88
    # mercurial hooks use unix process conventions for hook return values
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    89
    # so a truthy return means failure
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    90
    return True
1ba3e17186c8 hg-ssh: read-only flag
David Schleimer <dschleimer@fb.com>
parents: 16779
diff changeset
    91
16779
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    92
if __name__ == '__main__':
67bfe7f64e57 hg-ssh: refactor to have main() method
David Schleimer <dschleimer@fb.com>
parents: 16607
diff changeset
    93
    main()