Merge lp:~zisis00/drizzle/ldap_policy into lp:drizzle

Proposed by Zisis Sialveras
Status: Work in progress
Proposed branch: lp:~zisis00/drizzle/ldap_policy
Merge into: lp:drizzle
Diff against target: 1707 lines (+1673/-2)
5 files modified
plugin/ldap_policy/docs/index.rst (+187/-0)
plugin/ldap_policy/ldap_policy.cc (+1286/-0)
plugin/ldap_policy/ldap_policy.hpp (+194/-0)
plugin/ldap_policy/plugin.ini (+3/-0)
tests/lib/server_mgmt/drizzled.py (+3/-2)
To merge this branch: bzr merge lp:~zisis00/drizzle/ldap_policy
Reviewer Review Type Date Requested Status
Drizzle Trunk Pending
Review via email: mp+119016@code.launchpad.net

Description of the change

This branch introduce a new plugin named ldap policy. The plugin is an authentication system using LDAP. Each schema/table of Drizzle and user has a record in LDAP. The ldap_policy plugin search in LDAP and dictates if access to target schema/table from user should be granted or not. Also, it is capable to search for supplementaries groups and it has an implementation of a "per-user" cache system for better performance.

Note: Extending the testing suite to have some automated tests & writing detailed documentation are currently in progress.

To post a comment you must log in.
Revision history for this message
Brian Aker (brianaker) wrote :

Thanks, this will be reviewed next.

lp:~zisis00/drizzle/ldap_policy updated
2556. By Zisis Sialveras

Fixed some errors in ldap_policy

2557. By Zisis Sialveras

Documentation for ldap-policy

Revision history for this message
Brian Aker (brianaker) wrote :

  CXX plugin/performance_dictionary/plugin_libperformance_dictionary_plugin_la-session_usage.lo
  CXX plugin/performance_dictionary/plugin_libperformance_dictionary_plugin_la-session_usage_logger.lo
plugin/ldap_policy/ldap_policy.cc: In member function 'virtual bool ldap_policy::LDAP_policy::restrictProcess(const drizzled::identifier::User&, const drizzled::identifier::User&)':
plugin/ldap_policy/ldap_policy.cc:331:32: error: 'uid' may be used uninitialized in this function [-Werror=uninitialized]
plugin/ldap_policy/ldap_policy.cc:152:28: error: 'gid' may be used uninitialized in this function [-Werror=uninitialized]
  CXX plugin/query_log/plugin_libquery_log_plugin_la-module.lo
cc1plus: all warnings being treated as errors
  CXX plugin/query_log/plugin_libquery_log_plugin_la-query_log.lo
make[2]: *** [plugin/ldap_policy/plugin_libldap_policy_plugin_la-ldap_policy.lo] Error 1
make[2]: *** Waiting for unfinished jobs....
make[2]: Leaving directory `/home/jenkins/workspace/drizzle-smoke-test/label/ubuntu-12.04'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/jenkins/workspace/drizzle-smoke-test/label/ubuntu-12.04'
make: *** [all] Error 2
Build step 'Use builders from another project' marked build as failure
[WARNINGS] Skipping publisher since build result is FAILURE
Notifying upstream projects of job completion
Finished: FAILURE

Unmerged revisions

2557. By Zisis Sialveras

Documentation for ldap-policy

2556. By Zisis Sialveras

Fixed some errors in ldap_policy

2555. By Zisis Sialveras

Some changes in ldap_policy

2554. By Zisis Sialveras

The LDAP policy plugin.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'plugin/ldap_policy'
=== added directory 'plugin/ldap_policy/docs'
=== added file 'plugin/ldap_policy/docs/index.rst'
--- plugin/ldap_policy/docs/index.rst 1970-01-01 00:00:00 +0000
+++ plugin/ldap_policy/docs/index.rst 2012-08-21 14:09:20 +0000
@@ -0,0 +1,187 @@
1.. _ldap_policy_plugin:
2
3LDAP Authorization
4==================
5
6:program: `ldap_policy` is an :doc:`/administration/authorization` plugin that uses LDAP (Lightweight Directory Access Protocol) records to match policies.
7Each schema and table has a record in LDAP with attributes that indicate which users and groups are authorized to the target schema and/or table.
8More specifically, users exists in an LDAP directory (etc. ou=users,dc=example,dc=com). So do groups, tables and schemata.
9Schemata and tables are defined with objectClass: drizzleItem, and they can have attributes like allowedUsers and allowedGroups.
10These two attributes are the uidNumber of user or the gidNumber of the groups that should be authorized to the schema or table.
11
12The plugin is also capable to search for permissions in the supplementaries groups.
13Under the group directory (etc. ou=groups,dc=example,dc=com), may exist the groups of the users. Each group may have memberUID attribute
14if it is defined with objectClass: posixGroup. Having these, allows the plugin to understand the supplementaries groups of the user.
15So if a user has a group in supplementaries groups, and this group is authorized, then the user is authorized too, although he belong in a non-authorized
16primary group.
17
18.. seealso:: :doc:`/administration/authorization`
19.. seealso:: :doc:`/plugins/auth_ldap/index`
20
21.. _ldap_policy_loading:
22
23Loading
24-------
25
26To load this plugin, start :program:`drizzled` with::
27
28 --plugin-add=ldap_policy
29
30Loading the plugin may not enable or configure it. See the plugin's
31:ref:`ldap_policy_configuration` and :ref:`ldap_policy_variables`.
32
33.. seealso:: :ref:`drizzled_plugin_options` for more information about adding and removing plugins.
34
35.. _ldap_policy_configuration:
36
37Configuration
38-------------
39
40These command line options configure the plugin when :program:`drizzled`
41is started. See :ref:`command_line_options` for more information about specifying
42command line options.
43
44.. program:: drizzled
45
46.. option:: --ldap-policy.uri ARG
47
48 :Default: ``ldap://localhost/``
49 :Variable: :ref:`ldap_policy_uri <ldap_policy_uri>`
50
51 URI of LDAP server to connect.
52
53.. option:: --ldap-policy.users-dir ARG
54
55 :Default: ``ou=users,dc=example,dc=com``
56 :Variable: :ref:`ldap_policy_users_dir <ldap_policy_users_dir>`
57
58 The LDAP DN (distinguished name) with the users records.
59
60 Users should be in this LDAP directory, and must be defined objectClass: posixAccount. uidNumber and gidNumber attributes are required.
61
62.. option:: --ldap-policy.groups-dir ARG
63
64 :Default: ``ou=groups,dc=example,dc=com``
65 :Variable: :ref:`ldap_policy_groups_dir <ldap_policy_groups_dir>`
66
67 The LDAP DN (distinguished name) with the groups records.
68
69 Groups should be in this LDAP directory, and must be defined with objectClass: posixGroups. Although this class has as optional attribute memberUID,
70 it is essential to be filled so plugin can understand the supplementaries groups of the users.
71
72
73.. option:: --ldap-policy.schemas-dir ARG
74
75 :Default: ``ou=schemas,dc=example,dc=com``
76 :Variable: :ref:`ldap_policy_schemas_dir <ldap_policy_schemas_dir>`
77
78 The LDAP DN (distinguished name) with the schemas records.
79
80 Schemata should be in this LDAP directory, and must be defined with objectClass: drizzleItem. allowedUsers and allowedGroups attributes indicate
81 which uidNumber and gidNumber should be authorized in the current schema.
82
83.. option:: --ldap-policy.tables-dir ARG
84
85 :Default: ``ou=tables,dc=example,dc=com``
86 :Variable: :ref:`ldap_policy_tables_dir <ldap_policy_tables_dir>`
87
88 The LDAP DN (distinguished name) with the tables records.
89
90 Tables should be in this LDAP directory, and must be defined with objectClass: drizzleItem. allowedUsers and allowedGroups attributes indicate
91 which uidNumber and gidNumber should be authorized in the current table.
92
93.. option:: --ldap-policy.cache-timeout ARG
94
95 :Default: ``500``
96 :Variable: :ref:`ldap_policy_cache_timeout <ldap_policy_cache_timeout>`
97
98 How much time is valid each cache entry. (NOT implemented yet)
99
100 After a successful authorization to a schema or a table, the user and the schema/table is added in cache memory in order to achive better performance
101 the next time he/she tries to access the same schema/table again. Each cache entry is valid for only specific number of seconds.
102
103.. _ldap_policy_variables:
104
105Variables
106---------
107
108These variables show the running configuration of the plugin.
109See `variables` for more information about querying and setting variables.
110
111
112.. _ldap_policy_uri:
113* ``ldap_policy_uri``
114
115 :Scope: Global
116 :Dynamic: No
117 :Option: :option:`--ldap_policy.uri`
118
119 URI of the LDAP server to contact.
120
121.. _ldap_policy_users_dir:
122* ``ldap_policy_users_dir``
123
124 :Scope: Global
125 :Dynamic: No
126 :Option: :option:`--ldap_policy.users-dir`
127
128 The LDAP DN (distinguished name) with the users records.
129
130.. _ldap_policy_groups_dir:
131* ``ldap_policy_groups_dir``
132
133 :Scope: Global
134 :Dynamic: No
135 :Option: :option:`--ldap_policy.groups-dir`
136
137 The LDAP DN (distinguished name) with the groups records.
138
139.. _ldap_policy_schemas_dir:
140* ``ldap_policy_schemas_dir``
141
142 :Scope: Global
143 :Dynamic: No
144 :Option: :option:`--ldap_policy.schemas-dir`
145
146 The LDAP DN (distinguished name) with the schemas records.
147
148.. _ldap_policy_tables_dir:
149* ``ldap_policy_tables_dir``
150
151 :Scope: Global
152 :Dynamic: No
153 :Option: :option:`--ldap_policy.tables-dir`
154
155 The LDAP DN (distinguished name) with the tables records.
156
157
158.. ldap_policy_authors:
159
160Authors
161-------
162
163Zisis Sialveras
164
165.. ldap_policy_version:
166
167Version
168-------
169
170This documentation applies to version **ldap_policy 0.1**.
171
172To see which version of the plugin a Drizzle server is running, execute:
173
174.. code-block:: mysql
175
176 SELECT MODULE_VERSION FROM DATA_DICTIONARY.MODULES WHERE MODULE_NAME='ldap_policy'
177
178
179.. ldap_policy_changelog
180
181Changelog
182---------
183
184v0.1
185*First release.
186
187
0188
=== added file 'plugin/ldap_policy/ldap_policy.cc'
--- plugin/ldap_policy/ldap_policy.cc 1970-01-01 00:00:00 +0000
+++ plugin/ldap_policy/ldap_policy.cc 2012-08-21 14:09:20 +0000
@@ -0,0 +1,1286 @@
1/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3 *
4 * Copyright (C) 2012 Zisis Sialveras
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "ldap_policy.hpp"
21#include <drizzled/module/option_map.h>
22
23
24namespace po= boost::program_options;
25
26using namespace std;
27using namespace drizzled;
28
29namespace ldap_policy
30{
31
32static int init(module::Context &context)
33{
34 LDAP_policy *ldap_policy= new LDAP_policy();
35
36 if(ldap_policy->connect() == false)
37 {
38 errmsg_printf(error::ERROR, _("Could not load ldap_policy\n"));
39 delete ldap_policy;
40 return 1;
41 }
42
43 context.registerVariable(new sys_var_const_string_val("uri", uri));
44 context.registerVariable(new sys_var_const_string_val("users-dir", users_dir));
45 context.registerVariable(new sys_var_const_string_val("schema-dir", schemas_dir));
46 context.registerVariable(new sys_var_const_string_val("groups-dir", groups_dir));
47 context.registerVariable(new sys_var_const_string_val("tables-dir", tables_dir));
48 ///Remember to register the Variable Cache-timeout
49
50 context.add(ldap_policy);
51 return 0;
52}
53
54static void init_options(drizzled::module::option_context &context)
55{
56 context("uri", po::value<string>(&uri)->default_value(DEFAULT_URI),
57 N_("URI of the LDAP server to contact"));
58 context("users-dir", po::value<string>(&users_dir)->default_value(DEFAULT_USERS_DIR),
59 N_("Users' LDAP directory"));
60 context("schemas-dir", po::value<string>(&schemas_dir)->default_value(DEFAULT_SCHEMAS_DIR),
61 N_("Schemas' LDAP directory"));
62 context("groups-dir", po::value<string>(&groups_dir)->default_value(DEFAULT_GROUPS_DIR),
63 N_("Groups' LDAP directory"));
64 context("tables-dir", po::value<string>(&tables_dir)->default_value(DEFAULT_TABLES_DIR),
65 N_("Tables' LDAP directory"));
66 context("cache-timeout", po::value<time_t>(&cache_timeout)->default_value(DEFAULT_CACHE_TIMEOUT),
67 N_("Cache timeout"));
68}
69
70void LDAP_policy::printerror()
71{
72 errmsg_printf(error::ERROR, _(error.c_str()));
73}
74
75/**
76 * restrictProcess dictates if user A is allowed to see/kill user B connection.
77 *
78 * In the beginning, restrictProcess checks if user A and B has the same gidNumber
79 * attribute in their LDAP records. If they have not, restrictProcess checks
80 * if user's B group is one of the user's A supplementaries groups. This is done
81 * by searching in user's B group LDAP record and checking if its attributes is uid
82 * of user A.
83 */
84
85bool LDAP_policy::restrictProcess(const drizzled::identifier::User &user_ctx,
86 const drizzled::identifier::User &session_ctx)
87{
88
89 LDAPMessage *response;
90 const char *attrs[]= {"uidNumber",
91 "gidNumber",
92 NULL
93 };
94 string filter= "(cn=" + user_ctx.username() + ")";
95
96
97 int return_code= ldap_search_ext_s(ldap,
98 users_dir.c_str(),
99 LDAP_SCOPE_ONELEVEL,
100 filter.c_str(),
101 const_cast<char**>(attrs),
102 0,
103 NULL,
104 NULL,
105 NULL,
106 1,
107 &response);
108
109 if( return_code != LDAP_SUCCESS )
110 {
111 error= "ldap_search_ext_s failed:";
112 error+= ldap_err2string(return_code);
113 printerror();
114
115 ldap_msgfree(response);
116 return true;
117 }
118
119 LDAPMessage *entry;
120 int ldap_entries= ldap_count_entries(ldap, response);
121
122 if( ldap_entries == 0 || ldap_entries == (-1))
123 {
124 ldap_msgfree(response);
125 return true;
126 }
127
128 entry= ldap_first_entry(ldap, response);
129 BerElement *berv;
130 char **gid, **uid, *attr;
131 for(attr= ldap_first_attribute(ldap, entry, &berv); //attr is gidNumber attribute
132 attr != NULL;
133 attr= ldap_next_attribute(ldap, entry, berv))
134 {
135
136 if(not strcmp(attr, "uidNumber"))
137 {
138 uid= ldap_get_values(ldap, entry, attr);
139 }
140 else if( not strcmp(attr, "gidNumber"))
141 {
142 gid= ldap_get_values(ldap, entry, attr);
143 }
144 } //we have uid and gid of user A
145
146 if(gid == NULL)
147 {
148 return true;
149 }
150
151 struct berval brv;
152 brv.bv_len= strlen(gid[0]);
153 brv.bv_val= gid[0];
154
155 string dn= "cn=" + session_ctx.username() + "," + users_dir.c_str();
156
157 return_code= ldap_compare_ext_s(ldap,
158 dn.c_str(),
159 "gidNumber",
160 &brv,
161 NULL,
162 NULL);
163
164 if(return_code == LDAP_COMPARE_TRUE)
165 {
166 if(berv != NULL)
167 {
168 ber_free(berv, 0);
169 }
170 ldap_memfree(attr);
171 ldap_msgfree(response);
172 ldap_value_free(gid);
173 ldap_value_free(uid);
174
175 return false;
176 }
177 else if (return_code != LDAP_COMPARE_FALSE)
178 {
179
180 error= "ldap_compare_ext_s failed";
181 error+= ldap_err2string(return_code);
182 printerror();
183
184 if(berv != NULL)
185 {
186 ber_free(berv, 0);
187 }
188 ldap_memfree(attr);
189 ldap_msgfree(response);
190 ldap_value_free(gid);
191 ldap_value_free(uid);
192 return true;
193 }
194
195 //If they are not in the same group, search for the supplementaries
196 ldap_msgfree(response);
197 ldap_memfree(attr);
198
199 if(berv != NULL)
200 {
201 ber_free(berv, 0);
202 }
203
204 filter= "(cn=" + session_ctx.username() + ")";
205
206 const char *attrs2[]= {"gidNumber", NULL};
207
208 return_code= ldap_search_ext_s( ldap,
209 users_dir.c_str(),
210 LDAP_SCOPE_ONELEVEL,
211 filter.c_str(),
212 const_cast<char**>(attrs2),
213 0,
214 NULL,
215 NULL,
216 NULL,
217 1,
218 &response);
219
220
221 if(return_code != LDAP_SUCCESS)
222 {
223 error= "ldap_search_ext_s failed:";
224 error+= ldap_err2string(return_code);
225 printerror();
226 ldap_msgfree(response);
227 ldap_value_free(gid);
228 ldap_value_free(uid);
229 return true;
230 }
231
232 LDAPMessage *entry2= ldap_first_entry(ldap, response);
233 ldap_entries= ldap_count_entries(ldap, entry2);
234
235 if(ldap_entries == 0 || ldap_entries == -1)
236 {
237 ldap_msgfree(response);
238 ldap_value_free(gid);
239 ldap_value_free(uid);
240 return true;
241 }
242
243 attr= ldap_first_attribute(ldap, entry2, &berv); //attr is gidNumber
244 char **gidNumber= ldap_get_values(ldap, entry2, attr); //we got the gidNumber of user B
245
246 if(gidNumber==NULL)
247 {
248 if(berv != NULL)
249 {
250 ber_free(berv, 0);
251 }
252
253 ldap_memfree(attr);
254 ldap_msgfree(response);
255 ldap_value_free(gid);
256 ldap_value_free(uid);
257 return true;
258 }
259
260 filter= "gidNumber=";
261 filter+= gidNumber[0];
262
263 // searching for the user B group attrs
264 return_code= ldap_search_ext_s(ldap,
265 groups_dir.c_str(),
266 LDAP_SCOPE_ONELEVEL,
267 filter.c_str(),
268 NULL, /* all attributes are requested */
269 0,
270 NULL,
271 NULL,
272 NULL,
273 1,
274 &response);
275
276 if(return_code != LDAP_SUCCESS)
277 {
278 error= "ldap_search_ext_s failed:";
279 error+= ldap_err2string(return_code);
280 printerror();
281
282 ldap_msgfree(response);
283 ldap_value_free(gid);
284 ldap_value_free(uid);
285
286 return true;
287 }
288
289 LDAPMessage *grp_entry= ldap_first_entry(ldap, response);
290 ldap_entries= ldap_count_entries(ldap, grp_entry);
291
292 if(ldap_entries == 0 || ldap_entries == -1)
293 {
294
295 if(berv != NULL)
296 {
297 ber_free(berv, 0);
298 }
299
300 ldap_memfree(attr);
301 ldap_msgfree(response);
302 ldap_value_free(gidNumber);
303 ldap_value_free(gid);
304 ldap_value_free(uid);
305 return true;
306 }
307
308 char *group_dn= ldap_get_dn(ldap, grp_entry);
309
310 if(group_dn == NULL)
311 {
312
313 if(berv != NULL)
314 {
315 ber_free(berv, 0);
316 }
317
318 ldap_memfree(attr);
319 ldap_value_free(gidNumber);
320 ldap_value_free(gid);
321 ldap_value_free(uid);
322
323 return true;
324 }
325
326 if(uid == NULL)
327 {
328 return true;
329 }
330 struct berval ber_uid;
331 ber_uid.bv_len= strlen(uid[0]);
332 ber_uid.bv_val= uid[0];
333
334 return_code= ldap_compare_ext_s(ldap,
335 group_dn,
336 "memberUID",
337 &ber_uid,
338 NULL,
339 NULL);
340 bool retval= true;
341
342 if(return_code == LDAP_COMPARE_TRUE)
343 {
344 retval= false;
345 }
346 else if(return_code != LDAP_COMPARE_FALSE)
347 {
348 error= "ldap_compare_ext_s failed:";
349 error+= ldap_err2string(return_code);
350 printerror();
351 }
352
353 ldap_memfree(group_dn);
354 if(berv != NULL)
355 {
356 ber_free(berv, 0);
357 }
358 ldap_memfree(attr);
359 ldap_value_free(gidNumber);
360 ldap_value_free(gid);
361 ldap_value_free(uid);
362
363 return retval;
364}
365
366
367/**
368 * check_if_allowed returns TRUE if user is NOT authorized in target table. Otherwise, it returns FALSE.
369 * check_if_allowed function, checks if uidNumber attribute of user's LDAP record matches with
370 * allowedUsers attribute of tables's LDAP record or gidNumber matches with allowedGroups.
371 * If neither of them matches, check_if_allowed search for the supplementaries groups of user
372 * and returns true if none of them is allowed. Otherwise it returns false.
373 */
374
375bool LDAP_policy::check_if_allowed(LDAPMessage *u_rep, const drizzled::identifier::User &user, const drizzled::identifier::Table &table)
376{
377 LDAPMessage *entry= ldap_first_entry(ldap, u_rep);
378 int rc;
379 string table_dn= "cn=" + table.getTableName() + "," + tables_dir;
380 char *uattr, **gid= NULL, **uid= NULL;
381 BerElement *uber_val;
382 int ldap_entries= ldap_count_entries(ldap, entry);
383
384 if(ldap_entries == 0 || ldap_entries == -1)
385 {
386 return true;
387 }
388
389 for(uattr= ldap_first_attribute(ldap, entry, &uber_val);
390 uattr != NULL;
391 uattr=ldap_next_attribute(ldap, entry, uber_val))
392 {
393 if( not strcmp(uattr, "gidNumber"))
394 {
395 gid= ldap_get_values(ldap, entry, uattr);
396
397 struct berval bval;
398 bval.bv_val= gid[0];
399 bval.bv_len= strlen(gid[0]);
400
401 rc= ldap_compare_ext_s( ldap,
402 table_dn.c_str(),
403 "allowedGroups",
404 &bval,
405 NULL,
406 NULL);
407
408 if(rc == LDAP_COMPARE_TRUE)
409 {
410 if(uber_val != NULL)
411 {
412 ber_free(uber_val, 0);
413 }
414
415 ldap_memfree(uattr);
416
417 if(uid!=NULL)
418 ldap_value_free(uid);
419
420 ldap_value_free(gid);
421
422 user_cache.insert(user, table, true);
423
424 return false;
425 }
426 else if(rc != LDAP_COMPARE_FALSE)
427 {
428 error= "ldap_compare_ext_s failed: ";
429 error+= ldap_err2string(rc);
430 printerror();
431
432 if(uber_val != NULL)
433 {
434 ber_free(uber_val, 0);
435 }
436
437 ldap_memfree(uattr);
438
439 if(uid!=NULL)
440 ldap_value_free(uid);
441
442 ldap_value_free(gid);
443
444 return true;
445 }
446
447 }
448 else if( not strcmp(uattr, "uidNumber"))
449 {
450 uid= ldap_get_values(ldap, entry, uattr);
451
452 struct berval bval;
453 bval.bv_val= uid[0];
454 bval.bv_len= strlen(uid[0]);
455
456 rc= ldap_compare_ext_s( ldap,
457 table_dn.c_str(),
458 "allowedUsers",
459 &bval,
460 NULL,
461 NULL);
462
463 if( rc == LDAP_COMPARE_TRUE )
464 {
465
466 if(uber_val != NULL)
467 {
468 ber_free(uber_val, 0);
469 }
470 ldap_memfree(uattr);
471
472 if(gid!=NULL)
473 ldap_value_free(gid);
474
475 ldap_value_free(uid);
476
477 user_cache.insert(user, table, true);
478
479 return false;
480 }
481 else if(rc != LDAP_COMPARE_FALSE)
482 {
483 error= "ldap_compare_ext_s failed: ";
484 error+= ldap_err2string(rc);
485 printerror();
486
487 if(uber_val != NULL)
488 {
489 ber_free(uber_val, 0);
490 }
491
492 ldap_memfree(uattr);
493
494 if(gid!=NULL)
495 ldap_value_free(gid);
496
497 ldap_value_free(uid);
498
499 return true;
500 }
501 }
502 }
503
504 if(uber_val != NULL)
505 {
506 ber_free(uber_val, 0);
507 }
508
509 ldap_memfree(uattr);
510
511 const char *group_attrs[]= { "gidNumber",
512 NULL
513 };
514
515 LDAPMessage *group_response;
516
517 string filter= "(memberUID=";
518 filter+= uid[0];
519 filter+= ")";
520
521 rc= ldap_search_ext_s(ldap,
522 groups_dir.c_str(),
523 LDAP_SCOPE_ONELEVEL,
524 filter.c_str(),
525 const_cast<char**>(group_attrs),
526 0,
527 NULL,
528 NULL,
529 NULL,
530 LDAP_NO_LIMIT,
531 &group_response);
532
533 if( rc != LDAP_SUCCESS)
534 {
535 error= "ldap_search_ext_s: ";
536 error+= ldap_err2string(rc);
537 printerror();
538 ldap_value_free(uid);
539 ldap_value_free(gid);
540
541 return true;
542 }
543
544 LDAPMessage *gentry= ldap_first_entry(ldap, group_response);
545 ldap_entries= ldap_count_entries(ldap, gentry);
546
547 if(ldap_entries == 0 || ldap_entries == -1)
548 {
549 ldap_value_free(gid);
550 ldap_value_free(uid);
551 ldap_msgfree(gentry);
552 ldap_msgfree(group_response);
553
554 return true;
555 }
556
557 BerElement *gber;
558 char *gattr= ldap_first_attribute(ldap, gentry, &gber); // it has only one attribute, gidNumber
559
560 if(gattr == NULL)
561 {
562 ldap_value_free(gid);
563 ldap_value_free(uid);
564 if(gber != NULL)
565 {
566 ber_free(gber, 0);
567 }
568 ldap_msgfree(group_response);
569 ldap_msgfree(gentry);
570 return true;
571 }
572
573 char **groups= ldap_get_values(ldap, gentry, gattr); // we have the gidNumber attribute of users' supplementaries groups
574
575 if(groups == NULL)
576 {
577 ldap_value_free(gid);
578 ldap_value_free(uid);
579 if( gber != NULL )
580 {
581 ber_free(gber, 0);
582 }
583 ldap_msgfree(group_response);
584 ldap_msgfree(gentry);
585 return true;
586 }
587
588 int num_of_val= ldap_count_values(groups) - 1;
589
590 while( num_of_val >= 0)
591 {
592 struct berval bval;
593 bval.bv_len= strlen(groups[num_of_val]);
594 bval.bv_val= groups[num_of_val];
595
596 rc= ldap_compare_ext_s( ldap,
597 table_dn.c_str(),
598 "allowedGroups",
599 &bval,
600 NULL,
601 NULL);
602
603 if( rc == LDAP_COMPARE_TRUE )
604 {
605
606 if(gber != NULL)
607 {
608 ber_free(gber, 0);
609 }
610 ldap_memfree(gattr);
611 ldap_value_free(groups);
612 ldap_value_free(gid);
613 ldap_value_free(uid);
614 ldap_msgfree(gentry);
615
616 user_cache.insert(user, table, true);
617
618 return false;
619 }
620 else if( rc != LDAP_COMPARE_FALSE )
621 {
622 error= "ldap_compare_ext_s failed: ";
623 error+= ldap_err2string(rc);
624 printerror();
625
626 if(gber != NULL)
627 {
628 ber_free(gber, 0);
629 }
630
631 ldap_memfree(gattr);
632 ldap_value_free(groups);
633 ldap_value_free(gid);
634 ldap_value_free(uid);
635 ldap_msgfree(gentry);
636
637 return true;
638 }
639
640 num_of_val--;
641 }
642
643 if(gber != NULL)
644 {
645 ber_free(gber, 0);
646 }
647
648 ldap_memfree(gattr);
649 ldap_value_free(groups);
650 ldap_value_free(gid);
651 ldap_value_free(uid);
652 ldap_msgfree(gentry);
653 ldap_msgfree(group_response);
654
655 user_cache.insert(user, table, false);
656
657 return true;
658}
659
660
661/**
662 * check_if_allowed returns TRUE if user is NOT authorized in target schema. Otherwise, it returns FALSE.
663 * check_if_allowed function, checks if uidNumber attribute of user's LDAP record matches with
664 * allowedUsers attribute of schema's LDAP record or gidNumber matches with allowedGroups.
665 * If neither of them matches, check_if_allowed search for the supplementaries groups of user
666 * and returns true if none of them is allowed. Otherwise it returns false.
667 */
668
669bool LDAP_policy::check_if_allowed(LDAPMessage *u_rep, const drizzled::identifier::User &user, const drizzled::identifier::Schema& schema)
670{
671 LDAPMessage *entry= ldap_first_entry(ldap, u_rep);
672 int ldap_entries= ldap_count_entries(ldap, entry);
673 if(ldap_entries == 0 || ldap_entries == -1)
674 {
675 return true;
676 }
677
678 int rc;
679 string user_id;
680 char *uattr, **gid= NULL, **uid= NULL;
681 uid= NULL;
682 BerElement *uber_val;
683 string schema_dn= "cn=" + schema.getSchemaName() + "," + schemas_dir;
684
685 for(uattr= ldap_first_attribute(ldap, entry, &uber_val);
686 uattr!=NULL;
687 uattr=ldap_next_attribute(ldap, entry, uber_val))
688 {
689
690 if(not strcmp(uattr, "gidNumber"))
691 {
692 gid= ldap_get_values(ldap, entry, uattr);
693
694 struct berval bval;
695 bval.bv_val= gid[0];
696 bval.bv_len= strlen(gid[0]);
697
698 rc= ldap_compare_ext_s( ldap,
699 schema_dn.c_str(),
700 "allowedGroups",
701 &bval,
702 NULL,
703 NULL);
704
705 if( rc == LDAP_COMPARE_TRUE)
706 {
707 if(uber_val != NULL)
708 {
709 ber_free(uber_val, 0);
710 }
711 ldap_memfree(uattr);
712 ldap_value_free(gid);
713
714 if(uid != NULL)
715 ldap_value_free(uid);
716
717 user_cache.insert(user, schema, true);
718
719 return false;
720 }
721 else if(rc != LDAP_COMPARE_FALSE)
722 {
723 //Maybe when return code is "No such object" I could add in cache.
724
725 error= "ldap_compare_ext_s failed: ";
726 error+= ldap_err2string(rc);
727 printerror();
728
729 if(uber_val != NULL)
730 {
731 ber_free(uber_val, 0);
732 }
733
734 ldap_memfree(uattr);
735 ldap_value_free(gid);
736
737 if( uid != NULL)
738 ldap_value_free(uid);
739
740 return true;
741 }
742 }
743 else if (not strcmp(uattr, "uidNumber"))
744 {
745 uid= ldap_get_values(ldap, entry, uattr);
746
747 struct berval bval;
748 bval.bv_val= uid[0];
749 bval.bv_len= strlen(uid[0]);
750
751 rc= ldap_compare_ext_s( ldap,
752 schema_dn.c_str(),
753 "allowedUsers",
754 &bval,
755 NULL,
756 NULL);
757
758 if( rc == LDAP_COMPARE_TRUE)
759 {
760
761 if(uber_val != NULL)
762 {
763 ber_free(uber_val, 0);
764 }
765
766 if(gid != NULL)
767 ldap_value_free(gid);
768
769 ldap_memfree(uattr);
770 ldap_value_free(uid);
771
772 user_cache.insert(user, schema, true);
773
774 return false;
775 }
776 else if (rc != LDAP_COMPARE_FALSE)
777 {
778
779 error= "ldap_compare_ext_s failed: ";
780 error+= ldap_err2string(rc);
781 printerror();
782 if(uber_val != NULL)
783 {
784 ber_free(uber_val, 0);
785 }
786 ldap_memfree(uattr);
787
788 if(uid != NULL)
789 ldap_value_free(uid);
790
791 ldap_value_free(gid);
792
793 return true;
794 }
795 }
796 }
797
798 ldap_memfree(uattr);
799
800 if(uber_val != NULL)
801 {
802 ber_free(uber_val, 0);
803 }
804
805 if(uid==NULL)
806 {
807 return true;
808 }
809 const char *gattrs[]= {"gidNumber",
810 NULL
811 };
812
813 LDAPMessage *group_response;
814
815 string filter= "(memberUID=";
816 filter+= uid[0];
817 filter+= ")";
818
819 rc= ldap_search_ext_s(ldap,
820 groups_dir.c_str(),
821 LDAP_SCOPE_ONELEVEL,
822 filter.c_str(),
823 const_cast<char**>(gattrs),
824 0,
825 NULL,
826 NULL,
827 NULL,
828 LDAP_NO_LIMIT,
829 &group_response);
830
831 if(rc != LDAP_SUCCESS)
832 {
833 error= "ldap_search_ext_s: ";
834 error+= ldap_err2string(rc);
835 printerror();
836 return true;
837 }
838
839 LDAPMessage *gentry= ldap_first_entry(ldap, group_response);
840 BerElement *gber;
841
842 char *gattr= ldap_first_attribute(ldap, gentry, &gber);
843 char **groups= ldap_get_values(ldap, gentry, gattr); // exoyme ta groups sta opoia anoikei o user
844
845 for(int num_of_values= ldap_count_values(groups) - 1; num_of_values >= 0; num_of_values--)
846 {
847 struct berval bval;
848 bval.bv_len= strlen(groups[num_of_values]);
849 bval.bv_val= groups[num_of_values];
850
851 if( ldap_compare_ext_s( ldap,
852 schema_dn.c_str(),
853 "allowedGroups",
854 &bval,
855 NULL,
856 NULL) == LDAP_COMPARE_TRUE)
857 {
858
859 if(gber != NULL)
860 {
861 ber_free(gber, 0);
862 }
863 ldap_memfree(gattr);
864 ldap_value_free(groups);
865
866 user_cache.insert(user, schema, true);
867
868 return false;
869 }
870 }
871
872 if(gber != NULL)
873 {
874 ber_free(gber, 0);
875 }
876 ldap_memfree(gattr);
877 ldap_value_free(groups);
878 ldap_msgfree(group_response);
879
880 user_cache.insert(user, schema, false);
881
882 return true;
883}
884
885bool LDAP_policy::restrictTable(const drizzled::identifier::User &user_ctx,
886 const drizzled::identifier::Table& table)
887{
888
889 if( table.getSchemaName() == "information_schema" || table.getSchemaName() == "INFORMATION_SCHEMA")
890 {
891 return false;
892 }
893
894 LDAPMessage *user_response;
895
896 const char *uattrs[]= { "uidNumber",
897 "gidNumber",
898 NULL
899 };
900
901 string filter= "(&(cn=" + user_ctx.username() + ")(BelongInSchema=" + table.getSchemaName() + "))";
902 /* Schema attribute allows to determine from which schema, is the table we are looking for.
903 Still I need to implement the BelongInSchema schema */
904
905 CacheResponse cache_res= user_cache.is_authorized(user_ctx, table);
906
907 if(cache_res == ALLOWED)
908 {
909 return false;
910 }
911 else if(cache_res == DENIED)
912 {
913 return true;
914 }
915
916 int return_code= ldap_search_ext_s( ldap,
917 users_dir.c_str(),
918 LDAP_SCOPE_ONELEVEL,
919 filter.c_str(),
920 const_cast<char**>(uattrs),
921 0,
922 NULL,
923 NULL,
924 NULL,
925 1,
926 &user_response);
927
928 if(return_code != LDAP_SUCCESS)
929 {
930 error= "ldap_search_ext_s failed:";
931 error+= ldap_err2string(return_code);
932 printerror();
933
934 return true;
935 }
936
937 bool restr= check_if_allowed(user_response, user_ctx, table);
938
939 ldap_msgfree(user_response);
940
941 return restr;
942}
943
944bool LDAP_policy::restrictSchema(const drizzled::identifier::User &user_ctx,
945 const drizzled::identifier::Schema& schema)
946{
947
948 if(schema.getSchemaName() == "information_schema" || schema.getSchemaName() == "INFORMATION_SCHEMA")
949 {
950 return false;
951 }
952
953 CacheResponse cache_res= user_cache.is_authorized(user_ctx, schema);
954
955 if(cache_res == ALLOWED)
956 {
957 return false;
958 }
959 else if (cache_res == DENIED)
960 {
961 return true;
962 }
963
964 LDAPMessage *user_response;
965 const char *uattrs[]= { "uidNumber",
966 "gidNumber",
967 NULL
968 };
969 string filter = "(cn=" + user_ctx.username() + ")";
970
971 int return_code= ldap_search_ext_s(ldap,
972 users_dir.c_str(),
973 LDAP_SCOPE_ONELEVEL,
974 filter.c_str(),
975 const_cast<char**>(uattrs),
976 0,
977 NULL,
978 NULL,
979 NULL,
980 1,
981 &user_response); //search for gidNumber and uidNumber in users' directory
982
983 if(return_code != LDAP_SUCCESS) {
984 error= "ldap_search_ext_s failed:";
985 error+= ldap_err2string(return_code);
986 printerror();
987 return true;
988 }
989
990 bool restr= check_if_allowed(user_response, user_ctx, schema);
991 ldap_msgfree(user_response);
992
993 return restr;
994}
995
996bool LDAP_policy::connect(void)
997{
998 int return_code= ldap_initialize(&ldap, (char *)uri.c_str());
999
1000 if (return_code != LDAP_SUCCESS)
1001 {
1002 error= "ldap_initialize failed: ";
1003 error+= ldap_err2string(return_code);
1004 printerror();
1005 return false;
1006 }
1007
1008 int version= 3;
1009 return_code= ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
1010
1011 if (return_code != LDAP_SUCCESS)
1012 {
1013 ldap_unbind_ext_s(ldap, NULL, NULL);
1014 ldap= NULL;
1015 error= "ldap_set_option failed: ";
1016 error+= ldap_err2string(return_code);
1017 printerror();
1018 return false;
1019 }
1020
1021 return_code= ldap_simple_bind_s(ldap, NULL, NULL);
1022
1023 if (return_code != LDAP_SUCCESS)
1024 {
1025 ldap_unbind(ldap);
1026 ldap= NULL;
1027 error= "ldap_simple_bind_s failed: ";
1028 error+= ldap_err2string(return_code);
1029 printerror();
1030
1031 return false;
1032 }
1033
1034 return true;
1035
1036}
1037
1038inline bool CacheItem::is_valid() const
1039{
1040 time_t temp_timer;
1041 temp_timer = time(NULL);
1042
1043 if(temp_timer - timer > cache_timeout)
1044 {
1045 return false;
1046 }
1047 else
1048 {
1049 return true;
1050 }
1051}
1052
1053void UserCache::insert(const drizzled::identifier::User &user, const drizzled::identifier::Table &table, bool auth)
1054{
1055 string user_name= user.username();
1056
1057 if(table_cache.count(user_name) != 1) // user not found, need to insert a new one
1058 {
1059 CacheItem new_cache_item(user_name, table.getTableName(), table.getSchemaName(), auth);
1060 table_cache.insert(CacheMap::value_type(user_name, ItemDeque()));
1061 table_cache[user_name].push_back(new_cache_item);
1062 }
1063 else //user found
1064 {
1065 CacheItem new_cache_item(user_name, table.getTableName(), table.getSchemaName(), auth);
1066 table_cache[user_name].push_back(new_cache_item);
1067 }
1068}
1069
1070void UserCache::insert(const drizzled::identifier::User &user, const drizzled::identifier::Schema &schema, bool auth)
1071{
1072 string user_name= user.username();
1073
1074 if(schema_cache.count(user.username()) != 1)
1075 {
1076 CacheItem new_cache_item(user_name, "", schema.getSchemaName(), auth);
1077 schema_cache.insert(CacheMap::value_type(user_name, ItemDeque()));
1078 schema_cache[user_name].push_back(new_cache_item);
1079 }
1080 else
1081 {
1082 CacheItem new_cache_item(user_name, "", schema.getSchemaName(), auth);
1083 schema_cache[user_name].push_back(new_cache_item);
1084 }
1085}
1086
1087int UserCache::remove(const drizzled::identifier::User &user, const drizzled::identifier::Table &table)
1088{
1089 CacheMap_Iterator map_iterator;
1090 map_iterator= table_cache.find(user.username());
1091
1092 if(map_iterator == table_cache.end() )
1093 {
1094 return -1;
1095 }
1096
1097 ItemDeque::iterator deque_iter;
1098
1099 string user_name= user.username();
1100 string table_name= table.getTableName();
1101 string schema_name= table.getSchemaName();
1102
1103 for( deque_iter= table_cache[user_name].begin();
1104 deque_iter != table_cache[user_name].end();
1105 deque_iter++)
1106 {
1107 if( (deque_iter->getTable() == table_name)
1108 && (deque_iter->getSchema() == schema_name) )
1109 {
1110 break;
1111 }
1112 }
1113
1114 if(deque_iter != table_cache[user_name].end())
1115 {
1116 table_cache[user_name].erase(deque_iter);
1117
1118 return 0;
1119 }
1120 return -1;
1121}
1122
1123int UserCache::remove(const drizzled::identifier::User &user, const drizzled::identifier::Schema &schema)
1124{
1125 CacheMap_Iterator map_iterator;
1126 map_iterator= schema_cache.find(user.username());
1127
1128 if( map_iterator == schema_cache.end())
1129 {
1130 return -1;
1131 }
1132
1133 ItemDeque::iterator deque_iter;
1134
1135 string user_name= user.username();
1136 string schema_name= schema.getSchemaName();
1137
1138 for( deque_iter= schema_cache[user_name].begin();
1139 deque_iter != schema_cache[user_name].end();
1140 deque_iter++)
1141 {
1142 if( deque_iter->getSchema() == schema_name)
1143 {
1144 break;
1145 }
1146 }
1147
1148 if( deque_iter != schema_cache[user_name].end())
1149 {
1150 schema_cache[user_name].erase(deque_iter);
1151
1152 return 0;
1153 }
1154 return -1;
1155}
1156
1157CacheResponse UserCache::is_authorized(const drizzled::identifier::User &user, const drizzled::identifier::Schema &schema)
1158{
1159 if(schema_cache.size() == 0)
1160 return NOT_FOUND;
1161
1162 CacheMap_Iterator map_iterator;
1163 map_iterator= schema_cache.find(user.username());
1164
1165 if(map_iterator != schema_cache.end())
1166 {
1167 ItemDeque::iterator deque_iter;
1168
1169 string user_name= user.username();
1170 string schema_name= schema.getSchemaName();
1171
1172 for(deque_iter= schema_cache[user_name].begin();
1173 deque_iter != schema_cache[user_name].end();
1174 deque_iter++)
1175 {
1176 if(deque_iter->getSchema() == schema_name)
1177 {
1178 break;
1179 }
1180 }
1181
1182
1183 if(deque_iter != schema_cache[user_name].end())
1184 {
1185 if(deque_iter->is_valid())
1186 {
1187 if(deque_iter->is_authorized())
1188 {
1189 return ALLOWED;
1190 }
1191 else
1192 {
1193 return DENIED;
1194 }
1195 }
1196 else
1197 {
1198 remove(user, schema);
1199 return NOT_FOUND;
1200 }
1201 }
1202 else //not found
1203 {
1204 return NOT_FOUND;
1205 }
1206 }
1207 else
1208 {
1209 return NOT_FOUND;
1210 }
1211}
1212
1213CacheResponse UserCache::is_authorized(const drizzled::identifier::User &user, const drizzled::identifier::Table &table)
1214{
1215 if(table_cache.size() == 0)
1216 return NOT_FOUND;
1217
1218 CacheMap_Iterator map_iterator;
1219 map_iterator= table_cache.find(user.username());
1220
1221 if(map_iterator != table_cache.end())
1222 {
1223 ItemDeque::iterator deque_iter;
1224
1225 string user_name= user.username();
1226 string table_name= table.getTableName();
1227 string schema_name= table.getSchemaName();
1228
1229 for(deque_iter= table_cache[user_name].begin();
1230 deque_iter != table_cache[user_name].end();
1231 deque_iter++)
1232 {
1233 if(deque_iter->getTable() == table_name
1234 && deque_iter->getSchema() == schema_name)
1235 {
1236 break;
1237 }
1238 }
1239
1240
1241 if(deque_iter != table_cache[user_name].end())
1242 {
1243 if(deque_iter->is_valid())
1244 {
1245 if(deque_iter->is_authorized())
1246 {
1247 return ALLOWED;
1248 }
1249 else
1250 {
1251 return DENIED;
1252 }
1253 }
1254 else //cache item has expired, so we should remove it
1255 {
1256 remove(user, table);
1257 return NOT_FOUND;
1258 }
1259 }
1260 else // table/schema for the user does not exist in cache
1261 {
1262 return NOT_FOUND;
1263 }
1264 }
1265 else //user does not exist in cache
1266 {
1267 return NOT_FOUND;
1268 }
1269}
1270
1271} /* namespace ldap_policy */
1272
1273DRIZZLE_DECLARE_PLUGIN
1274{
1275 DRIZZLE_VERSION_ID,
1276 "ldap_policy",
1277 "0.1",
1278 "Sialveras Zisis",
1279 N_("LDAP based authorization system"),
1280 PLUGIN_LICENSE_GPL,
1281 ldap_policy::init,
1282 NULL,
1283 ldap_policy::init_options
1284}
1285DRIZZLE_DECLARE_PLUGIN_END;
1286
01287
=== added file 'plugin/ldap_policy/ldap_policy.hpp'
--- plugin/ldap_policy/ldap_policy.hpp 1970-01-01 00:00:00 +0000
+++ plugin/ldap_policy/ldap_policy.hpp 2012-08-21 14:09:20 +0000
@@ -0,0 +1,194 @@
1/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3 *
4 * Copyright (C) 2012 Zisis Sialveras
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20
21#pragma once
22
23#include <config.h>
24
25
26#include <boost/unordered_map.hpp>
27
28#include <drizzled/plugin/authorization.h>
29#include <drizzled/plugin.h>
30
31#include <deque>
32#include <string>
33#include <ctime>
34
35#define LDAP_DEPRECATED 1
36#include <ldap.h>
37
38namespace ldap_policy
39{
40
41std::string DEFAULT_URI= "ldap://localhost/";
42std::string DEFAULT_USERS_DIR= "ou=users,dc=example,dc=com";
43std::string DEFAULT_SCHEMAS_DIR= "ou=schemas,dc=example,dc=com";
44std::string DEFAULT_TABLES_DIR= "ou=tables,dc=example,dc=com";
45std::string DEFAULT_GROUPS_DIR= "ou=groups,dc=example,dc=com";
46time_t DEFAULT_CACHE_TIMEOUT= 500;
47
48time_t cache_timeout;
49std::string uri;
50std::string groups_dir;
51std::string base_dn;
52std::string bind_passwd;
53std::string users_dir;
54std::string schemas_dir;
55std::string tables_dir;
56
57
58class CacheItem
59{
60 std::string user, table, schema;
61 bool authorized;
62 time_t timer;
63
64 public:
65
66 CacheItem(std::string u, std::string t, std::string s, bool a): user(u), table(t), schema(s), authorized(a)
67 {
68 timer = time(NULL);
69 };
70
71 /*
72 CacheItem()
73 {
74 gettimeofday(&tv, NULL);
75 };
76 */
77
78 ~CacheItem(){};
79
80 inline bool is_valid() const;
81
82 inline bool is_authorized()
83 {
84 return authorized;
85 };
86
87 void setTable(std::string t)
88 {
89 table = t;
90 };
91
92 void setSchema(std::string s)
93 {
94 schema = s;
95 };
96
97 inline std::string getTable()
98 {
99 return table;
100 };
101
102 inline std::string getSchema()
103 {
104 return schema;
105 };
106
107};
108
109typedef std::deque<CacheItem> ItemDeque;
110typedef boost::unordered_map<std::string, ItemDeque> CacheMap;
111typedef boost::unordered_map<std::string, ItemDeque>::const_iterator CacheMap_Iterator;
112
113typedef enum
114{
115 ALLOWED,
116 DENIED,
117 NOT_FOUND
118} CacheResponse;
119
120class UserCache
121{
122 CacheMap table_cache, schema_cache;
123
124 public:
125
126 UserCache() {};
127
128 ~UserCache() {};
129
130 /**
131 * Insert a schema/table in cache for a specific user.
132 *
133 * If the last parametr is true then the user is allowed to access the schema/table.
134 * Otherwise, if it is false, access is denied.
135 */
136 void insert(const drizzled::identifier::User &, const drizzled::identifier::Table &, bool );
137 void insert(const drizzled::identifier::User &, const drizzled::identifier::Schema &, bool );
138
139 /**
140 * Removes a schema/table from cache for a specific user.
141 */
142 int remove(const drizzled::identifier::User &, const drizzled::identifier::Table &);
143 int remove(const drizzled::identifier::User &, const drizzled::identifier::Schema &);
144
145 /**
146 * Returns if a user is authorized to access target schema/table.
147 */
148 CacheResponse is_authorized(const drizzled::identifier::User &, const drizzled::identifier::Table &);
149 CacheResponse is_authorized(const drizzled::identifier::User &, const drizzled::identifier::Schema &);
150
151} user_cache;
152
153class LDAP_policy :
154 public drizzled::plugin::Authorization
155{
156
157 std::string error;
158 LDAP *ldap;
159
160 void printerror();
161
162 bool check_if_allowed(LDAPMessage *, const drizzled::identifier::User &, const drizzled::identifier::Schema& );
163 bool check_if_allowed(LDAPMessage *, const drizzled::identifier::User &, const drizzled::identifier::Table & );
164
165 public:
166 LDAP_policy():
167 drizzled::plugin::Authorization("ldap_policy")
168 {
169
170 }
171
172 ~LDAP_policy()
173 {
174 if(ldap != NULL)
175 ldap_unbind(ldap);
176 }
177
178 bool connect(void);
179
180 virtual bool restrictSchema(const drizzled::identifier::User &user_ctx,
181 const drizzled::identifier::Schema& schema);
182
183 virtual bool restrictProcess(const drizzled::identifier::User &user_ctx,
184 const drizzled::identifier::User &session_ctx);
185
186 virtual bool restrictTable(const drizzled::identifier::User& user_ctx,
187 const drizzled::identifier::Table& table);
188
189
190};
191
192} /* namespace ldap_policy */
193
194
0195
=== added file 'plugin/ldap_policy/plugin.ini'
--- plugin/ldap_policy/plugin.ini 1970-01-01 00:00:00 +0000
+++ plugin/ldap_policy/plugin.ini 2012-08-21 14:09:20 +0000
@@ -0,0 +1,3 @@
1[plugin]
2build_conditional="x${ac_cv_libldap}" = "xyes"
3ldflags=${LTLIBLDAP}
04
=== modified file 'tests/lib/server_mgmt/drizzled.py'
--- tests/lib/server_mgmt/drizzled.py 2012-06-19 18:46:42 +0000
+++ tests/lib/server_mgmt/drizzled.py 2012-08-21 14:09:20 +0000
@@ -200,8 +200,9 @@
200 # This is what test-run.pl does and it helps us pass logging_stats tests200 # This is what test-run.pl does and it helps us pass logging_stats tests
201 # while not self.ping_server(server, quiet=True) and timer != timeout:201 # while not self.ping_server(server, quiet=True) and timer != timeout:
202202
203 return self.system_manager.find_path( [self.pid_file]203 #return self.system_manager.find_path( [self.pid_file]
204 , required=0)204 # , required=0)
205 return self.ping(quiet=True)
205206
206 def create_slave_config_file(self):207 def create_slave_config_file(self):
207 """ Create a config file suitable for use208 """ Create a config file suitable for use

Subscribers

People subscribed via source and target branches

to all changes: