Attachment 'ldap_login_refactored.patch'
Download 1 # HG changeset patch
2 # User Thomas Waldmann <tw AT waldmann-edv DOT de>
3 # Date 1204717258 -3600
4 # Node ID 9d3f64f9daf49736ab8f6fa8f3efa71bc6c5bc10
5 # Parent 6e28cd3623a1819683b440b13e2d36288e9436b8
6 ldap_login auth: move configuration values to auth object init parameters
7
8 diff -r 6e28cd3623a1 -r 9d3f64f9daf4 MoinMoin/auth/ldap_login.py
9 --- a/MoinMoin/auth/ldap_login.py Tue Mar 04 20:58:07 2008 +0100
10 +++ b/MoinMoin/auth/ldap_login.py Wed Mar 05 12:40:58 2008 +0100
11 @@ -2,8 +2,8 @@
12 """
13 MoinMoin - LDAP / Active Directory authentication
14
15 - This code only creates a user object, the session has to be established by
16 - the auth.moin_session auth plugin.
17 + This code only creates a user object, the session will be established by
18 + moin automatically.
19
20 python-ldap needs to be at least 2.0.0pre06 (available since mid 2002) for
21 ldaps support - some older debian installations (woody and older?) require
22 @@ -11,9 +11,7 @@
23 "Can't contact LDAP server" - more recent debian installations have tls
24 support in libldap2 (see dependency on gnutls) and also in python-ldap.
25
26 - TODO: migrate configuration items to constructor parameters,
27 - allow more configuration (alias name, ...) by using
28 - callables as parameters
29 + TODO: allow more configuration (alias name, ...) by using callables as parameters
30
31 @copyright: 2006-2008 MoinMoin:ThomasWaldmann,
32 2006 Nick Phillips
33 @@ -31,20 +29,90 @@ class LDAPAuth(BaseAuth):
34 class LDAPAuth(BaseAuth):
35 """ get authentication data from form, authenticate against LDAP (or Active
36 Directory), fetch some user infos from LDAP and create a user object
37 - for that user. The session is kept by the moin_session auth plugin.
38 + for that user. The session is kept by moin automatically.
39 """
40
41 login_inputs = ['username', 'password']
42 logout_possible = True
43 name = 'ldap'
44 +
45 + def __init__(self,
46 + server_uri='ldap://localhost', # ldap / active directory server URI
47 + # use ldaps://server:636 url for ldaps,
48 + # use ldap://server for ldap without tls (and set start_tls to 0),
49 + # use ldap://server for ldap with tls (and set start_tls to 1 or 2).
50 + bind_dn='', # We can either use some fixed user and password for binding to LDAP.
51 + # Be careful if you need a % char in those strings - as they are used as
52 + # a format string, you have to write %% to get a single % in the end.
53 + #bind_dn = 'binduser@example.org' # (AD)
54 + #bind_dn = 'cn=admin,dc=example,dc=org' # (OpenLDAP)
55 + #bind_pw = 'secret'
56 + # or we can use the username and password we got from the user:
57 + #bind_dn = '%(username)s@example.org' # DN we use for first bind (AD)
58 + #bind_pw = '%(password)s' # password we use for first bind
59 + # or we can bind anonymously (if that is supported by your directory).
60 + # In any case, bind_dn and bind_pw must be defined.
61 + bind_pw='',
62 + base_dn='', # base DN we use for searching
63 + #base_dn = 'ou=SOMEUNIT,dc=example,dc=org'
64 + scope=ldap.SCOPE_SUBTREE, # scope of the search we do (2 == ldap.SCOPE_SUBTREE)
65 + referrals=0, # LDAP REFERRALS (0 needed for AD)
66 + search_filter='(uid=%(username)s)', # ldap filter used for searching:
67 + #search_filter = '(sAMAccountName=%(username)s)' # (AD)
68 + #search_filter = '(uid=%(username)s)' # (OpenLDAP)
69 + # you can also do more complex filtering like:
70 + # "(&(cn=%(username)s)(memberOf=CN=WikiUsers,OU=Groups,DC=example,DC=org))"
71 + # some attribute names we use to extract information from LDAP:
72 + givenname_attribute=None, # ('givenName') ldap attribute we get the first name from
73 + surname_attribute=None, # ('sn') ldap attribute we get the family name from
74 + aliasname_attribute=None, # ('displayName') ldap attribute we get the aliasname from
75 + email_attribute=None, # ('mail') ldap attribute we get the email address from
76 + email_callback=None, # called to make up email address
77 + coding='utf-8', # coding used for ldap queries and result values
78 + timeout=10, # how long we wait for the ldap server [s]
79 + verbose=True, # if True, put lots of LDAP debug info into the log
80 + start_tls=0, # 0 = No, 1 = Try, 2 = Required
81 + tls_cacertdir='',
82 + tls_cacertfile='',
83 + tls_certfile='',
84 + tls_keyfile='',
85 + tls_require_cert=0, # 0 == ldap.OPT_X_TLS_NEVER (needed for self-signed certs)
86 + bind_once=False, # set to True to only do one bind - useful if configured to bind as the user on the first attempt
87 + ):
88 + self.server_uri = server_uri
89 + self.bind_dn = bind_dn
90 + self.bind_pw = bind_pw
91 + self.base_dn = base_dn
92 + self.scope = scope
93 + self.referrals = referrals
94 + self.search_filter = search_filter
95 +
96 + self.givenname_attribute = givenname_attribute
97 + self.surname_attribute = surname_attribute
98 + self.aliasname_attribute = aliasname_attribute
99 + self.email_attribute = email_attribute
100 + self.email_callback = email_callback
101 +
102 + self.coding = coding
103 + self.timeout = timeout
104 + self.verbose = verbose
105 +
106 + self.start_tls = start_tls
107 + self.tls_cacertdir = tls_cacertdir
108 + self.tls_cacertfile = tls_cacertfile
109 + self.tls_certfile = tls_certfile
110 + self.tls_keyfile = tls_keyfile
111 + self.tls_require_cert = tls_require_cert
112 +
113 + self.bind_once = bind_once
114 +
115
116 def login(self, request, user_obj, **kw):
117 username = kw.get('username')
118 password = kw.get('password')
119 _ = request.getText
120
121 - cfg = request.cfg
122 - verbose = cfg.ldap_verbose
123 + verbose = self.verbose
124
125 # we require non-empty password as ldap bind does a anon (not password
126 # protected) bind if the password is empty and SUCCEEDS!
127 @@ -55,32 +123,31 @@ class LDAPAuth(BaseAuth):
128 try:
129 u = None
130 dn = None
131 - coding = cfg.ldap_coding
132 + coding = self.coding
133 if verbose: logging.info("Setting misc. ldap options...")
134 ldap.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3) # ldap v2 is outdated
135 - ldap.set_option(ldap.OPT_REFERRALS, cfg.ldap_referrals)
136 - ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, cfg.ldap_timeout)
137 -
138 - starttls = cfg.ldap_start_tls
139 + ldap.set_option(ldap.OPT_REFERRALS, self.referrals)
140 + ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)
141 +
142 if hasattr(ldap, 'TLS_AVAIL') and ldap.TLS_AVAIL:
143 for option, value in (
144 - (ldap.OPT_X_TLS_CACERTDIR, cfg.ldap_tls_cacertdir),
145 - (ldap.OPT_X_TLS_CACERTFILE, cfg.ldap_tls_cacertfile),
146 - (ldap.OPT_X_TLS_CERTFILE, cfg.ldap_tls_certfile),
147 - (ldap.OPT_X_TLS_KEYFILE, cfg.ldap_tls_keyfile),
148 - (ldap.OPT_X_TLS_REQUIRE_CERT, cfg.ldap_tls_require_cert),
149 - (ldap.OPT_X_TLS, starttls),
150 + (ldap.OPT_X_TLS_CACERTDIR, self.tls_cacertdir),
151 + (ldap.OPT_X_TLS_CACERTFILE, self.tls_cacertfile),
152 + (ldap.OPT_X_TLS_CERTFILE, self.tls_certfile),
153 + (ldap.OPT_X_TLS_KEYFILE, self.tls_keyfile),
154 + (ldap.OPT_X_TLS_REQUIRE_CERT, self.tls_require_cert),
155 + (ldap.OPT_X_TLS, self.start_tls),
156 #(ldap.OPT_X_TLS_ALLOW, 1),
157 ):
158 if value:
159 ldap.set_option(option, value)
160
161 - server = cfg.ldap_uri
162 + server = self.server_uri
163 if verbose: logging.info("Trying to initialize %r." % server)
164 l = ldap.initialize(server)
165 if verbose: logging.info("Connected to LDAP server %r." % server)
166
167 - if starttls and server.startswith('ldap:'):
168 + if self.start_tls and server.startswith('ldap:'):
169 if verbose: logging.info("Trying to start TLS to %r." % server)
170 try:
171 l.start_tls_s()
172 @@ -90,22 +157,22 @@ class LDAPAuth(BaseAuth):
173 raise
174
175 # you can use %(username)s and %(password)s here to get the stuff entered in the form:
176 - ldap_binddn = cfg.ldap_binddn % locals()
177 - ldap_bindpw = cfg.ldap_bindpw % locals()
178 - l.simple_bind_s(ldap_binddn.encode(coding), ldap_bindpw.encode(coding))
179 - if verbose: logging.info("Bound with binddn %r" % ldap_binddn)
180 + binddn = self.bind_dn % locals()
181 + bindpw = self.bind_pw % locals()
182 + l.simple_bind_s(binddn.encode(coding), bindpw.encode(coding))
183 + if verbose: logging.info("Bound with binddn %r" % binddn)
184
185 # you can use %(username)s here to get the stuff entered in the form:
186 - filterstr = cfg.ldap_filter % locals()
187 + filterstr = self.search_filter % locals()
188 if verbose: logging.info("Searching %r" % filterstr)
189 - attrs = [getattr(cfg, attr) for attr in [
190 - 'ldap_email_attribute',
191 - 'ldap_aliasname_attribute',
192 - 'ldap_surname_attribute',
193 - 'ldap_givenname_attribute',
194 - ] if getattr(cfg, attr) is not None]
195 - lusers = l.search_st(cfg.ldap_base, cfg.ldap_scope, filterstr.encode(coding),
196 - attrlist=attrs, timeout=cfg.ldap_timeout)
197 + attrs = [getattr(self, attr) for attr in [
198 + 'email_attribute',
199 + 'aliasname_attribute',
200 + 'surname_attribute',
201 + 'givenname_attribute',
202 + ] if getattr(self, attr) is not None]
203 + lusers = l.search_st(self.base_dn, self.scope, filterstr.encode(coding),
204 + attrlist=attrs, timeout=self.timeout)
205 # we remove entries with dn == None to get the real result list:
206 lusers = [(dn, ldap_dict) for dn, ldap_dict in lusers if dn is not None]
207 if verbose:
208 @@ -123,27 +190,27 @@ class LDAPAuth(BaseAuth):
209 return CancelLogin(_("Invalid username or password."))
210
211 dn, ldap_dict = lusers[0]
212 - if not cfg.ldap_bindonce:
213 + if not self.bind_once:
214 if verbose: logging.info("DN found is %r, trying to bind with pw" % dn)
215 l.simple_bind_s(dn, password.encode(coding))
216 if verbose: logging.info("Bound with dn %r (username: %r)" % (dn, username))
217
218 - if cfg.ldap_email_callback is None:
219 - if cfg.ldap_email_attribute:
220 - email = ldap_dict.get(cfg.ldap_email_attribute, [''])[0].decode(coding)
221 + if self.email_callback is None:
222 + if self.email_attribute:
223 + email = ldap_dict.get(self.email_attribute, [''])[0].decode(coding)
224 else:
225 email = None
226 else:
227 - email = cfg.ldap_email_callback(ldap_dict)
228 + email = self.email_callback(ldap_dict)
229
230 aliasname = ''
231 try:
232 - aliasname = ldap_dict[cfg.ldap_aliasname_attribute][0]
233 + aliasname = ldap_dict[self.aliasname_attribute][0]
234 except (KeyError, IndexError):
235 pass
236 if not aliasname:
237 - sn = ldap_dict.get(cfg.ldap_surname_attribute, [''])[0]
238 - gn = ldap_dict.get(cfg.ldap_givenname_attribute, [''])[0]
239 + sn = ldap_dict.get(self.surname_attribute, [''])[0]
240 + gn = ldap_dict.get(self.givenname_attribute, [''])[0]
241 if sn and gn:
242 aliasname = "%s, %s" % (sn, gn)
243 elif sn:
244 diff -r 6e28cd3623a1 -r 9d3f64f9daf4 MoinMoin/config/multiconfig.py
245 --- a/MoinMoin/config/multiconfig.py Tue Mar 04 20:58:07 2008 +0100
246 +++ b/MoinMoin/config/multiconfig.py Wed Mar 05 12:40:58 2008 +0100
247 @@ -338,64 +338,6 @@ Lists: * bullets; 1., a. numbered items.
248 language_default = 'en'
249 language_ignore_browser = False # ignore browser settings, use language_default
250 # or user prefs
251 -
252 - # ldap / active directory server URI
253 - # use ldaps://server:636 url for ldaps,
254 - # use ldap://server for ldap without tls (and set ldap_start_tls to 0),
255 - # use ldap://server for ldap with tls (and set ldap_start_tls to 1 or 2).
256 - ldap_uri = 'ldap://localhost'
257 -
258 - # We can either use some fixed user and password for binding to LDAP.
259 - # Be careful if you need a % char in those strings - as they are used as
260 - # a format string, you have to write %% to get a single % in the end.
261 - #ldap_binddn = 'binduser@example.org' # (AD)
262 - #ldap_binddn = 'cn=admin,dc=example,dc=org' # (OpenLDAP)
263 - #ldap_bindpw = 'secret'
264 - # or we can use the username and password we got from the user:
265 - #ldap_binddn = '%(username)s@example.org' # DN we use for first bind (AD)
266 - #ldap_bindpw = '%(password)s' # password we use for first bind
267 - # or we can bind anonymously (if that is supported by your directory).
268 - # In any case, ldap_binddn and ldap_bindpw must be defined.
269 - ldap_binddn = ''
270 - ldap_bindpw = ''
271 -
272 - # base DN we use for searching
273 - #ldap_base = 'ou=SOMEUNIT,dc=example,dc=org'
274 - ldap_base = ''
275 -
276 - # scope of the search we do (2 == ldap.SCOPE_SUBTREE)
277 - ldap_scope = 2 # we do not want to import ldap for everybody just for that
278 -
279 - # LDAP REFERRALS
280 - ldap_referrals = 0 # (0 needed for AD)
281 -
282 - # ldap filter used for searching:
283 - #ldap_filter = '(sAMAccountName=%(username)s)' # (AD)
284 - ldap_filter = '(uid=%(username)s)' # (OpenLDAP)
285 - # you can also do more complex filtering like:
286 - # "(&(cn=%(username)s)(memberOf=CN=WikiUsers,OU=Groups,DC=example,DC=org))"
287 -
288 - # some attribute names we use to extract information from LDAP:
289 - ldap_givenname_attribute = None # ('givenName') ldap attribute we get the first name from
290 - ldap_surname_attribute = None # ('sn') ldap attribute we get the family name from
291 - ldap_aliasname_attribute = None # ('displayName') ldap attribute we get the aliasname from
292 - ldap_email_attribute = None # ('mail') ldap attribute we get the email address from
293 - ldap_email_callback = None # called to make up email address
294 -
295 - ldap_coding = 'utf-8' # coding used for ldap queries and result values
296 - ldap_timeout = 10 # how long we wait for the ldap server [s]
297 - ldap_verbose = True # if True, put lots of LDAP debug info into the log
298 -
299 - # TLS / SSL related defaults
300 - ldap_start_tls = 0 # 0 = No, 1 = Try, 2 = Required
301 - ldap_tls_cacertdir = ''
302 - ldap_tls_cacertfile = ''
303 - ldap_tls_certfile = ''
304 - ldap_tls_keyfile = ''
305 - ldap_tls_require_cert = 0 # 0 == ldap.OPT_X_TLS_NEVER (needed for self-signed certs)
306 -
307 - ldap_bindonce = False # set to True to only do one bind. Useful if
308 - # configured to bind as the user on the first attempt
309
310 log_reverse_dns_lookups = True # if we do reverse dns lookups for logging hostnames
311 # instead of just IPs
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.