hgext/factotum.py
author Steven Stallion <sstallion@gmail.com>
Sun, 08 Apr 2012 12:43:41 -0700
changeset 16383 f5dd179bfa4a
child 16463 cef755f86d5c
permissions -rw-r--r--
plan9: initial support for plan 9 from bell labs This patch contains support for Plan 9 from Bell Labs. A README is provided in contrib/plan9 which describes the port in greater detail. A new extension is also provided named factotum which permits the factotum(4) authentication agent to provide credentials for HTTP repositories. This extension is also applicable to other POSIX platforms which make use of Plan 9 from User Space (aka plan9ports).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16383
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     1
# factotum.py - Plan 9 factotum integration for Mercurial
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     2
#
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     3
# Copyright (C) 2012 Steven Stallion <sstallion@gmail.com>
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     4
#
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     5
# This program is free software; you can redistribute it and/or modify it
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     6
# under the terms of the GNU General Public License as published by the
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     7
# Free Software Foundation; either version 2 of the License, or (at your
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     8
# option) any later version.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
     9
#
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    10
# This program is distributed in the hope that it will be useful, but
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    11
# WITHOUT ANY WARRANTY; without even the implied warranty of
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    13
# Public License for more details.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    14
#
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    15
# You should have received a copy of the GNU General Public License along
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    16
# with this program; if not, write to the Free Software Foundation, Inc.,
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    17
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    18
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    19
'''http authentication with factotum
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    20
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    21
This extension allows the factotum facility on Plan 9 from Bell Labs platforms
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    22
to provide authentication information for HTTP access. Configuration entries
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    23
specified in the auth section as well as authentication information provided
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    24
in the repository URL are fully supported. If no prefix is specified, a value
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    25
of ``*`` will be assumed.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    26
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    27
By default, keys are specified as::
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    28
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    29
  proto=pass service=hg prefix=<prefix> user=<username> !password=<password>
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    30
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    31
If the factotum extension is unable to read the required key, one will be
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    32
requested interactively.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    33
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    34
A configuration section is available to customize runtime behavior. By
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    35
default, these entries are::
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    36
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    37
  [factotum]
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    38
  mount = /mnt/factotum
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    39
  path = /bin/auth/factotum
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    40
  service = hg
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    41
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    42
The mount entry defines the mount point for the factotum file service. The
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    43
path entry defines the full path to the factotum binary. Lastly, the service
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    44
entry controls the service name used when reading keys.
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    45
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    46
'''
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    47
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    48
from mercurial.i18n import _
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    49
from mercurial.url import passwordmgr
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    50
from mercurial import httpconnection, urllib2, util
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    51
import os
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    52
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    53
ERRMAX = 128
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    54
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    55
def auth_getkey(self, params):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    56
    if not self.ui.interactive():
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    57
        raise util.Abort(_('factotum not interactive'))
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    58
    if 'user=' not in params:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    59
        params = '%s user?' % params
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    60
    params = '%s !password?' % params
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    61
    os.system("%s -g '%s'" % (_path, params))
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    62
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    63
def auth_getuserpasswd(self, getkey, params):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    64
    params = 'proto=pass %s' % params
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    65
    while True:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    66
        fd = os.open('%s/rpc' % _mount, os.O_RDWR)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    67
        try:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    68
            try:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    69
                os.write(fd, 'start %s' % params)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    70
                l = os.read(fd, ERRMAX).split()
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    71
                if l[0] == 'ok':
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    72
                    os.write(fd, 'read')
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    73
                    l = os.read(fd, ERRMAX).split()
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    74
                    if l[0] == 'ok':
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    75
                        return l[1:]
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    76
            except (OSError, IOError):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    77
                raise util.Abort(_('factotum not responding'))
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    78
        finally:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    79
            os.close(fd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    80
        getkey(self, params)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    81
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    82
def monkeypatch_method(cls):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    83
    def decorator(func):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    84
        setattr(cls, func.__name__, func)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    85
        return func
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    86
    return decorator
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    87
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    88
@monkeypatch_method(passwordmgr)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    89
def find_user_password(self, realm, authuri):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    90
    user, passwd = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    91
        self, realm, authuri)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    92
    if user and passwd:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    93
        self._writedebug(user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    94
        return (user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    95
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    96
    prefix = ''
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    97
    res = httpconnection.readauthforuri(self.ui, authuri, user)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    98
    if res:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
    99
        _, auth = res
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   100
        prefix = auth.get('prefix')
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   101
        user, passwd = auth.get('username'), auth.get('password')
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   102
    if not user or not passwd:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   103
        if not prefix:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   104
            prefix = '*'
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   105
        params = 'service=%s prefix=%s' % (_service, prefix)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   106
        if user:
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   107
            params = '%s user=%s' % (params, user)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   108
        user, passwd = auth_getuserpasswd(self, auth_getkey, params)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   109
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   110
    self.add_password(realm, authuri, user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   111
    self._writedebug(user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   112
    return (user, passwd)
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   113
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   114
def uisetup(ui):
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   115
    global _mount
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   116
    _mount = ui.config('factotum', 'mount', '/mnt/factotum')
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   117
    global _path
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   118
    _path = ui.config('factotum', 'path', '/bin/auth/factotum')
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   119
    global _service
f5dd179bfa4a plan9: initial support for plan 9 from bell labs
Steven Stallion <sstallion@gmail.com>
parents:
diff changeset
   120
    _service = ui.config('factotum', 'service', 'hg')