##// END OF EJS Templates
configitems: register the 'factotum.mountpoint' config
marmoute -
r33239:037c5c93 default
parent child Browse files
Show More
@@ -1,142 +1,145
1 1 # factotum.py - Plan 9 factotum integration for Mercurial
2 2 #
3 3 # Copyright (C) 2012 Steven Stallion <sstallion@gmail.com>
4 4 #
5 5 # This program is free software; you can redistribute it and/or modify it
6 6 # under the terms of the GNU General Public License as published by the
7 7 # Free Software Foundation; either version 2 of the License, or (at your
8 8 # option) any later version.
9 9 #
10 10 # This program is distributed in the hope that it will be useful, but
11 11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 13 # Public License for more details.
14 14 #
15 15 # You should have received a copy of the GNU General Public License along
16 16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 18
19 19 '''http authentication with factotum
20 20
21 21 This extension allows the factotum(4) facility on Plan 9 from Bell Labs
22 22 platforms to provide authentication information for HTTP access. Configuration
23 23 entries specified in the auth section as well as authentication information
24 24 provided in the repository URL are fully supported. If no prefix is specified,
25 25 a value of "*" will be assumed.
26 26
27 27 By default, keys are specified as::
28 28
29 29 proto=pass service=hg prefix=<prefix> user=<username> !password=<password>
30 30
31 31 If the factotum extension is unable to read the required key, one will be
32 32 requested interactively.
33 33
34 34 A configuration section is available to customize runtime behavior. By
35 35 default, these entries are::
36 36
37 37 [factotum]
38 38 executable = /bin/auth/factotum
39 39 mountpoint = /mnt/factotum
40 40 service = hg
41 41
42 42 The executable entry defines the full path to the factotum binary. The
43 43 mountpoint entry defines the path to the factotum file service. Lastly, the
44 44 service entry controls the service name used when reading keys.
45 45
46 46 '''
47 47
48 48 from __future__ import absolute_import
49 49
50 50 import os
51 51 from mercurial.i18n import _
52 52 from mercurial import (
53 53 error,
54 54 httpconnection,
55 55 registrar,
56 56 url,
57 57 util,
58 58 )
59 59
60 60 urlreq = util.urlreq
61 61 passwordmgr = url.passwordmgr
62 62
63 63 ERRMAX = 128
64 64
65 65 _executable = _mountpoint = _service = None
66 66
67 67 configtable = {}
68 68 configitem = registrar.configitem(configtable)
69 69
70 70 configitem('factotum', 'executable',
71 71 default='/bin/auth/factotum',
72 72 )
73 configitem('factotum', 'mountpoint',
74 default='/mnt/factotum',
75 )
73 76
74 77 def auth_getkey(self, params):
75 78 if not self.ui.interactive():
76 79 raise error.Abort(_('factotum not interactive'))
77 80 if 'user=' not in params:
78 81 params = '%s user?' % params
79 82 params = '%s !password?' % params
80 83 os.system("%s -g '%s'" % (_executable, params))
81 84
82 85 def auth_getuserpasswd(self, getkey, params):
83 86 params = 'proto=pass %s' % params
84 87 while True:
85 88 fd = os.open('%s/rpc' % _mountpoint, os.O_RDWR)
86 89 try:
87 90 os.write(fd, 'start %s' % params)
88 91 l = os.read(fd, ERRMAX).split()
89 92 if l[0] == 'ok':
90 93 os.write(fd, 'read')
91 94 status, user, passwd = os.read(fd, ERRMAX).split(None, 2)
92 95 if status == 'ok':
93 96 if passwd.startswith("'"):
94 97 if passwd.endswith("'"):
95 98 passwd = passwd[1:-1].replace("''", "'")
96 99 else:
97 100 raise error.Abort(_('malformed password string'))
98 101 return (user, passwd)
99 102 except (OSError, IOError):
100 103 raise error.Abort(_('factotum not responding'))
101 104 finally:
102 105 os.close(fd)
103 106 getkey(self, params)
104 107
105 108 def monkeypatch_method(cls):
106 109 def decorator(func):
107 110 setattr(cls, func.__name__, func)
108 111 return func
109 112 return decorator
110 113
111 114 @monkeypatch_method(passwordmgr)
112 115 def find_user_password(self, realm, authuri):
113 116 user, passwd = self.passwddb.find_user_password(realm, authuri)
114 117 if user and passwd:
115 118 self._writedebug(user, passwd)
116 119 return (user, passwd)
117 120
118 121 prefix = ''
119 122 res = httpconnection.readauthforuri(self.ui, authuri, user)
120 123 if res:
121 124 _, auth = res
122 125 prefix = auth.get('prefix')
123 126 user, passwd = auth.get('username'), auth.get('password')
124 127 if not user or not passwd:
125 128 if not prefix:
126 129 prefix = realm.split(' ')[0].lower()
127 130 params = 'service=%s prefix=%s' % (_service, prefix)
128 131 if user:
129 132 params = '%s user=%s' % (params, user)
130 133 user, passwd = auth_getuserpasswd(self, auth_getkey, params)
131 134
132 135 self.add_password(realm, authuri, user, passwd)
133 136 self._writedebug(user, passwd)
134 137 return (user, passwd)
135 138
136 139 def uisetup(ui):
137 140 global _executable
138 141 _executable = ui.config('factotum', 'executable')
139 142 global _mountpoint
140 _mountpoint = ui.config('factotum', 'mountpoint', '/mnt/factotum')
143 _mountpoint = ui.config('factotum', 'mountpoint')
141 144 global _service
142 145 _service = ui.config('factotum', 'service', 'hg')
General Comments 0
You need to be logged in to leave comments. Login now