Attachment 'RemoteAuth.py'
Download 1 # LEG25062006
2 # LEG20080704
3 # Martin Schwarzbauer added wikipedia_mysql authentication
4 #
5 # Several authentication modules which try to log in the use
6 # into some remote system like pop, ftp, etc.
7 #
8 # typically you would use it somehow like:
9 '''
10 from RemoteAuth import <auth>, <map>, cookie
11 auth = [<auth>, <map> <cookie>]
12 auth_<*>_verbose=True
13 auth_<auth>_server=<server where to authenticate>
14 auth_<auth>_ssl=<True|False>
15 # Create User Profile on first login
16 # Note: need to login a second time then
17 user_autocreate=True
18 '''
19 #
20 # the 'cookie' module is a remake of 'moin_cookie', but it does not
21 # use the username from the login form, instead it expects it to be
22 # found in the user_obj
23 #
24 # the <map> modules, currently 'gecos', map a name from the login
25 # form, to something else. Often the <auth> module needs an account
26 # name or email address, which is not suitable as a WikiName. The
27 # <map> modules can help out with this issue.
28 # map modules:
29 # gecos .. gets the gecos field from the /etc/passwd file (or from
30 # nss) extracts the name field and sticks the first two
31 # strings there together
32 #
33 # the <auth> modules use some commonly used protocol which requires
34 # authentication. The take the given username and password from the
35 # login form and try to authenticate with the respective protocol.
36 # Then they log out immediately from the service. If the login was
37 # successful, the user gets authenticated to the Wiki. So it suffices
38 # to have e.g. a POP server with the accounts of the users to get a
39 # kind of Single Signon for your Wiki.
40 # auth modules:
41 # imap .. logs in to an IMAP server.
42 # ftp .. not tested
43 #
44 #
45 # Security note: it is surely prefereable to have the "remote" service
46 # run on the same machine as the Wiki, and better even to run it on
47 # "localhost". This would reduce the chance of credencial leaking.
48 #
49 # Note: an interesting module would be the 'uri' auth module, it would
50 # take an uri in the following form as username:
51 #
52 # proto://user@host e.g.:
53 #
54 # imaps://fran=FrancisBacon@mail.hiho.com
55 #
56 # the 'uri' module would then use the 'imap' module, set the server
57 # to 'mail.hiho.com', the username to 'fran', and auth_imap_ssl to
58 # True. The Wiki username would be set to "FrancisBacon"
59 #
60 # The uri module thus would allow a user to log in with credencials
61 # from wherever they please.
62 #
63 # Again note, that the user is not assured that this credencials
64 # could eventually be leaked by flaws in the Wiki or in the
65 # operating system where it is run.
66 # History:
67 #
68 # LEG25062006: initial version
69 #
70 # TODO:
71 # more modules ...
72 #
73 # Bugs:
74 #
75 # When logging in (imap), the wiki says "unknown user", however the
76 # user gets authenticated.
77
78
79 def gecos(request, **kw):
80 """ not for authentication, but rather for determining
81 the user name via a Gecos field entry from the
82 /etc/passwd file on unix-systems.
83 must be switched in between auth and cookie
84 """
85 u = kw.get('user_obj')
86
87 # If there is no user object we are at the wrong place here
88 if not u:
89 return u, True
90
91 import sys, traceback, os
92 from MoinMoin import user
93
94 verbose = request.cfg.auth_gecos_verbose
95
96 # Extract the Gecos field from the nss passwd database
97 # TODO: access /etc/passwd directly if nss not available
98 try:
99 P = os.popen("getent passwd "+u.auth_username,'r')
100 passwd = P.readline()
101 P.close
102 # TODO: fails if the user does not exist
103 gecos = passwd.split(':')[4]
104 cn = gecos.split(',')[0]
105 names = cn.split(' ')
106 # TODO: verfiy that names is not empty, etc.
107 u.name = names[0]+names[1]
108
109 except:
110 info = sys.exc_info()
111 request.log("GECOS: caught an exception, traceback follows...")
112 request.log(''.join(traceback.format_exception(*info)))
113 u.name = u.auth_username
114
115 if verbose:
116 request.log("GECOS: mapped auth_name %s to name %s" % (u.auth_username, u.name))
117
118 u.auth_method='gecos'
119 u.auth_attribs=('name', 'auth_username', 'password')
120 u.create_or_update(True)
121 return u, True # cookie has to set the cookie to maintain the session alive
122
123
124 def cookie(request, **kw):
125 """ authenticate via the MOIN_ID cookie
126 this module must be chained in after another authentication
127 module, it does not login, otherwise.
128 In contrast to moin_cookie it does not look up the user locally.
129 """
130
131 username = kw.get('name')
132 password = kw.get('password')
133 login = kw.get('login')
134 logout = kw.get('logout')
135 u = kw.get('user_obj')
136
137 from MoinMoin import auth, user
138 import Cookie
139
140 if login:
141 if not u:
142 return None, True
143
144 if u.valid:
145 auth.setCookie(request, u)
146 return u, True # we make continuing possible, e.g. for smbmount
147
148 try:
149 cookie = Cookie.SimpleCookie(request.saved_cookie)
150 except Cookie.CookieError:
151 # ignore invalid cookies, else user can't relogin
152 cookie = None
153
154 if cookie and cookie.has_key('MOIN_ID'):
155 u = user.User(request, id=cookie['MOIN_ID'].value,
156 auth_method='cookie', auth_attribs=())
157
158 if logout:
159 u.valid = 0 # just make user invalid, but remember him
160
161 if u.valid:
162 auth.setCookie(request, u) # refreshes cookie lifetime
163 return u, True # use True to get other methods called, too
164
165 else: # logout or invalid user
166 auth.deleteCookie(request)
167 return u, True # we return a invalidated user object, so that
168 # following auth methods can get the name of
169 # the user who logged out
170 return u, True
171
172
173 def imap(request, **kw):
174 """ get authentication data from form, authenticate via imap
175 user profile must be handled e.g. by cookie
176 """
177 username = kw.get('name')
178 password = kw.get('password')
179 login = kw.get('login')
180 user_obj = kw.get('user_obj')
181
182 cfg = request.cfg
183 verbose = cfg.auth_imap_verbose
184
185 if verbose:
186 request.log("IMAP: got name=%s login=%r" % (username, login))
187
188 # we just intercept login, other requests have to be
189 # handled by another auth handler
190 if not login:
191 return user_obj, True
192
193 import sys, re, imaplib
194 import traceback
195 from MoinMoin import user
196
197 u = None
198
199 try:
200 if cfg.auth_imap_ssl:
201 M = imaplib.IMAP4_SSL(cfg.auth_imap_server)
202 else:
203 M = imaplib.IMAP4(cfg.auth_imap_server)
204 try:
205 M.login(username, password)
206 u = user.User(request,
207 auth_username=username,
208 name=username,
209 password=password,
210 auth_method='imap',
211 auth_attribs=('name', 'auth_username', 'password',))
212 except M.error, err:
213 request.log("IMAP: Login failed: %s" % err)
214
215 except:
216 info = sys.exc_info()
217 request.log("IMAP: caught an exception, traceback follows...")
218 request.log(''.join(traceback.format_exception(*info)))
219
220
221 if u:
222 u.create_or_update(True)
223 return u, True
224
225 def wikipedia_mysql(request, **kw):
226 """ get authentication data from Wikipedia database
227 """
228 username = kw.get('name')
229 password = kw.get('password')
230 login = kw.get('login')
231 user_obj = kw.get('user_obj')
232
233 cfg = request.cfg
234 mysql_host = cfg.auth_wikipedia_mysql_host
235 mysql_user = cfg.auth_wikipedia_mysql_user
236 mysql_passwd = cfg.auth_wikipedia_mysql_passwd
237 mysql_db = cfg.auth_wikipedia_mysql_db
238
239 # we just intercept login, other requests have to be
240 # handled by another auth handler
241 if not login:
242 return user_obj, True
243
244 import sys, re, MySQLdb
245 import traceback
246 from MoinMoin import user
247
248 u = None
249
250 try:
251 conn = MySQLdb.connect(host = mysql_host, user = mysql_user, passwd = mysql_passwd, db = mysql_db)
252 cursor = conn.cursor()
253 query = """
254 SELECT (user_password = MD5(CONCAT(user_id,'-',MD5('"""+password+"""'))))
255 FROM (
256 SELECT user_id, user_password
257 FROM user
258 WHERE user_name = '"""+username.capitalize()+"""'
259 ) AS Temp;"""
260
261 cursor.execute(query)
262
263 result = cursor.fetchall()
264
265 # check if password and username are valid
266 if len (result) == 1:
267 if (result[0])[0]:
268
269 # request.log("wikipedia_mysql: Login successful")
270 # request.log("wikipedia_mysql Username:" + username)
271 u = user.User(request,
272 auth_username=username,
273 name=username,
274 password=password,
275 auth_method='wikipedia_mysql',
276 auth_attribs=('name', 'auth_username', 'password',))
277 u.valid = True
278
279 except:
280 info = sys.exc_info()
281 request.log("Wikipedia: caught an exception, traceback follows...")
282 request.log(''.join(traceback.format_exception(*info)))
283
284 if u:
285 u.create_or_update(True)
286
287 # clean up
288 cursor.close()
289 conn.close()
290
291 return u, True
292
293 def ftp(request, **kw):
294 """ get authentication data from form, authenticate via ftp
295 user profile must be handled e.g. by cookie
296 """
297 username = kw.get('name')
298 password = kw.get('password')
299 login = kw.get('login')
300 user_obj = kw.get('user_obj')
301
302 cfg = request.cfg
303 verbose = cfg.auth_ftp_verbose
304
305 if verbose:
306 request.log("FTP: got name=%s login=%r" % (username, login))
307
308 # we just intercept login, other requests have to be
309 # handled by another auth handler
310 if not login:
311 return user_obj, True
312
313 import sys, re, ftplib
314 import traceback
315 from MoinMoin import user
316
317 u = None
318
319 try:
320 F = ftplib.FTP(cfg.auth_ftp_server, username, password)
321 u = user.User(request,
322 auth_username=username,
323 name=username,
324 password=password,
325 auth_method='ftp',
326 auth_attribs=('name', 'auth_username', 'password',))
327 except:
328 info = sys.exc_info()
329 request.log("FTP: caught an exception, traceback follows...")
330 request.log(''.join(traceback.format_exception(*info)))
331
332 if u:
333 u.create_or_update(True)
334 return u, True
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.