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