r23404: Fix wrong (and missing) action on error condition in ldap reply evaluation...
[Samba/bb.git] / source / nsswitch / idmap_ldap.c
blobe5dd658fe386c77299f0a399d31b13a204ff5b0c
1 /*
2 Unix SMB/CIFS implementation.
4 idmap LDAP backend
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8 Copyright (C) Gerald Carter 2003
9 Copyright (C) Simo Sorce 2003-2006
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
27 #include "winbindd.h"
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_IDMAP
32 #include <lber.h>
33 #include <ldap.h>
35 #include "smbldap.h"
37 struct idmap_ldap_context {
38 struct smbldap_state *smbldap_state;
39 char *url;
40 char *suffix;
41 char *user_dn;
42 uint32_t filter_low_id, filter_high_id; /* Filter range */
43 BOOL anon;
46 struct idmap_ldap_alloc_context {
47 struct smbldap_state *smbldap_state;
48 char *url;
49 char *suffix;
50 char *user_dn;
51 uid_t low_uid, high_uid; /* Range of uids */
52 gid_t low_gid, high_gid; /* Range of gids */
56 #define CHECK_ALLOC_DONE(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while (0)
58 /**********************************************************************
59 IDMAP ALLOC TDB BACKEND
60 **********************************************************************/
62 static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
64 /*********************************************************************
65 ********************************************************************/
67 static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
68 struct smbldap_state *ldap_state,
69 const char *config_option,
70 struct idmap_domain *dom,
71 char **dn )
73 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
74 char *user_dn = NULL;
75 char *secret = NULL;
76 const char *tmp = NULL;
78 /* assume anonymous if we don't have a specified user */
80 tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
82 if ( tmp ) {
83 if (!dom) {
84 /* only the alloc backend is allowed to pass in a NULL dom */
85 secret = idmap_fetch_secret("ldap", true, NULL, tmp);
86 } else {
87 secret = idmap_fetch_secret("ldap", false, dom->name, tmp);
90 if (!secret) {
91 DEBUG(0, ("get_credentials: Unable to fetch "
92 "auth credentials for %s in %s\n",
93 tmp, (dom==NULL)?"ALLOC":dom->name));
94 ret = NT_STATUS_ACCESS_DENIED;
95 goto done;
97 *dn = talloc_strdup(mem_ctx, tmp);
98 CHECK_ALLOC_DONE(*dn);
99 } else {
100 if ( !fetch_ldap_pw( &user_dn, &secret ) ) {
101 DEBUG(2, ("get_credentials: Failed to lookup ldap "
102 "bind creds. Using anonymous connection.\n"));
103 *dn = talloc_strdup( mem_ctx, "" );
104 } else {
105 *dn = talloc_strdup(mem_ctx, user_dn);
106 SAFE_FREE( user_dn );
107 CHECK_ALLOC_DONE(*dn);
111 smbldap_set_creds(ldap_state, false, *dn, secret);
112 ret = NT_STATUS_OK;
114 done:
115 SAFE_FREE( secret );
117 return ret;
121 /**********************************************************************
122 Verify the sambaUnixIdPool entry in the directory.
123 **********************************************************************/
125 static NTSTATUS verify_idpool(void)
127 NTSTATUS ret;
128 TALLOC_CTX *ctx;
129 LDAPMessage *result = NULL;
130 LDAPMod **mods = NULL;
131 const char **attr_list;
132 char *filter;
133 int count;
134 int rc;
136 if ( ! idmap_alloc_ldap) {
137 return NT_STATUS_UNSUCCESSFUL;
140 ctx = talloc_new(idmap_alloc_ldap);
141 if ( ! ctx) {
142 DEBUG(0, ("Out of memory!\n"));
143 return NT_STATUS_NO_MEMORY;
146 filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
147 CHECK_ALLOC_DONE(filter);
149 attr_list = get_attr_list(ctx, idpool_attr_list);
150 CHECK_ALLOC_DONE(attr_list);
152 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
153 idmap_alloc_ldap->suffix,
154 LDAP_SCOPE_SUBTREE,
155 filter,
156 attr_list,
158 &result);
160 if (rc != LDAP_SUCCESS) {
161 DEBUG(1, ("Unable to verify the idpool, cannot continue initialization!\n"));
162 return NT_STATUS_UNSUCCESSFUL;
165 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
167 ldap_msgfree(result);
169 if ( count > 1 ) {
170 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
171 filter, idmap_alloc_ldap->suffix));
172 ret = NT_STATUS_UNSUCCESSFUL;
173 goto done;
175 else if (count == 0) {
176 char *uid_str, *gid_str;
178 uid_str = talloc_asprintf(ctx, "%lu", (unsigned long)idmap_alloc_ldap->low_uid);
179 gid_str = talloc_asprintf(ctx, "%lu", (unsigned long)idmap_alloc_ldap->low_gid);
181 smbldap_set_mod(&mods, LDAP_MOD_ADD,
182 "objectClass", LDAP_OBJ_IDPOOL);
183 smbldap_set_mod(&mods, LDAP_MOD_ADD,
184 get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER),
185 uid_str);
186 smbldap_set_mod(&mods, LDAP_MOD_ADD,
187 get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER),
188 gid_str);
189 if (mods) {
190 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
191 idmap_alloc_ldap->suffix,
192 mods);
193 ldap_mods_free(mods, True);
194 } else {
195 ret = NT_STATUS_UNSUCCESSFUL;
196 goto done;
200 ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
201 done:
202 talloc_free(ctx);
203 return ret;
206 /*****************************************************************************
207 Initialise idmap database.
208 *****************************************************************************/
210 static NTSTATUS idmap_ldap_alloc_init(const char *params)
212 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
213 const char *range;
214 const char *tmp;
215 uid_t low_uid = 0;
216 uid_t high_uid = 0;
217 gid_t low_gid = 0;
218 gid_t high_gid = 0;
220 /* Only do init if we are online */
221 if (idmap_is_offline()) {
222 return NT_STATUS_FILE_IS_OFFLINE;
225 idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
226 CHECK_ALLOC_DONE( idmap_alloc_ldap );
228 /* load ranges */
230 idmap_alloc_ldap->low_uid = 0;
231 idmap_alloc_ldap->high_uid = 0;
232 idmap_alloc_ldap->low_gid = 0;
233 idmap_alloc_ldap->high_gid = 0;
235 range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL);
236 if (range && range[0]) {
237 unsigned low_id, high_id;
239 if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) {
240 if (low_id < high_id) {
241 idmap_alloc_ldap->low_gid = idmap_alloc_ldap->low_uid = low_id;
242 idmap_alloc_ldap->high_gid = idmap_alloc_ldap->high_uid = high_id;
243 } else {
244 DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range));
246 } else {
247 DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range));
251 if (lp_idmap_uid(&low_uid, &high_uid)) {
252 idmap_alloc_ldap->low_uid = low_uid;
253 idmap_alloc_ldap->high_uid = high_uid;
256 if (lp_idmap_gid(&low_gid, &high_gid)) {
257 idmap_alloc_ldap->low_gid = low_gid;
258 idmap_alloc_ldap->high_gid= high_gid;
261 if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) {
262 DEBUG(1, ("idmap uid range missing or invalid\n"));
263 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
264 ret = NT_STATUS_UNSUCCESSFUL;
265 goto done;
268 if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) {
269 DEBUG(1, ("idmap gid range missing or invalid\n"));
270 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
271 ret = NT_STATUS_UNSUCCESSFUL;
272 goto done;
275 if (params && *params) {
276 /* assume location is the only parameter */
277 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
278 } else {
279 tmp = lp_parm_const_string(-1, "idmap alloc config", "ldap_url", NULL);
281 if ( ! tmp) {
282 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
283 ret = NT_STATUS_UNSUCCESSFUL;
284 goto done;
287 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
289 CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
291 tmp = lp_ldap_idmap_suffix();
292 if ( ! tmp || ! *tmp) {
293 tmp = lp_parm_const_string(-1, "idmap alloc config", "ldap_base_dn", NULL);
295 if ( ! tmp) {
296 tmp = lp_ldap_suffix();
297 if (tmp) {
298 DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp));
299 DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
301 if ( ! tmp) {
302 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
303 ret = NT_STATUS_UNSUCCESSFUL;
304 goto done;
308 idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
309 CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
311 ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
312 idmap_alloc_ldap->url,
313 &idmap_alloc_ldap->smbldap_state);
314 if (!NT_STATUS_IS_OK(ret)) {
315 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
316 idmap_alloc_ldap->url));
317 goto done;
320 ret = get_credentials( idmap_alloc_ldap,
321 idmap_alloc_ldap->smbldap_state,
322 "idmap alloc config", NULL,
323 &idmap_alloc_ldap->user_dn );
324 if ( !NT_STATUS_IS_OK(ret) ) {
325 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
326 "credentials (%s)\n", nt_errstr(ret)));
327 goto done;
330 /* see if the idmap suffix and sub entries exists */
332 ret = verify_idpool();
334 done:
335 if ( !NT_STATUS_IS_OK( ret ) )
336 TALLOC_FREE( idmap_alloc_ldap );
338 return ret;
341 /********************************
342 Allocate a new uid or gid
343 ********************************/
345 static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
347 TALLOC_CTX *ctx;
348 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
349 int rc = LDAP_SERVER_DOWN;
350 int count = 0;
351 LDAPMessage *result = NULL;
352 LDAPMessage *entry = NULL;
353 LDAPMod **mods = NULL;
354 char *id_str;
355 char *new_id_str;
356 char *filter = NULL;
357 const char *dn = NULL;
358 const char **attr_list;
359 const char *type;
361 /* Only do query if we are online */
362 if (idmap_is_offline()) {
363 return NT_STATUS_FILE_IS_OFFLINE;
366 if ( ! idmap_alloc_ldap) {
367 return NT_STATUS_UNSUCCESSFUL;
370 ctx = talloc_new(idmap_alloc_ldap);
371 if ( ! ctx) {
372 DEBUG(0, ("Out of memory!\n"));
373 return NT_STATUS_NO_MEMORY;
376 /* get type */
377 switch (xid->type) {
379 case ID_TYPE_UID:
380 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
381 break;
383 case ID_TYPE_GID:
384 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
385 break;
387 default:
388 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
389 return NT_STATUS_INVALID_PARAMETER;
392 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
393 CHECK_ALLOC_DONE(filter);
395 attr_list = get_attr_list(ctx, idpool_attr_list);
396 CHECK_ALLOC_DONE(attr_list);
398 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
400 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
401 idmap_alloc_ldap->suffix,
402 LDAP_SCOPE_SUBTREE, filter,
403 attr_list, 0, &result);
405 if (rc != LDAP_SUCCESS) {
406 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
407 goto done;
410 talloc_autofree_ldapmsg(ctx, result);
412 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
413 if (count != 1) {
414 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
415 goto done;
418 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
420 dn = smbldap_talloc_dn(ctx, idmap_alloc_ldap->smbldap_state->ldap_struct, entry);
421 if ( ! dn) {
422 goto done;
425 if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
426 entry, type, ctx))) {
427 DEBUG(0,("%s attribute not found\n", type));
428 goto done;
430 if ( ! id_str) {
431 DEBUG(0,("Out of memory\n"));
432 ret = NT_STATUS_NO_MEMORY;
433 goto done;
436 xid->id = strtoul(id_str, NULL, 10);
438 /* make sure we still have room to grow */
440 switch (xid->type) {
441 case ID_TYPE_UID:
442 if (xid->id > idmap_alloc_ldap->high_uid) {
443 DEBUG(0,("Cannot allocate uid above %lu!\n",
444 (unsigned long)idmap_alloc_ldap->high_uid));
445 goto done;
447 break;
449 case ID_TYPE_GID:
450 if (xid->id > idmap_alloc_ldap->high_gid) {
451 DEBUG(0,("Cannot allocate gid above %lu!\n",
452 (unsigned long)idmap_alloc_ldap->high_uid));
453 goto done;
455 break;
457 default:
458 /* impossible */
459 goto done;
462 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
463 if ( ! new_id_str) {
464 DEBUG(0,("Out of memory\n"));
465 ret = NT_STATUS_NO_MEMORY;
466 goto done;
469 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
470 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
472 if (mods == NULL) {
473 DEBUG(0,("smbldap_set_mod() failed.\n"));
474 goto done;
477 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n", id_str, new_id_str));
479 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
481 ldap_mods_free(mods, True);
483 if (rc != LDAP_SUCCESS) {
484 DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type));
485 goto done;
488 ret = NT_STATUS_OK;
490 done:
491 talloc_free(ctx);
492 return ret;
495 /**********************************
496 Get current highest id.
497 **********************************/
499 static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
501 TALLOC_CTX *memctx;
502 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
503 int rc = LDAP_SERVER_DOWN;
504 int count = 0;
505 LDAPMessage *result = NULL;
506 LDAPMessage *entry = NULL;
507 char *id_str;
508 char *filter = NULL;
509 const char **attr_list;
510 const char *type;
512 /* Only do query if we are online */
513 if (idmap_is_offline()) {
514 return NT_STATUS_FILE_IS_OFFLINE;
517 if ( ! idmap_alloc_ldap) {
518 return NT_STATUS_UNSUCCESSFUL;
521 memctx = talloc_new(idmap_alloc_ldap);
522 if ( ! memctx) {
523 DEBUG(0, ("Out of memory!\n"));
524 return NT_STATUS_NO_MEMORY;
527 /* get type */
528 switch (xid->type) {
530 case ID_TYPE_UID:
531 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
532 break;
534 case ID_TYPE_GID:
535 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
536 break;
538 default:
539 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
540 return NT_STATUS_INVALID_PARAMETER;
543 filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
544 CHECK_ALLOC_DONE(filter);
546 attr_list = get_attr_list(memctx, idpool_attr_list);
547 CHECK_ALLOC_DONE(attr_list);
549 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
550 idmap_alloc_ldap->suffix,
551 LDAP_SCOPE_SUBTREE, filter,
552 attr_list, 0, &result);
554 if (rc != LDAP_SUCCESS) {
555 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
556 goto done;
559 talloc_autofree_ldapmsg(memctx, result);
561 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
562 if (count != 1) {
563 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
564 goto done;
567 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
569 id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
570 entry, type, memctx);
571 if ( ! id_str) {
572 DEBUG(0,("%s attribute not found\n", type));
573 goto done;
575 if ( ! id_str) {
576 DEBUG(0,("Out of memory\n"));
577 ret = NT_STATUS_NO_MEMORY;
578 goto done;
581 xid->id = strtoul(id_str, NULL, 10);
583 ret = NT_STATUS_OK;
584 done:
585 talloc_free(memctx);
586 return ret;
588 /**********************************
589 Set highest id.
590 **********************************/
592 static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
594 TALLOC_CTX *ctx;
595 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
596 int rc = LDAP_SERVER_DOWN;
597 int count = 0;
598 LDAPMessage *result = NULL;
599 LDAPMessage *entry = NULL;
600 LDAPMod **mods = NULL;
601 char *new_id_str;
602 char *filter = NULL;
603 const char *dn = NULL;
604 const char **attr_list;
605 const char *type;
607 /* Only do query if we are online */
608 if (idmap_is_offline()) {
609 return NT_STATUS_FILE_IS_OFFLINE;
612 if ( ! idmap_alloc_ldap) {
613 return NT_STATUS_UNSUCCESSFUL;
616 ctx = talloc_new(idmap_alloc_ldap);
617 if ( ! ctx) {
618 DEBUG(0, ("Out of memory!\n"));
619 return NT_STATUS_NO_MEMORY;
622 /* get type */
623 switch (xid->type) {
625 case ID_TYPE_UID:
626 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
627 break;
629 case ID_TYPE_GID:
630 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
631 break;
633 default:
634 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
635 return NT_STATUS_INVALID_PARAMETER;
638 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
639 CHECK_ALLOC_DONE(filter);
641 attr_list = get_attr_list(ctx, idpool_attr_list);
642 CHECK_ALLOC_DONE(attr_list);
644 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
645 idmap_alloc_ldap->suffix,
646 LDAP_SCOPE_SUBTREE, filter,
647 attr_list, 0, &result);
649 if (rc != LDAP_SUCCESS) {
650 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
651 goto done;
654 talloc_autofree_ldapmsg(ctx, result);
656 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
657 if (count != 1) {
658 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
659 goto done;
662 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
664 dn = smbldap_talloc_dn(ctx, idmap_alloc_ldap->smbldap_state->ldap_struct, entry);
665 if ( ! dn) {
666 goto done;
669 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
670 if ( ! new_id_str) {
671 DEBUG(0,("Out of memory\n"));
672 ret = NT_STATUS_NO_MEMORY;
673 goto done;
676 smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
678 if (mods == NULL) {
679 DEBUG(0,("smbldap_set_mod() failed.\n"));
680 goto done;
683 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
685 ldap_mods_free(mods, True);
687 if (rc != LDAP_SUCCESS) {
688 DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type));
689 goto done;
692 ret = NT_STATUS_OK;
694 done:
695 talloc_free(ctx);
696 return ret;
699 /**********************************
700 Close idmap ldap alloc
701 **********************************/
703 static NTSTATUS idmap_ldap_alloc_close(void)
705 if (idmap_alloc_ldap) {
706 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
707 DEBUG(5,("The connection to the LDAP server was closed\n"));
708 /* maybe free the results here --metze */
709 TALLOC_FREE(idmap_alloc_ldap);
711 return NT_STATUS_OK;
715 /**********************************************************************
716 IDMAP MAPPING LDAP BACKEND
717 **********************************************************************/
719 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
721 smbldap_free_struct(&ctx->smbldap_state);
722 DEBUG(5,("The connection to the LDAP server was closed\n"));
723 /* maybe free the results here --metze */
725 return 0;
728 /********************************
729 Initialise idmap database.
730 ********************************/
732 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom)
734 NTSTATUS ret;
735 struct idmap_ldap_context *ctx = NULL;
736 char *config_option = NULL;
737 const char *range = NULL;
738 const char *tmp = NULL;
740 /* Only do init if we are online */
741 if (idmap_is_offline()) {
742 return NT_STATUS_FILE_IS_OFFLINE;
745 ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
746 if ( ! ctx) {
747 DEBUG(0, ("Out of memory!\n"));
748 return NT_STATUS_NO_MEMORY;
751 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
752 if ( ! config_option) {
753 DEBUG(0, ("Out of memory!\n"));
754 ret = NT_STATUS_NO_MEMORY;
755 goto done;
758 /* load ranges */
759 range = lp_parm_const_string(-1, config_option, "range", NULL);
760 if (range && range[0]) {
761 if ((sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
762 (ctx->filter_low_id > ctx->filter_high_id)) {
763 DEBUG(1, ("ERROR: invalid filter range [%s]", range));
764 ctx->filter_low_id = 0;
765 ctx->filter_high_id = 0;
769 if (dom->params && *(dom->params)) {
770 /* assume location is the only parameter */
771 ctx->url = talloc_strdup(ctx, dom->params);
772 } else {
773 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
775 if ( ! tmp) {
776 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
777 ret = NT_STATUS_UNSUCCESSFUL;
778 goto done;
781 ctx->url = talloc_strdup(ctx, tmp);
783 CHECK_ALLOC_DONE(ctx->url);
785 tmp = lp_ldap_idmap_suffix();
786 if ( ! tmp || ! *tmp) {
787 tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
789 if ( ! tmp) {
790 tmp = lp_ldap_suffix();
791 if (tmp) {
792 DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp));
793 DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
794 } else {
795 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
796 ret = NT_STATUS_UNSUCCESSFUL;
797 goto done;
800 ctx->suffix = talloc_strdup(ctx, tmp);
801 CHECK_ALLOC_DONE(ctx->suffix);
803 ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
804 &ctx->smbldap_state);
805 if (!NT_STATUS_IS_OK(ret)) {
806 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
807 goto done;
810 ret = get_credentials( ctx, ctx->smbldap_state, config_option,
811 dom, &ctx->user_dn );
812 if ( !NT_STATUS_IS_OK(ret) ) {
813 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
814 "credentials (%s)\n", nt_errstr(ret)));
815 goto done;
818 /* set the destructor on the context, so that resource are properly
819 freed if the contexts is released */
821 talloc_set_destructor(ctx, idmap_ldap_close_destructor);
823 dom->private_data = ctx;
824 dom->initialized = True;
826 talloc_free(config_option);
827 return NT_STATUS_OK;
829 /*failed */
830 done:
831 talloc_free(ctx);
832 return ret;
835 /* max number of ids requested per batch query */
836 #define IDMAP_LDAP_MAX_IDS 30
838 /**********************************
839 lookup a set of unix ids.
840 **********************************/
842 /* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
843 static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id)
845 int i;
847 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
848 if (maps[i] == NULL) { /* end of the run */
849 return NULL;
851 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
852 return maps[i];
856 return NULL;
859 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
861 NTSTATUS ret;
862 TALLOC_CTX *memctx;
863 struct idmap_ldap_context *ctx;
864 LDAPMessage *result = NULL;
865 const char *uidNumber;
866 const char *gidNumber;
867 const char **attr_list;
868 char *filter = NULL;
869 BOOL multi = False;
870 int idx = 0;
871 int bidx = 0;
872 int count;
873 int rc;
874 int i;
876 /* Only do query if we are online */
877 if (idmap_is_offline()) {
878 return NT_STATUS_FILE_IS_OFFLINE;
881 /* Initilization my have been deferred because we were offline */
882 if ( ! dom->initialized) {
883 ret = idmap_ldap_db_init(dom);
884 if ( ! NT_STATUS_IS_OK(ret)) {
885 return ret;
889 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
891 memctx = talloc_new(ctx);
892 if ( ! memctx) {
893 DEBUG(0, ("Out of memory!\n"));
894 return NT_STATUS_NO_MEMORY;
897 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
898 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
900 attr_list = get_attr_list(ctx, sidmap_attr_list);
902 if ( ! ids[1]) {
903 /* if we are requested just one mapping use the simple filter */
905 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
906 LDAP_OBJ_IDMAP_ENTRY,
907 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
908 (unsigned long)ids[0]->xid.id);
909 CHECK_ALLOC_DONE(filter);
910 DEBUG(10, ("Filter: [%s]\n", filter));
911 } else {
912 /* multiple mappings */
913 multi = True;
916 again:
917 if (multi) {
919 talloc_free(filter);
920 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY);
921 CHECK_ALLOC_DONE(filter);
923 bidx = idx;
924 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
925 filter = talloc_asprintf_append(filter, "(%s=%lu)",
926 (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
927 (unsigned long)ids[idx]->xid.id);
928 CHECK_ALLOC_DONE(filter);
930 filter = talloc_asprintf_append(filter, "))");
931 CHECK_ALLOC_DONE(filter);
932 DEBUG(10, ("Filter: [%s]\n", filter));
933 } else {
934 bidx = 0;
935 idx = 1;
938 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
939 filter, attr_list, 0, &result);
941 if (rc != LDAP_SUCCESS) {
942 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
943 ret = NT_STATUS_UNSUCCESSFUL;
944 goto done;
947 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
949 if (count == 0) {
950 DEBUG(10, ("NO SIDs found\n"));
953 for (i = 0; i < count; i++) {
954 LDAPMessage *entry = NULL;
955 char *sidstr = NULL;
956 char *tmp = NULL;
957 enum id_type type;
958 struct id_map *map;
959 uint32_t id;
961 if (i == 0) { /* first entry */
962 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result);
963 } else { /* following ones */
964 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, entry);
966 if ( ! entry) {
967 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
968 break;
971 /* first check if the SID is present */
972 sidstr = smbldap_talloc_single_attribute(
973 ctx->smbldap_state->ldap_struct,
974 entry, LDAP_ATTRIBUTE_SID, memctx);
975 if ( ! sidstr) { /* no sid, skip entry */
976 DEBUG(2, ("WARNING SID not found on entry\n"));
977 continue;
980 /* now try to see if it is a uid, if not try with a gid
981 * (gid is more common, but in case both uidNumber and
982 * gidNumber are returned the SID is mapped to the uid not the gid) */
983 type = ID_TYPE_UID;
984 tmp = smbldap_talloc_single_attribute(
985 ctx->smbldap_state->ldap_struct,
986 entry, uidNumber, memctx);
987 if ( ! tmp) {
988 type = ID_TYPE_GID;
989 tmp = smbldap_talloc_single_attribute(
990 ctx->smbldap_state->ldap_struct,
991 entry, gidNumber, memctx);
993 if ( ! tmp) { /* wow very strange entry, how did it match ? */
994 DEBUG(5, ("Unprobable match on (%s), no uidNumber, nor gidNumber returned\n", sidstr));
995 TALLOC_FREE(sidstr);
996 continue;
999 id = strtoul(tmp, NULL, 10);
1000 if ((id == 0) ||
1001 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1002 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1003 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
1004 id, ctx->filter_low_id, ctx->filter_high_id));
1005 TALLOC_FREE(sidstr);
1006 TALLOC_FREE(tmp);
1007 continue;
1009 TALLOC_FREE(tmp);
1011 map = find_map_by_id(&ids[bidx], type, id);
1012 if (!map) {
1013 DEBUG(2, ("WARNING: couldn't match sid (%s) with requested ids\n", sidstr));
1014 TALLOC_FREE(sidstr);
1015 continue;
1018 if ( ! string_to_sid(map->sid, sidstr)) {
1019 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1020 TALLOC_FREE(sidstr);
1021 continue;
1023 TALLOC_FREE(sidstr);
1025 /* mapped */
1026 map->status = ID_MAPPED;
1028 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map->sid), (unsigned long)map->xid.id, map->xid.type));
1031 /* free the ldap results */
1032 if (result) {
1033 ldap_msgfree(result);
1034 result = NULL;
1037 if (multi && ids[idx]) { /* still some values to map */
1038 goto again;
1041 ret = NT_STATUS_OK;
1043 /* mark all unknwon/expired ones as unmapped */
1044 for (i = 0; ids[i]; i++) {
1045 if (ids[i]->status != ID_MAPPED)
1046 ids[i]->status = ID_UNMAPPED;
1049 done:
1050 talloc_free(memctx);
1051 return ret;
1054 /**********************************
1055 lookup a set of sids.
1056 **********************************/
1058 /* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
1059 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
1061 int i;
1063 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
1064 if (maps[i] == NULL) { /* end of the run */
1065 return NULL;
1067 if (sid_equal(maps[i]->sid, sid)) {
1068 return maps[i];
1072 return NULL;
1075 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
1077 LDAPMessage *entry = NULL;
1078 NTSTATUS ret;
1079 TALLOC_CTX *memctx;
1080 struct idmap_ldap_context *ctx;
1081 LDAPMessage *result = NULL;
1082 const char *uidNumber;
1083 const char *gidNumber;
1084 const char **attr_list;
1085 char *filter = NULL;
1086 BOOL multi = False;
1087 int idx = 0;
1088 int bidx = 0;
1089 int count;
1090 int rc;
1091 int i;
1093 /* Only do query if we are online */
1094 if (idmap_is_offline()) {
1095 return NT_STATUS_FILE_IS_OFFLINE;
1098 /* Initilization my have been deferred because we were offline */
1099 if ( ! dom->initialized) {
1100 ret = idmap_ldap_db_init(dom);
1101 if ( ! NT_STATUS_IS_OK(ret)) {
1102 return ret;
1106 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1108 memctx = talloc_new(ctx);
1109 if ( ! memctx) {
1110 DEBUG(0, ("Out of memory!\n"));
1111 return NT_STATUS_NO_MEMORY;
1114 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
1115 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
1117 attr_list = get_attr_list(ctx, sidmap_attr_list);
1119 if ( ! ids[1]) {
1120 /* if we are requested just one mapping use the simple filter */
1122 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
1123 LDAP_OBJ_IDMAP_ENTRY,
1124 LDAP_ATTRIBUTE_SID,
1125 sid_string_static(ids[0]->sid));
1126 CHECK_ALLOC_DONE(filter);
1127 DEBUG(10, ("Filter: [%s]\n", filter));
1128 } else {
1129 /* multiple mappings */
1130 multi = True;
1133 again:
1134 if (multi) {
1136 TALLOC_FREE(filter);
1137 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY);
1138 CHECK_ALLOC_DONE(filter);
1140 bidx = idx;
1141 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
1142 filter = talloc_asprintf_append(filter, "(%s=%s)",
1143 LDAP_ATTRIBUTE_SID,
1144 sid_string_static(ids[idx]->sid));
1145 CHECK_ALLOC_DONE(filter);
1147 filter = talloc_asprintf_append(filter, "))");
1148 CHECK_ALLOC_DONE(filter);
1149 DEBUG(10, ("Filter: [%s]", filter));
1150 } else {
1151 bidx = 0;
1152 idx = 1;
1155 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1156 filter, attr_list, 0, &result);
1158 if (rc != LDAP_SUCCESS) {
1159 DEBUG(3,("Failure looking up sids (%s)\n", ldap_err2string(rc)));
1160 ret = NT_STATUS_UNSUCCESSFUL;
1161 goto done;
1164 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1166 if (count == 0) {
1167 DEBUG(10, ("NO SIDs found\n"));
1170 for (i = 0; i < count; i++) {
1171 char *sidstr = NULL;
1172 char *tmp = NULL;
1173 enum id_type type;
1174 struct id_map *map;
1175 DOM_SID sid;
1176 uint32_t id;
1178 if (i == 0) { /* first entry */
1179 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result);
1180 } else { /* following ones */
1181 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, entry);
1183 if ( ! entry) {
1184 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
1185 break;
1188 /* first check if the SID is present */
1189 sidstr = smbldap_talloc_single_attribute(
1190 ctx->smbldap_state->ldap_struct,
1191 entry, LDAP_ATTRIBUTE_SID, memctx);
1192 if ( ! sidstr) { /* no sid ??, skip entry */
1193 DEBUG(2, ("WARNING SID not found on entry\n"));
1194 continue;
1197 if ( ! string_to_sid(&sid, sidstr)) {
1198 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1199 TALLOC_FREE(sidstr);
1200 continue;
1203 map = find_map_by_sid(&ids[bidx], &sid);
1204 if (!map) {
1205 DEBUG(2, ("WARNING: couldn't find entry sid (%s) in ids", sidstr));
1206 TALLOC_FREE(sidstr);
1207 continue;
1210 TALLOC_FREE(sidstr);
1212 /* now try to see if it is a uid, if not try with a gid
1213 * (gid is more common, but in case both uidNumber and
1214 * gidNumber are returned the SID is mapped to the uid not the gid) */
1215 type = ID_TYPE_UID;
1216 tmp = smbldap_talloc_single_attribute(
1217 ctx->smbldap_state->ldap_struct,
1218 entry, uidNumber, memctx);
1219 if ( ! tmp) {
1220 type = ID_TYPE_GID;
1221 tmp = smbldap_talloc_single_attribute(
1222 ctx->smbldap_state->ldap_struct,
1223 entry, gidNumber, memctx);
1225 if ( ! tmp) { /* no ids ?? */
1226 DEBUG(5, ("no uidNumber, nor gidNumber attributes found\n"));
1227 continue;
1230 id = strtoul(tmp, NULL, 10);
1231 if ((id == 0) ||
1232 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1233 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1234 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
1235 id, ctx->filter_low_id, ctx->filter_high_id));
1236 TALLOC_FREE(tmp);
1237 continue;
1239 TALLOC_FREE(tmp);
1241 /* mapped */
1242 map->xid.type = type;
1243 map->xid.id = id;
1244 map->status = ID_MAPPED;
1246 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map->sid), (unsigned long)map->xid.id, map->xid.type));
1249 /* free the ldap results */
1250 if (result) {
1251 ldap_msgfree(result);
1252 result = NULL;
1255 if (multi && ids[idx]) { /* still some values to map */
1256 goto again;
1259 ret = NT_STATUS_OK;
1261 /* mark all unknwon/expired ones as unmapped */
1262 for (i = 0; ids[i]; i++) {
1263 if (ids[i]->status != ID_MAPPED)
1264 ids[i]->status = ID_UNMAPPED;
1267 done:
1268 talloc_free(memctx);
1269 return ret;
1272 /**********************************
1273 set a mapping.
1274 **********************************/
1276 /* TODO: change this: This function cannot be called to modify a mapping, only set a new one */
1278 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id_map *map)
1280 NTSTATUS ret;
1281 TALLOC_CTX *memctx;
1282 struct idmap_ldap_context *ctx;
1283 LDAPMessage *entry = NULL;
1284 LDAPMod **mods = NULL;
1285 const char *type;
1286 char *id_str;
1287 char *sid;
1288 char *dn;
1289 int rc = -1;
1291 /* Only do query if we are online */
1292 if (idmap_is_offline()) {
1293 return NT_STATUS_FILE_IS_OFFLINE;
1296 /* Initilization my have been deferred because we were offline */
1297 if ( ! dom->initialized) {
1298 ret = idmap_ldap_db_init(dom);
1299 if ( ! NT_STATUS_IS_OK(ret)) {
1300 return ret;
1304 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1306 switch(map->xid.type) {
1307 case ID_TYPE_UID:
1308 type = get_attr_key2string(sidmap_attr_list, LDAP_ATTR_UIDNUMBER);
1309 break;
1311 case ID_TYPE_GID:
1312 type = get_attr_key2string(sidmap_attr_list, LDAP_ATTR_GIDNUMBER);
1313 break;
1315 default:
1316 return NT_STATUS_INVALID_PARAMETER;
1319 memctx = talloc_new(ctx);
1320 if ( ! memctx) {
1321 DEBUG(0, ("Out of memory!\n"));
1322 return NT_STATUS_NO_MEMORY;
1325 id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1326 CHECK_ALLOC_DONE(id_str);
1328 sid = talloc_strdup(memctx, sid_string_static(map->sid));
1329 CHECK_ALLOC_DONE(sid);
1331 dn = talloc_asprintf(memctx, "%s=%s,%s",
1332 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1333 sid,
1334 ctx->suffix);
1335 CHECK_ALLOC_DONE(dn);
1337 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY);
1339 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods, type, id_str);
1341 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1342 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), sid);
1344 if ( ! mods) {
1345 DEBUG(2, ("ERROR: No mods?\n"));
1346 ret = NT_STATUS_UNSUCCESSFUL;
1347 goto done;
1350 /* TODO: remove conflicting mappings! */
1352 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1354 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1356 rc = smbldap_add(ctx->smbldap_state, dn, mods);
1357 ldap_mods_free(mods, True);
1359 if (rc != LDAP_SUCCESS) {
1360 char *ld_error = NULL;
1361 ldap_get_option(ctx->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1362 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu mapping [%s]\n",
1363 sid, (unsigned long)map->xid.id, type));
1364 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1365 ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1366 if (ld_error) {
1367 ldap_memfree(ld_error);
1369 ret = NT_STATUS_UNSUCCESSFUL;
1370 goto done;
1373 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
1374 sid, (unsigned long)map->xid.id, type));
1376 ret = NT_STATUS_OK;
1378 done:
1379 talloc_free(memctx);
1380 return ret;
1383 /**********************************
1384 Close the idmap ldap instance
1385 **********************************/
1387 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1389 struct idmap_ldap_context *ctx;
1391 if (dom->private_data) {
1392 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1394 talloc_free(ctx);
1395 dom->private_data = NULL;
1398 return NT_STATUS_OK;
1401 static struct idmap_methods idmap_ldap_methods = {
1403 .init = idmap_ldap_db_init,
1404 .unixids_to_sids = idmap_ldap_unixids_to_sids,
1405 .sids_to_unixids = idmap_ldap_sids_to_unixids,
1406 .set_mapping = idmap_ldap_set_mapping,
1407 .close_fn = idmap_ldap_close
1410 static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
1412 .init = idmap_ldap_alloc_init,
1413 .allocate_id = idmap_ldap_allocate_id,
1414 .get_id_hwm = idmap_ldap_get_hwm,
1415 .set_id_hwm = idmap_ldap_set_hwm,
1416 .close_fn = idmap_ldap_alloc_close,
1417 /* .dump_data = TODO */
1420 NTSTATUS idmap_alloc_ldap_init(void)
1422 return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap", &idmap_ldap_alloc_methods);
1425 NTSTATUS idmap_ldap_init(void)
1427 NTSTATUS ret;
1429 /* FIXME: bad hack to actually register also the alloc_ldap module without changining configure.in */
1430 ret = idmap_alloc_ldap_init();
1431 if (! NT_STATUS_IS_OK(ret)) {
1432 return ret;
1434 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", &idmap_ldap_methods);