##// END OF EJS Templates
factotum: convert Plan 9 quoted string to Python string
David Eckhardt -
r23393:c834c019 default
parent child Browse files
Show More
@@ -1,122 +1,127 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 mercurial.i18n import _
49 49 from mercurial.url import passwordmgr
50 50 from mercurial import httpconnection, util
51 51 import os, urllib2
52 52
53 53 ERRMAX = 128
54 54
55 55 _executable = _mountpoint = _service = None
56 56
57 57 def auth_getkey(self, params):
58 58 if not self.ui.interactive():
59 59 raise util.Abort(_('factotum not interactive'))
60 60 if 'user=' not in params:
61 61 params = '%s user?' % params
62 62 params = '%s !password?' % params
63 63 os.system("%s -g '%s'" % (_executable, params))
64 64
65 65 def auth_getuserpasswd(self, getkey, params):
66 66 params = 'proto=pass %s' % params
67 67 while True:
68 68 fd = os.open('%s/rpc' % _mountpoint, os.O_RDWR)
69 69 try:
70 70 try:
71 71 os.write(fd, 'start %s' % params)
72 72 l = os.read(fd, ERRMAX).split()
73 73 if l[0] == 'ok':
74 74 os.write(fd, 'read')
75 l = os.read(fd, ERRMAX).split()
76 if l[0] == 'ok':
77 return l[1:]
75 status, user, passwd = os.read(fd, ERRMAX).split(None, 2)
76 if status == 'ok':
77 if passwd.startswith("'"):
78 if passwd.endswith("'"):
79 passwd = passwd[1:-1].replace("''", "'")
80 else:
81 raise util.Abort(_('malformed password string'))
82 return (user, passwd)
78 83 except (OSError, IOError):
79 84 raise util.Abort(_('factotum not responding'))
80 85 finally:
81 86 os.close(fd)
82 87 getkey(self, params)
83 88
84 89 def monkeypatch_method(cls):
85 90 def decorator(func):
86 91 setattr(cls, func.__name__, func)
87 92 return func
88 93 return decorator
89 94
90 95 @monkeypatch_method(passwordmgr)
91 96 def find_user_password(self, realm, authuri):
92 97 user, passwd = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
93 98 self, realm, authuri)
94 99 if user and passwd:
95 100 self._writedebug(user, passwd)
96 101 return (user, passwd)
97 102
98 103 prefix = ''
99 104 res = httpconnection.readauthforuri(self.ui, authuri, user)
100 105 if res:
101 106 _, auth = res
102 107 prefix = auth.get('prefix')
103 108 user, passwd = auth.get('username'), auth.get('password')
104 109 if not user or not passwd:
105 110 if not prefix:
106 111 prefix = realm.split(' ')[0].lower()
107 112 params = 'service=%s prefix=%s' % (_service, prefix)
108 113 if user:
109 114 params = '%s user=%s' % (params, user)
110 115 user, passwd = auth_getuserpasswd(self, auth_getkey, params)
111 116
112 117 self.add_password(realm, authuri, user, passwd)
113 118 self._writedebug(user, passwd)
114 119 return (user, passwd)
115 120
116 121 def uisetup(ui):
117 122 global _executable
118 123 _executable = ui.config('factotum', 'executable', '/bin/auth/factotum')
119 124 global _mountpoint
120 125 _mountpoint = ui.config('factotum', 'mountpoint', '/mnt/factotum')
121 126 global _service
122 127 _service = ui.config('factotum', 'service', 'hg')
General Comments 0
You need to be logged in to leave comments. Login now