##// END OF EJS Templates
configitems: register the 'factotum.service' config
marmoute -
r33240:a9524aea default
parent child Browse files
Show More
@@ -1,145 +1,148 b''
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 73 configitem('factotum', 'mountpoint',
74 74 default='/mnt/factotum',
75 75 )
76 configitem('factotum', 'service',
77 default='hg',
78 )
76 79
77 80 def auth_getkey(self, params):
78 81 if not self.ui.interactive():
79 82 raise error.Abort(_('factotum not interactive'))
80 83 if 'user=' not in params:
81 84 params = '%s user?' % params
82 85 params = '%s !password?' % params
83 86 os.system("%s -g '%s'" % (_executable, params))
84 87
85 88 def auth_getuserpasswd(self, getkey, params):
86 89 params = 'proto=pass %s' % params
87 90 while True:
88 91 fd = os.open('%s/rpc' % _mountpoint, os.O_RDWR)
89 92 try:
90 93 os.write(fd, 'start %s' % params)
91 94 l = os.read(fd, ERRMAX).split()
92 95 if l[0] == 'ok':
93 96 os.write(fd, 'read')
94 97 status, user, passwd = os.read(fd, ERRMAX).split(None, 2)
95 98 if status == 'ok':
96 99 if passwd.startswith("'"):
97 100 if passwd.endswith("'"):
98 101 passwd = passwd[1:-1].replace("''", "'")
99 102 else:
100 103 raise error.Abort(_('malformed password string'))
101 104 return (user, passwd)
102 105 except (OSError, IOError):
103 106 raise error.Abort(_('factotum not responding'))
104 107 finally:
105 108 os.close(fd)
106 109 getkey(self, params)
107 110
108 111 def monkeypatch_method(cls):
109 112 def decorator(func):
110 113 setattr(cls, func.__name__, func)
111 114 return func
112 115 return decorator
113 116
114 117 @monkeypatch_method(passwordmgr)
115 118 def find_user_password(self, realm, authuri):
116 119 user, passwd = self.passwddb.find_user_password(realm, authuri)
117 120 if user and passwd:
118 121 self._writedebug(user, passwd)
119 122 return (user, passwd)
120 123
121 124 prefix = ''
122 125 res = httpconnection.readauthforuri(self.ui, authuri, user)
123 126 if res:
124 127 _, auth = res
125 128 prefix = auth.get('prefix')
126 129 user, passwd = auth.get('username'), auth.get('password')
127 130 if not user or not passwd:
128 131 if not prefix:
129 132 prefix = realm.split(' ')[0].lower()
130 133 params = 'service=%s prefix=%s' % (_service, prefix)
131 134 if user:
132 135 params = '%s user=%s' % (params, user)
133 136 user, passwd = auth_getuserpasswd(self, auth_getkey, params)
134 137
135 138 self.add_password(realm, authuri, user, passwd)
136 139 self._writedebug(user, passwd)
137 140 return (user, passwd)
138 141
139 142 def uisetup(ui):
140 143 global _executable
141 144 _executable = ui.config('factotum', 'executable')
142 145 global _mountpoint
143 146 _mountpoint = ui.config('factotum', 'mountpoint')
144 147 global _service
145 _service = ui.config('factotum', 'service', 'hg')
148 _service = ui.config('factotum', 'service')
General Comments 0
You need to be logged in to leave comments. Login now