Attachment 'ldap_group2.patch'
Download 1 diff -r a8a777074233 MoinMoin/auth/ldap_login.py
2 --- a/MoinMoin/auth/ldap_login.py Mon Jul 27 01:55:59 2009 +0200
3 +++ b/MoinMoin/auth/ldap_login.py Wed Jul 29 20:22:10 2009 +0200
4 @@ -229,6 +229,7 @@
5 else:
6 u = user.User(request, auth_username=username, auth_method=self.name, auth_attribs=('name', 'password', 'mailto_author', ))
7 u.name = username
8 + u.dn = dn
9 u.aliasname = aliasname
10 u.remember_me = 0 # 0 enforces cookie_lifetime config param
11 logging.debug("creating userprefs with name %r email %r alias %r" % (username, email, aliasname))
12 diff -r a8a777074233 MoinMoin/datastruct/backends/ldap_groups.py
13 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14 +++ b/MoinMoin/datastruct/backends/ldap_groups.py Wed Jul 29 20:22:10 2009 +0200
15 @@ -0,0 +1,91 @@
16 +# -*- coding: iso-8859-1 -*-
17 +"""
18 + MoinMoin - ldap group lazy backend.
19 +
20 + The ldap group backend allows one to define groups in an
21 + ldap server. Group members must be authenticated via
22 + ldap.
23 +
24 + @copyright: 2009 Benoit Peccatte (peck)
25 + @license: GPL, see COPYING for details
26 +"""
27 +
28 +from MoinMoin import log
29 +logging = log.getLogger(__name__)
30 +
31 +from MoinMoin.user import User
32 +from MoinMoin.datastruct.backends import LazyGroup, LazyGroupsBackend
33 +from MoinMoin.util.ldap_connection import LDAPConnection
34 +
35 +import ldap
36 +
37 +class LdapGroup(LazyGroup):
38 + pass
39 +
40 +
41 +class LdapGroups(LazyGroupsBackend):
42 +
43 + def __init__(self, request,
44 + ldap_connection, # LDAPConnection to use for connections
45 + base_dn='', # base ldap dn to use when searching for groups
46 + scope=ldap.SCOPE_SUBTREE, # scope of the search
47 + filter='', # filter to use when searching for groups
48 + member_attribute='member', # attribute name for group members
49 + name_attribute='cn', # attribute name for group name
50 + ):
51 +
52 + super(LdapGroups, self).__init__(request)
53 + self.base = base_dn
54 + self.scope = scope
55 + if filter != '' and not filter.startswith('('):
56 + filter = filter = '(%s)' % filter
57 + self.filter = filter
58 + self.member_attribute = member_attribute
59 + self.name_attribute = name_attribute
60 + self.ldap = ldap_connection
61 +
62 + def __contains__(self, group_name):
63 + filter = self._getfilter(group_name)
64 + res = self.ldap.search_single(self.base, self.scope, filter, 'dn')
65 + return res != []
66 +
67 + def __iter__(self):
68 + filter = self._getfilter('*')
69 + res = self.ldap.search_single(self.base, self.scope, filter, self.name_attribute)
70 + # XXX better group name rebuilding ? needs configurability
71 + res = [ '%sGroup' % x for x in res ]
72 + return res.__iter__()
73 +
74 + def __getitem__(self, group_name):
75 + return LdapGroup(self.request, group_name, self)
76 +
77 + def _iter_group_members(self, group_name):
78 + filter = self._getfilter(group_name)
79 + return self.ldap.search_single( self.base, self.scope, filter, self.member_attribute)
80 +
81 + def _group_has_member(self, group_name, member):
82 + # only check users that are authenticated using ldap
83 + u = User(self.request, auth_username=member)
84 + if not hasattr(u, 'dn'):
85 + return False
86 + filter = self._getfilter(group_name, u.dn)
87 + res = self.ldap.search_single( self.base, self.scope, filter, 'dn')
88 + return res != []
89 +
90 + def _getfilter(self, group_name, member=None):
91 + """ Create a filter string for a group.
92 + Add a member filter if one is provided."""
93 + # extract real group name from the form XxxGroup
94 + grp = self.page_group_regex.search(group_name)
95 + if grp:
96 + group = grp.group(2)
97 + else:
98 + group = group_name
99 +
100 + filter = '(%s=%s)' % (self.name_attribute, group)
101 + if self.filter:
102 + filter = '(&%s%s)' % (self.filter, filter)
103 + if member:
104 + filter = '(&%s(%s=%s))' % (filter, self.member_attribute, member)
105 + return filter
106 +
107 diff -r a8a777074233 MoinMoin/util/ldap_connection.py
108 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109 +++ b/MoinMoin/util/ldap_connection.py Wed Jul 29 20:22:10 2009 +0200
110 @@ -0,0 +1,135 @@
111 +# -*- coding: iso-8859-1 -*-
112 +"""
113 + MoinMoin - ldap connection object
114 +
115 + The connexion object holds informations to connect to a single
116 + ldap server.
117 +
118 + @copyright: 2006-2008 MoinMoin:ThomasWaldmann,
119 + 2006 Nick Phillips
120 + 2009 Benoit Peccatte (peck)
121 + @license: GPL, see COPYING for details
122 +"""
123 +
124 +from MoinMoin import log
125 +logging = log.getLogger(__name__)
126 +
127 +try:
128 + import ldap
129 +except ImportError, err:
130 + logging.error("You need to have python-ldap installed (%s)." % str(err))
131 + raise
132 +
133 +class LDAPConnection(object):
134 + def __init__(self,
135 + server_uri='ldap://localhost', # ldap / active directory server URI
136 + # use ldaps://server:636 url for ldaps,
137 + # use ldap://server for ldap without tls (and set start_tls to 0),
138 + # use ldap://server for ldap with tls (and set start_tls to 1 or 2).
139 + bind_dn='', # We can only use fixed user and password here
140 + # TODO implement "the username and password we got from the user" in ldap_auth
141 + bind_pw='',
142 + referrals=0, # LDAP REFERRALS (0 needed for AD)
143 + coding='utf-8', # coding used for ldap queries and result values
144 + timeout=10, # how long we wait for the ldap server [s]
145 + start_tls=0, # 0 = No, 1 = Try, 2 = Required
146 + tls_cacertdir=None,
147 + tls_cacertfile=None,
148 + tls_certfile=None,
149 + tls_keyfile=None,
150 + tls_require_cert=0, # 0 == ldap.OPT_X_TLS_NEVER (needed for self-signed certs)
151 + ):
152 +
153 + self.server_uri = server_uri
154 + self.bind_dn = bind_dn
155 + self.bind_pw = bind_pw
156 + self.referrals = referrals
157 + self.coding = coding
158 + self.timeout = timeout
159 + self.start_tls = start_tls
160 + self.tls_cacertdir = tls_cacertdir
161 + self.tls_cacertfile = tls_cacertfile
162 + self.tls_certfile = tls_certfile
163 + self.tls_keyfile = tls_keyfile
164 + self.tls_require_cert = tls_require_cert
165 +
166 + self.ldap = None
167 +
168 + def __connect(self):
169 + """ Make a new connection to ldap only if needed.
170 + Public method should call this."""
171 + if self.ldap:
172 + return
173 + self.ldap = self.__new_ldap(self.bind_dn, self.bind_pw)
174 +
175 + def __new_ldap(self, binddn, password):
176 + """ Create a connection object and bind. """
177 + try:
178 + # options
179 + logging.debug("Setting misc. ldap options...")
180 + ldap.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)
181 + ldap.set_option(ldap.OPT_REFERRALS, self.referrals)
182 + ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)
183 + if hasattr(ldap, 'TLS_AVAIL') and ldap.TLS_AVAIL:
184 + for option, value in (
185 + (ldap.OPT_X_TLS_CACERTDIR, self.tls_cacertdir),
186 + (ldap.OPT_X_TLS_CACERTFILE, self.tls_cacertfile),
187 + (ldap.OPT_X_TLS_CERTFILE, self.tls_certfile),
188 + (ldap.OPT_X_TLS_KEYFILE, self.tls_keyfile),
189 + (ldap.OPT_X_TLS_REQUIRE_CERT, self.tls_require_cert),
190 + (ldap.OPT_X_TLS, self.start_tls),
191 + #(ldap.OPT_X_TLS_ALLOW, 1),
192 + ):
193 + if value is not None:
194 + ldap.set_option(option, value)
195 +
196 + # connect and bind
197 + logging.debug("Trying to initialize %r." % self.server_uri)
198 + conn = ldap.initialize(self.server_uri)
199 + conn.protocol_version = ldap.VERSION3 # recommended by documentation
200 + logging.debug("Connected to LDAP server %r." % self.server_uri)
201 + if self.start_tls and server.startswith('ldap:'):
202 + logging.debug("Trying to start TLS to %r." % self.server_uri)
203 + try:
204 + conn.start_tls_s()
205 + logging.debug("Using TLS to %r." % self.server_uri)
206 + except (ldap.SERVER_DOWN, ldap.CONNECT_ERROR), err:
207 + logging.warning("Couldn't establish TLS to %r (err: %s)." % (self.server_uri, str(err)))
208 + raise
209 +
210 + conn.simple_bind_s(binddn.encode(self.coding), password.encode(self.coding))
211 + logging.debug("Bound with binddn %r" % binddn)
212 + return conn
213 + except ldap.LDAPError, error_message:
214 + print "LDAP error %r" % error_message
215 + raise
216 +
217 + def authenticate(self, binddn, passwd):
218 + # TODO for ldap_auth.py
219 + return
220 +
221 + def search(self, base, scope, filter, attributes):
222 + """ Make a specific search on the ldap server """
223 + self.__connect()
224 + try:
225 + result_id = self.ldap.search(base.encode(self.coding),
226 + scope,
227 + filter.encode(self.coding),
228 + attributes)
229 + result_type, result_data = self.ldap.result(result_id, self.timeout)
230 + if result_type == ldap.RES_SEARCH_RESULT:
231 + return result_data
232 + else:
233 + print "unknown result_type"
234 + except ldap.LDAPError, error_message:
235 + print "search error %s" % error_message
236 +
237 + def search_single(self, base, scope, filter, attribute):
238 + """ Search for a single attribute, returns an array of single values. """
239 + res = self.search(base, scope, filter, [attribute])
240 + if(attribute == 'dn'):
241 + res = [x[0] for x in res]
242 + else:
243 + res = [x[1][attribute][0] for x in res]
244 + return res
245 +
246
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.