s4:dsdb Split schema loading and schema data management
[Samba/ekacnet.git] / source3 / winbindd / idmap_ldap.c
blob375c04a0bf05fa5681a02692e62ba1f64e97fc46
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-2007
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 3 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, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "winbindd.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_IDMAP
31 #include <lber.h>
32 #include <ldap.h>
34 #include "smbldap.h"
36 static char *idmap_fetch_secret(const char *backend, bool alloc,
37 const char *domain, const char *identity)
39 char *tmp, *ret;
40 int r;
42 if (alloc) {
43 r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
44 } else {
45 r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
48 if (r < 0)
49 return NULL;
51 strupper_m(tmp); /* make sure the key is case insensitive */
52 ret = secrets_fetch_generic(tmp, identity);
54 SAFE_FREE(tmp);
56 return ret;
59 struct idmap_ldap_context {
60 struct smbldap_state *smbldap_state;
61 char *url;
62 char *suffix;
63 char *user_dn;
64 uint32_t filter_low_id, filter_high_id; /* Filter range */
65 bool anon;
68 struct idmap_ldap_alloc_context {
69 struct smbldap_state *smbldap_state;
70 char *url;
71 char *suffix;
72 char *user_dn;
73 uid_t low_uid, high_uid; /* Range of uids */
74 gid_t low_gid, high_gid; /* Range of gids */
78 #define CHECK_ALLOC_DONE(mem) do { \
79 if (!mem) { \
80 DEBUG(0, ("Out of memory!\n")); \
81 ret = NT_STATUS_NO_MEMORY; \
82 goto done; \
83 } } while (0)
85 /**********************************************************************
86 IDMAP ALLOC TDB BACKEND
87 **********************************************************************/
89 static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
91 /*********************************************************************
92 ********************************************************************/
94 static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
95 struct smbldap_state *ldap_state,
96 const char *config_option,
97 struct idmap_domain *dom,
98 char **dn )
100 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
101 char *secret = NULL;
102 const char *tmp = NULL;
103 char *user_dn = NULL;
104 bool anon = False;
106 /* assume anonymous if we don't have a specified user */
108 tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
110 if ( tmp ) {
111 if (!dom) {
112 /* only the alloc backend can pass in a NULL dom */
113 secret = idmap_fetch_secret("ldap", True,
114 NULL, tmp);
115 } else {
116 secret = idmap_fetch_secret("ldap", False,
117 dom->name, tmp);
120 if (!secret) {
121 DEBUG(0, ("get_credentials: Unable to fetch "
122 "auth credentials for %s in %s\n",
123 tmp, (dom==NULL)?"ALLOC":dom->name));
124 ret = NT_STATUS_ACCESS_DENIED;
125 goto done;
127 *dn = talloc_strdup(mem_ctx, tmp);
128 CHECK_ALLOC_DONE(*dn);
129 } else {
130 if (!fetch_ldap_pw(&user_dn, &secret)) {
131 DEBUG(2, ("get_credentials: Failed to lookup ldap "
132 "bind creds. Using anonymous connection.\n"));
133 anon = True;
134 *dn = NULL;
135 } else {
136 *dn = talloc_strdup(mem_ctx, user_dn);
137 SAFE_FREE( user_dn );
138 CHECK_ALLOC_DONE(*dn);
142 smbldap_set_creds(ldap_state, anon, *dn, secret);
143 ret = NT_STATUS_OK;
145 done:
146 SAFE_FREE(secret);
148 return ret;
152 /**********************************************************************
153 Verify the sambaUnixIdPool entry in the directory.
154 **********************************************************************/
156 static NTSTATUS verify_idpool(void)
158 NTSTATUS ret;
159 TALLOC_CTX *ctx;
160 LDAPMessage *result = NULL;
161 LDAPMod **mods = NULL;
162 const char **attr_list;
163 char *filter;
164 int count;
165 int rc;
167 if ( ! idmap_alloc_ldap) {
168 return NT_STATUS_UNSUCCESSFUL;
171 ctx = talloc_new(idmap_alloc_ldap);
172 if ( ! ctx) {
173 DEBUG(0, ("Out of memory!\n"));
174 return NT_STATUS_NO_MEMORY;
177 filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
178 CHECK_ALLOC_DONE(filter);
180 attr_list = get_attr_list(ctx, idpool_attr_list);
181 CHECK_ALLOC_DONE(attr_list);
183 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
184 idmap_alloc_ldap->suffix,
185 LDAP_SCOPE_SUBTREE,
186 filter,
187 attr_list,
189 &result);
191 if (rc != LDAP_SUCCESS) {
192 DEBUG(1, ("Unable to verify the idpool, "
193 "cannot continue initialization!\n"));
194 return NT_STATUS_UNSUCCESSFUL;
197 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
198 result);
200 ldap_msgfree(result);
202 if ( count > 1 ) {
203 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
204 filter, idmap_alloc_ldap->suffix));
205 ret = NT_STATUS_UNSUCCESSFUL;
206 goto done;
208 else if (count == 0) {
209 char *uid_str, *gid_str;
211 uid_str = talloc_asprintf(ctx, "%lu",
212 (unsigned long)idmap_alloc_ldap->low_uid);
213 gid_str = talloc_asprintf(ctx, "%lu",
214 (unsigned long)idmap_alloc_ldap->low_gid);
216 smbldap_set_mod(&mods, LDAP_MOD_ADD,
217 "objectClass", LDAP_OBJ_IDPOOL);
218 smbldap_set_mod(&mods, LDAP_MOD_ADD,
219 get_attr_key2string(idpool_attr_list,
220 LDAP_ATTR_UIDNUMBER),
221 uid_str);
222 smbldap_set_mod(&mods, LDAP_MOD_ADD,
223 get_attr_key2string(idpool_attr_list,
224 LDAP_ATTR_GIDNUMBER),
225 gid_str);
226 if (mods) {
227 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
228 idmap_alloc_ldap->suffix,
229 mods);
230 ldap_mods_free(mods, True);
231 } else {
232 ret = NT_STATUS_UNSUCCESSFUL;
233 goto done;
237 ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
238 done:
239 talloc_free(ctx);
240 return ret;
243 /*****************************************************************************
244 Initialise idmap database.
245 *****************************************************************************/
247 static NTSTATUS idmap_ldap_alloc_init(const char *params)
249 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
250 const char *tmp;
251 uid_t low_uid = 0;
252 uid_t high_uid = 0;
253 gid_t low_gid = 0;
254 gid_t high_gid = 0;
256 /* Only do init if we are online */
257 if (idmap_is_offline()) {
258 return NT_STATUS_FILE_IS_OFFLINE;
261 idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
262 CHECK_ALLOC_DONE( idmap_alloc_ldap );
264 /* load ranges */
266 if (!lp_idmap_uid(&low_uid, &high_uid)
267 || !lp_idmap_gid(&low_gid, &high_gid)) {
268 DEBUG(1, ("idmap uid or idmap gid missing\n"));
269 ret = NT_STATUS_UNSUCCESSFUL;
270 goto done;
273 idmap_alloc_ldap->low_uid = low_uid;
274 idmap_alloc_ldap->high_uid = high_uid;
275 idmap_alloc_ldap->low_gid = low_gid;
276 idmap_alloc_ldap->high_gid= high_gid;
278 if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) {
279 DEBUG(1, ("idmap uid range invalid\n"));
280 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
281 ret = NT_STATUS_UNSUCCESSFUL;
282 goto done;
285 if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) {
286 DEBUG(1, ("idmap gid range invalid\n"));
287 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
288 ret = NT_STATUS_UNSUCCESSFUL;
289 goto done;
292 if (params && *params) {
293 /* assume location is the only parameter */
294 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
295 } else {
296 tmp = lp_parm_const_string(-1, "idmap alloc config",
297 "ldap_url", NULL);
299 if ( ! tmp) {
300 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
301 ret = NT_STATUS_UNSUCCESSFUL;
302 goto done;
305 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
307 CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
309 tmp = lp_parm_const_string(-1, "idmap alloc config",
310 "ldap_base_dn", NULL);
311 if ( ! tmp || ! *tmp) {
312 tmp = lp_ldap_idmap_suffix();
313 if ( ! tmp) {
314 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
315 ret = NT_STATUS_UNSUCCESSFUL;
316 goto done;
320 idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
321 CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
323 ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
324 idmap_alloc_ldap->url,
325 &idmap_alloc_ldap->smbldap_state);
326 if (!NT_STATUS_IS_OK(ret)) {
327 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
328 idmap_alloc_ldap->url));
329 goto done;
332 ret = get_credentials( idmap_alloc_ldap,
333 idmap_alloc_ldap->smbldap_state,
334 "idmap alloc config", NULL,
335 &idmap_alloc_ldap->user_dn );
336 if ( !NT_STATUS_IS_OK(ret) ) {
337 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
338 "credentials (%s)\n", nt_errstr(ret)));
339 goto done;
342 /* see if the idmap suffix and sub entries exists */
344 ret = verify_idpool();
346 done:
347 if ( !NT_STATUS_IS_OK( ret ) )
348 TALLOC_FREE( idmap_alloc_ldap );
350 return ret;
353 /********************************
354 Allocate a new uid or gid
355 ********************************/
357 static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
359 TALLOC_CTX *ctx;
360 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
361 int rc = LDAP_SERVER_DOWN;
362 int count = 0;
363 LDAPMessage *result = NULL;
364 LDAPMessage *entry = NULL;
365 LDAPMod **mods = NULL;
366 char *id_str;
367 char *new_id_str;
368 char *filter = NULL;
369 const char *dn = NULL;
370 const char **attr_list;
371 const char *type;
373 /* Only do query if we are online */
374 if (idmap_is_offline()) {
375 return NT_STATUS_FILE_IS_OFFLINE;
378 if ( ! idmap_alloc_ldap) {
379 return NT_STATUS_UNSUCCESSFUL;
382 ctx = talloc_new(idmap_alloc_ldap);
383 if ( ! ctx) {
384 DEBUG(0, ("Out of memory!\n"));
385 return NT_STATUS_NO_MEMORY;
388 /* get type */
389 switch (xid->type) {
391 case ID_TYPE_UID:
392 type = get_attr_key2string(idpool_attr_list,
393 LDAP_ATTR_UIDNUMBER);
394 break;
396 case ID_TYPE_GID:
397 type = get_attr_key2string(idpool_attr_list,
398 LDAP_ATTR_GIDNUMBER);
399 break;
401 default:
402 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
403 return NT_STATUS_INVALID_PARAMETER;
406 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
407 CHECK_ALLOC_DONE(filter);
409 attr_list = get_attr_list(ctx, idpool_attr_list);
410 CHECK_ALLOC_DONE(attr_list);
412 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
414 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
415 idmap_alloc_ldap->suffix,
416 LDAP_SCOPE_SUBTREE, filter,
417 attr_list, 0, &result);
419 if (rc != LDAP_SUCCESS) {
420 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
421 goto done;
424 talloc_autofree_ldapmsg(ctx, result);
426 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
427 result);
428 if (count != 1) {
429 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
430 goto done;
433 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
434 result);
436 dn = smbldap_talloc_dn(ctx,
437 idmap_alloc_ldap->smbldap_state->ldap_struct,
438 entry);
439 if ( ! dn) {
440 goto done;
443 if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
444 entry, type, ctx))) {
445 DEBUG(0,("%s attribute not found\n", type));
446 goto done;
448 if ( ! id_str) {
449 DEBUG(0,("Out of memory\n"));
450 ret = NT_STATUS_NO_MEMORY;
451 goto done;
454 xid->id = strtoul(id_str, NULL, 10);
456 /* make sure we still have room to grow */
458 switch (xid->type) {
459 case ID_TYPE_UID:
460 if (xid->id > idmap_alloc_ldap->high_uid) {
461 DEBUG(0,("Cannot allocate uid above %lu!\n",
462 (unsigned long)idmap_alloc_ldap->high_uid));
463 goto done;
465 break;
467 case ID_TYPE_GID:
468 if (xid->id > idmap_alloc_ldap->high_gid) {
469 DEBUG(0,("Cannot allocate gid above %lu!\n",
470 (unsigned long)idmap_alloc_ldap->high_uid));
471 goto done;
473 break;
475 default:
476 /* impossible */
477 goto done;
480 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
481 if ( ! new_id_str) {
482 DEBUG(0,("Out of memory\n"));
483 ret = NT_STATUS_NO_MEMORY;
484 goto done;
487 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
488 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
490 if (mods == NULL) {
491 DEBUG(0,("smbldap_set_mod() failed.\n"));
492 goto done;
495 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
496 id_str, new_id_str));
498 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
500 ldap_mods_free(mods, True);
502 if (rc != LDAP_SUCCESS) {
503 DEBUG(1,("Failed to allocate new %s. "
504 "smbldap_modify() failed.\n", type));
505 goto done;
508 ret = NT_STATUS_OK;
510 done:
511 talloc_free(ctx);
512 return ret;
515 /**********************************
516 Get current highest id.
517 **********************************/
519 static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
521 TALLOC_CTX *memctx;
522 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
523 int rc = LDAP_SERVER_DOWN;
524 int count = 0;
525 LDAPMessage *result = NULL;
526 LDAPMessage *entry = NULL;
527 char *id_str;
528 char *filter = NULL;
529 const char **attr_list;
530 const char *type;
532 /* Only do query if we are online */
533 if (idmap_is_offline()) {
534 return NT_STATUS_FILE_IS_OFFLINE;
537 if ( ! idmap_alloc_ldap) {
538 return NT_STATUS_UNSUCCESSFUL;
541 memctx = talloc_new(idmap_alloc_ldap);
542 if ( ! memctx) {
543 DEBUG(0, ("Out of memory!\n"));
544 return NT_STATUS_NO_MEMORY;
547 /* get type */
548 switch (xid->type) {
550 case ID_TYPE_UID:
551 type = get_attr_key2string(idpool_attr_list,
552 LDAP_ATTR_UIDNUMBER);
553 break;
555 case ID_TYPE_GID:
556 type = get_attr_key2string(idpool_attr_list,
557 LDAP_ATTR_GIDNUMBER);
558 break;
560 default:
561 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
562 return NT_STATUS_INVALID_PARAMETER;
565 filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
566 CHECK_ALLOC_DONE(filter);
568 attr_list = get_attr_list(memctx, idpool_attr_list);
569 CHECK_ALLOC_DONE(attr_list);
571 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
572 idmap_alloc_ldap->suffix,
573 LDAP_SCOPE_SUBTREE, filter,
574 attr_list, 0, &result);
576 if (rc != LDAP_SUCCESS) {
577 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
578 goto done;
581 talloc_autofree_ldapmsg(memctx, result);
583 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
584 result);
585 if (count != 1) {
586 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
587 goto done;
590 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
591 result);
593 id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
594 entry, type, memctx);
595 if ( ! id_str) {
596 DEBUG(0,("%s attribute not found\n", type));
597 goto done;
599 if ( ! id_str) {
600 DEBUG(0,("Out of memory\n"));
601 ret = NT_STATUS_NO_MEMORY;
602 goto done;
605 xid->id = strtoul(id_str, NULL, 10);
607 ret = NT_STATUS_OK;
608 done:
609 talloc_free(memctx);
610 return ret;
612 /**********************************
613 Set highest id.
614 **********************************/
616 static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
618 TALLOC_CTX *ctx;
619 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
620 int rc = LDAP_SERVER_DOWN;
621 int count = 0;
622 LDAPMessage *result = NULL;
623 LDAPMessage *entry = NULL;
624 LDAPMod **mods = NULL;
625 char *new_id_str;
626 char *filter = NULL;
627 const char *dn = NULL;
628 const char **attr_list;
629 const char *type;
631 /* Only do query if we are online */
632 if (idmap_is_offline()) {
633 return NT_STATUS_FILE_IS_OFFLINE;
636 if ( ! idmap_alloc_ldap) {
637 return NT_STATUS_UNSUCCESSFUL;
640 ctx = talloc_new(idmap_alloc_ldap);
641 if ( ! ctx) {
642 DEBUG(0, ("Out of memory!\n"));
643 return NT_STATUS_NO_MEMORY;
646 /* get type */
647 switch (xid->type) {
649 case ID_TYPE_UID:
650 type = get_attr_key2string(idpool_attr_list,
651 LDAP_ATTR_UIDNUMBER);
652 break;
654 case ID_TYPE_GID:
655 type = get_attr_key2string(idpool_attr_list,
656 LDAP_ATTR_GIDNUMBER);
657 break;
659 default:
660 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
661 return NT_STATUS_INVALID_PARAMETER;
664 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
665 CHECK_ALLOC_DONE(filter);
667 attr_list = get_attr_list(ctx, idpool_attr_list);
668 CHECK_ALLOC_DONE(attr_list);
670 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
671 idmap_alloc_ldap->suffix,
672 LDAP_SCOPE_SUBTREE, filter,
673 attr_list, 0, &result);
675 if (rc != LDAP_SUCCESS) {
676 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
677 goto done;
680 talloc_autofree_ldapmsg(ctx, result);
682 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
683 result);
684 if (count != 1) {
685 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
686 goto done;
689 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
690 result);
692 dn = smbldap_talloc_dn(ctx,
693 idmap_alloc_ldap->smbldap_state->ldap_struct,
694 entry);
695 if ( ! dn) {
696 goto done;
699 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
700 if ( ! new_id_str) {
701 DEBUG(0,("Out of memory\n"));
702 ret = NT_STATUS_NO_MEMORY;
703 goto done;
706 smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
708 if (mods == NULL) {
709 DEBUG(0,("smbldap_set_mod() failed.\n"));
710 goto done;
713 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
715 ldap_mods_free(mods, True);
717 if (rc != LDAP_SUCCESS) {
718 DEBUG(1,("Failed to allocate new %s. "
719 "smbldap_modify() failed.\n", type));
720 goto done;
723 ret = NT_STATUS_OK;
725 done:
726 talloc_free(ctx);
727 return ret;
730 /**********************************
731 Close idmap ldap alloc
732 **********************************/
734 static NTSTATUS idmap_ldap_alloc_close(void)
736 if (idmap_alloc_ldap) {
737 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
738 DEBUG(5,("The connection to the LDAP server was closed\n"));
739 /* maybe free the results here --metze */
740 TALLOC_FREE(idmap_alloc_ldap);
742 return NT_STATUS_OK;
746 /**********************************************************************
747 IDMAP MAPPING LDAP BACKEND
748 **********************************************************************/
750 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
752 smbldap_free_struct(&ctx->smbldap_state);
753 DEBUG(5,("The connection to the LDAP server was closed\n"));
754 /* maybe free the results here --metze */
756 return 0;
759 /********************************
760 Initialise idmap database.
761 ********************************/
763 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
764 const char *params)
766 NTSTATUS ret;
767 struct idmap_ldap_context *ctx = NULL;
768 char *config_option = NULL;
769 const char *tmp = NULL;
771 /* Only do init if we are online */
772 if (idmap_is_offline()) {
773 return NT_STATUS_FILE_IS_OFFLINE;
776 ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
777 if ( ! ctx) {
778 DEBUG(0, ("Out of memory!\n"));
779 return NT_STATUS_NO_MEMORY;
782 if (strequal(dom->name, "*")) {
783 uid_t low_uid = 0;
784 uid_t high_uid = 0;
785 gid_t low_gid = 0;
786 gid_t high_gid = 0;
788 ctx->filter_low_id = 0;
789 ctx->filter_high_id = 0;
791 if (lp_idmap_uid(&low_uid, &high_uid)) {
792 ctx->filter_low_id = low_uid;
793 ctx->filter_high_id = high_uid;
794 } else {
795 DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
798 if (lp_idmap_gid(&low_gid, &high_gid)) {
799 if ((low_gid != low_uid) || (high_gid != high_uid)) {
800 DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
801 " ranges do not agree -- building "
802 "intersection\n"));
803 ctx->filter_low_id = MAX(ctx->filter_low_id,
804 low_gid);
805 ctx->filter_high_id = MIN(ctx->filter_high_id,
806 high_gid);
808 } else {
809 DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
811 } else {
812 const char *range = NULL;
814 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
815 if ( ! config_option) {
816 DEBUG(0, ("Out of memory!\n"));
817 ret = NT_STATUS_NO_MEMORY;
818 goto done;
821 /* load ranges */
822 range = lp_parm_const_string(-1, config_option, "range", NULL);
823 if (range && range[0]) {
824 if ((sscanf(range, "%u - %u", &ctx->filter_low_id,
825 &ctx->filter_high_id) != 2))
827 DEBUG(1, ("ERROR: invalid filter range [%s]", range));
828 ctx->filter_low_id = 0;
829 ctx->filter_high_id = 0;
834 if (ctx->filter_low_id > ctx->filter_high_id) {
835 DEBUG(1, ("ERROR: invalid filter range [%u-%u]",
836 ctx->filter_low_id, ctx->filter_high_id));
837 ctx->filter_low_id = 0;
838 ctx->filter_high_id = 0;
841 if (params != NULL) {
842 /* assume location is the only parameter */
843 ctx->url = talloc_strdup(ctx, params);
844 } else {
845 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
847 if ( ! tmp) {
848 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
849 ret = NT_STATUS_UNSUCCESSFUL;
850 goto done;
853 ctx->url = talloc_strdup(ctx, tmp);
855 CHECK_ALLOC_DONE(ctx->url);
857 tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
858 if ( ! tmp || ! *tmp) {
859 tmp = lp_ldap_idmap_suffix();
860 if ( ! tmp) {
861 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
862 ret = NT_STATUS_UNSUCCESSFUL;
863 goto done;
867 ctx->suffix = talloc_strdup(ctx, tmp);
868 CHECK_ALLOC_DONE(ctx->suffix);
870 ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
871 &ctx->smbldap_state);
872 if (!NT_STATUS_IS_OK(ret)) {
873 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
874 goto done;
877 ret = get_credentials( ctx, ctx->smbldap_state, config_option,
878 dom, &ctx->user_dn );
879 if ( !NT_STATUS_IS_OK(ret) ) {
880 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
881 "credentials (%s)\n", nt_errstr(ret)));
882 goto done;
885 /* set the destructor on the context, so that resource are properly
886 freed if the contexts is released */
888 talloc_set_destructor(ctx, idmap_ldap_close_destructor);
890 dom->private_data = ctx;
892 talloc_free(config_option);
893 return NT_STATUS_OK;
895 /*failed */
896 done:
897 talloc_free(ctx);
898 return ret;
901 /* max number of ids requested per batch query */
902 #define IDMAP_LDAP_MAX_IDS 30
904 /**********************************
905 lookup a set of unix ids.
906 **********************************/
908 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
909 * in maps for a match */
910 static struct id_map *find_map_by_id(struct id_map **maps,
911 enum id_type type,
912 uint32_t id)
914 int i;
916 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
917 if (maps[i] == NULL) { /* end of the run */
918 return NULL;
920 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
921 return maps[i];
925 return NULL;
928 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
929 struct id_map **ids)
931 NTSTATUS ret;
932 TALLOC_CTX *memctx;
933 struct idmap_ldap_context *ctx;
934 LDAPMessage *result = NULL;
935 LDAPMessage *entry = NULL;
936 const char *uidNumber;
937 const char *gidNumber;
938 const char **attr_list;
939 char *filter = NULL;
940 bool multi = False;
941 int idx = 0;
942 int bidx = 0;
943 int count;
944 int rc;
945 int i;
947 /* Only do query if we are online */
948 if (idmap_is_offline()) {
949 return NT_STATUS_FILE_IS_OFFLINE;
952 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
954 memctx = talloc_new(ctx);
955 if ( ! memctx) {
956 DEBUG(0, ("Out of memory!\n"));
957 return NT_STATUS_NO_MEMORY;
960 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
961 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
963 attr_list = get_attr_list(memctx, sidmap_attr_list);
965 if ( ! ids[1]) {
966 /* if we are requested just one mapping use the simple filter */
968 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
969 LDAP_OBJ_IDMAP_ENTRY,
970 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
971 (unsigned long)ids[0]->xid.id);
972 CHECK_ALLOC_DONE(filter);
973 DEBUG(10, ("Filter: [%s]\n", filter));
974 } else {
975 /* multiple mappings */
976 multi = True;
979 for (i = 0; ids[i]; i++) {
980 ids[i]->status = ID_UNKNOWN;
983 again:
984 if (multi) {
986 talloc_free(filter);
987 filter = talloc_asprintf(memctx,
988 "(&(objectClass=%s)(|",
989 LDAP_OBJ_IDMAP_ENTRY);
990 CHECK_ALLOC_DONE(filter);
992 bidx = idx;
993 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
994 filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
995 (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
996 (unsigned long)ids[idx]->xid.id);
997 CHECK_ALLOC_DONE(filter);
999 filter = talloc_asprintf_append_buffer(filter, "))");
1000 CHECK_ALLOC_DONE(filter);
1001 DEBUG(10, ("Filter: [%s]\n", filter));
1002 } else {
1003 bidx = 0;
1004 idx = 1;
1007 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1008 filter, attr_list, 0, &result);
1010 if (rc != LDAP_SUCCESS) {
1011 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
1012 ret = NT_STATUS_UNSUCCESSFUL;
1013 goto done;
1016 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1018 if (count == 0) {
1019 DEBUG(10, ("NO SIDs found\n"));
1022 for (i = 0; i < count; i++) {
1023 char *sidstr = NULL;
1024 char *tmp = NULL;
1025 enum id_type type;
1026 struct id_map *map;
1027 uint32_t id;
1029 if (i == 0) { /* first entry */
1030 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1031 result);
1032 } else { /* following ones */
1033 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1034 entry);
1036 if ( ! entry) {
1037 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1038 "from results\n"));
1039 break;
1042 /* first check if the SID is present */
1043 sidstr = smbldap_talloc_single_attribute(
1044 ctx->smbldap_state->ldap_struct,
1045 entry, LDAP_ATTRIBUTE_SID, memctx);
1046 if ( ! sidstr) { /* no sid, skip entry */
1047 DEBUG(2, ("WARNING SID not found on entry\n"));
1048 continue;
1051 /* now try to see if it is a uid, if not try with a gid
1052 * (gid is more common, but in case both uidNumber and
1053 * gidNumber are returned the SID is mapped to the uid
1054 *not the gid) */
1055 type = ID_TYPE_UID;
1056 tmp = smbldap_talloc_single_attribute(
1057 ctx->smbldap_state->ldap_struct,
1058 entry, uidNumber, memctx);
1059 if ( ! tmp) {
1060 type = ID_TYPE_GID;
1061 tmp = smbldap_talloc_single_attribute(
1062 ctx->smbldap_state->ldap_struct,
1063 entry, gidNumber, memctx);
1065 if ( ! tmp) { /* wow very strange entry, how did it match ? */
1066 DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
1067 "nor gidNumber returned\n", sidstr));
1068 TALLOC_FREE(sidstr);
1069 continue;
1072 id = strtoul(tmp, NULL, 10);
1073 if ((id == 0) ||
1074 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1075 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1076 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1077 "Filtered!\n", id,
1078 ctx->filter_low_id, ctx->filter_high_id));
1079 TALLOC_FREE(sidstr);
1080 TALLOC_FREE(tmp);
1081 continue;
1083 TALLOC_FREE(tmp);
1085 map = find_map_by_id(&ids[bidx], type, id);
1086 if (!map) {
1087 DEBUG(2, ("WARNING: couldn't match sid (%s) "
1088 "with requested ids\n", sidstr));
1089 TALLOC_FREE(sidstr);
1090 continue;
1093 if ( ! string_to_sid(map->sid, sidstr)) {
1094 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1095 TALLOC_FREE(sidstr);
1096 continue;
1099 if (map->status == ID_MAPPED) {
1100 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1101 "overwriting mapping %u -> %s with %u -> %s\n",
1102 (type == ID_TYPE_UID) ? "UID" : "GID",
1103 id, sid_string_dbg(map->sid), id, sidstr));
1106 TALLOC_FREE(sidstr);
1108 /* mapped */
1109 map->status = ID_MAPPED;
1111 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1112 (unsigned long)map->xid.id, map->xid.type));
1115 /* free the ldap results */
1116 if (result) {
1117 ldap_msgfree(result);
1118 result = NULL;
1121 if (multi && ids[idx]) { /* still some values to map */
1122 goto again;
1125 ret = NT_STATUS_OK;
1127 /* mark all unknwon/expired ones as unmapped */
1128 for (i = 0; ids[i]; i++) {
1129 if (ids[i]->status != ID_MAPPED)
1130 ids[i]->status = ID_UNMAPPED;
1133 done:
1134 talloc_free(memctx);
1135 return ret;
1138 /**********************************
1139 lookup a set of sids.
1140 **********************************/
1142 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
1143 * in maps for a match */
1144 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
1146 int i;
1148 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
1149 if (maps[i] == NULL) { /* end of the run */
1150 return NULL;
1152 if (sid_equal(maps[i]->sid, sid)) {
1153 return maps[i];
1157 return NULL;
1160 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
1161 struct id_map **ids)
1163 LDAPMessage *entry = NULL;
1164 NTSTATUS ret;
1165 TALLOC_CTX *memctx;
1166 struct idmap_ldap_context *ctx;
1167 LDAPMessage *result = NULL;
1168 const char *uidNumber;
1169 const char *gidNumber;
1170 const char **attr_list;
1171 char *filter = NULL;
1172 bool multi = False;
1173 int idx = 0;
1174 int bidx = 0;
1175 int count;
1176 int rc;
1177 int i;
1179 /* Only do query if we are online */
1180 if (idmap_is_offline()) {
1181 return NT_STATUS_FILE_IS_OFFLINE;
1184 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1186 memctx = talloc_new(ctx);
1187 if ( ! memctx) {
1188 DEBUG(0, ("Out of memory!\n"));
1189 return NT_STATUS_NO_MEMORY;
1192 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
1193 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
1195 attr_list = get_attr_list(memctx, sidmap_attr_list);
1197 if ( ! ids[1]) {
1198 /* if we are requested just one mapping use the simple filter */
1200 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
1201 LDAP_OBJ_IDMAP_ENTRY,
1202 LDAP_ATTRIBUTE_SID,
1203 sid_string_talloc(memctx, ids[0]->sid));
1204 CHECK_ALLOC_DONE(filter);
1205 DEBUG(10, ("Filter: [%s]\n", filter));
1206 } else {
1207 /* multiple mappings */
1208 multi = True;
1211 for (i = 0; ids[i]; i++) {
1212 ids[i]->status = ID_UNKNOWN;
1215 again:
1216 if (multi) {
1218 TALLOC_FREE(filter);
1219 filter = talloc_asprintf(memctx,
1220 "(&(objectClass=%s)(|",
1221 LDAP_OBJ_IDMAP_ENTRY);
1222 CHECK_ALLOC_DONE(filter);
1224 bidx = idx;
1225 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
1226 filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
1227 LDAP_ATTRIBUTE_SID,
1228 sid_string_talloc(memctx,
1229 ids[idx]->sid));
1230 CHECK_ALLOC_DONE(filter);
1232 filter = talloc_asprintf_append_buffer(filter, "))");
1233 CHECK_ALLOC_DONE(filter);
1234 DEBUG(10, ("Filter: [%s]", filter));
1235 } else {
1236 bidx = 0;
1237 idx = 1;
1240 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1241 filter, attr_list, 0, &result);
1243 if (rc != LDAP_SUCCESS) {
1244 DEBUG(3,("Failure looking up sids (%s)\n",
1245 ldap_err2string(rc)));
1246 ret = NT_STATUS_UNSUCCESSFUL;
1247 goto done;
1250 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1252 if (count == 0) {
1253 DEBUG(10, ("NO SIDs found\n"));
1256 for (i = 0; i < count; i++) {
1257 char *sidstr = NULL;
1258 char *tmp = NULL;
1259 enum id_type type;
1260 struct id_map *map;
1261 DOM_SID sid;
1262 uint32_t id;
1264 if (i == 0) { /* first entry */
1265 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1266 result);
1267 } else { /* following ones */
1268 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1269 entry);
1271 if ( ! entry) {
1272 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1273 "from results\n"));
1274 break;
1277 /* first check if the SID is present */
1278 sidstr = smbldap_talloc_single_attribute(
1279 ctx->smbldap_state->ldap_struct,
1280 entry, LDAP_ATTRIBUTE_SID, memctx);
1281 if ( ! sidstr) { /* no sid ??, skip entry */
1282 DEBUG(2, ("WARNING SID not found on entry\n"));
1283 continue;
1286 if ( ! string_to_sid(&sid, sidstr)) {
1287 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1288 TALLOC_FREE(sidstr);
1289 continue;
1292 map = find_map_by_sid(&ids[bidx], &sid);
1293 if (!map) {
1294 DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1295 "in ids", sidstr));
1296 TALLOC_FREE(sidstr);
1297 continue;
1300 /* now try to see if it is a uid, if not try with a gid
1301 * (gid is more common, but in case both uidNumber and
1302 * gidNumber are returned the SID is mapped to the uid
1303 * not the gid) */
1304 type = ID_TYPE_UID;
1305 tmp = smbldap_talloc_single_attribute(
1306 ctx->smbldap_state->ldap_struct,
1307 entry, uidNumber, memctx);
1308 if ( ! tmp) {
1309 type = ID_TYPE_GID;
1310 tmp = smbldap_talloc_single_attribute(
1311 ctx->smbldap_state->ldap_struct,
1312 entry, gidNumber, memctx);
1314 if ( ! tmp) { /* no ids ?? */
1315 DEBUG(5, ("no uidNumber, "
1316 "nor gidNumber attributes found\n"));
1317 TALLOC_FREE(sidstr);
1318 continue;
1321 id = strtoul(tmp, NULL, 10);
1322 if ((id == 0) ||
1323 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1324 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1325 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1326 "Filtered!\n", id,
1327 ctx->filter_low_id, ctx->filter_high_id));
1328 TALLOC_FREE(sidstr);
1329 TALLOC_FREE(tmp);
1330 continue;
1332 TALLOC_FREE(tmp);
1334 if (map->status == ID_MAPPED) {
1335 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1336 "overwriting mapping %s -> %u with %s -> %u\n",
1337 (type == ID_TYPE_UID) ? "UID" : "GID",
1338 sidstr, map->xid.id, sidstr, id));
1341 TALLOC_FREE(sidstr);
1343 /* mapped */
1344 map->xid.type = type;
1345 map->xid.id = id;
1346 map->status = ID_MAPPED;
1348 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1349 (unsigned long)map->xid.id, map->xid.type));
1352 /* free the ldap results */
1353 if (result) {
1354 ldap_msgfree(result);
1355 result = NULL;
1358 if (multi && ids[idx]) { /* still some values to map */
1359 goto again;
1362 ret = NT_STATUS_OK;
1364 /* mark all unknwon/expired ones as unmapped */
1365 for (i = 0; ids[i]; i++) {
1366 if (ids[i]->status != ID_MAPPED)
1367 ids[i]->status = ID_UNMAPPED;
1370 done:
1371 talloc_free(memctx);
1372 return ret;
1375 /**********************************
1376 set a mapping.
1377 **********************************/
1379 /* TODO: change this: This function cannot be called to modify a mapping,
1380 * only set a new one */
1382 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
1383 const struct id_map *map)
1385 NTSTATUS ret;
1386 TALLOC_CTX *memctx;
1387 struct idmap_ldap_context *ctx;
1388 LDAPMessage *entry = NULL;
1389 LDAPMod **mods = NULL;
1390 const char *type;
1391 char *id_str;
1392 char *sid;
1393 char *dn;
1394 int rc = -1;
1396 /* Only do query if we are online */
1397 if (idmap_is_offline()) {
1398 return NT_STATUS_FILE_IS_OFFLINE;
1401 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1403 switch(map->xid.type) {
1404 case ID_TYPE_UID:
1405 type = get_attr_key2string(sidmap_attr_list,
1406 LDAP_ATTR_UIDNUMBER);
1407 break;
1409 case ID_TYPE_GID:
1410 type = get_attr_key2string(sidmap_attr_list,
1411 LDAP_ATTR_GIDNUMBER);
1412 break;
1414 default:
1415 return NT_STATUS_INVALID_PARAMETER;
1418 memctx = talloc_new(ctx);
1419 if ( ! memctx) {
1420 DEBUG(0, ("Out of memory!\n"));
1421 return NT_STATUS_NO_MEMORY;
1424 id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1425 CHECK_ALLOC_DONE(id_str);
1427 sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
1428 CHECK_ALLOC_DONE(sid);
1430 dn = talloc_asprintf(memctx, "%s=%s,%s",
1431 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1432 sid,
1433 ctx->suffix);
1434 CHECK_ALLOC_DONE(dn);
1436 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1437 "objectClass", LDAP_OBJ_IDMAP_ENTRY);
1439 smbldap_make_mod(ctx->smbldap_state->ldap_struct,
1440 entry, &mods, type, id_str);
1442 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1443 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1444 sid);
1446 if ( ! mods) {
1447 DEBUG(2, ("ERROR: No mods?\n"));
1448 ret = NT_STATUS_UNSUCCESSFUL;
1449 goto done;
1452 /* TODO: remove conflicting mappings! */
1454 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1456 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1458 rc = smbldap_add(ctx->smbldap_state, dn, mods);
1459 ldap_mods_free(mods, True);
1461 if (rc != LDAP_SUCCESS) {
1462 char *ld_error = NULL;
1463 ldap_get_option(ctx->smbldap_state->ldap_struct,
1464 LDAP_OPT_ERROR_STRING, &ld_error);
1465 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
1466 "mapping [%s]\n", sid,
1467 (unsigned long)map->xid.id, type));
1468 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1469 ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1470 if (ld_error) {
1471 ldap_memfree(ld_error);
1473 ret = NT_STATUS_UNSUCCESSFUL;
1474 goto done;
1477 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
1478 "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
1480 ret = NT_STATUS_OK;
1482 done:
1483 talloc_free(memctx);
1484 return ret;
1487 /**********************************
1488 Close the idmap ldap instance
1489 **********************************/
1491 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1493 struct idmap_ldap_context *ctx;
1495 if (dom->private_data) {
1496 ctx = talloc_get_type(dom->private_data,
1497 struct idmap_ldap_context);
1499 talloc_free(ctx);
1500 dom->private_data = NULL;
1503 return NT_STATUS_OK;
1506 static struct idmap_methods idmap_ldap_methods = {
1508 .init = idmap_ldap_db_init,
1509 .unixids_to_sids = idmap_ldap_unixids_to_sids,
1510 .sids_to_unixids = idmap_ldap_sids_to_unixids,
1511 .set_mapping = idmap_ldap_set_mapping,
1512 .close_fn = idmap_ldap_close
1515 static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
1517 .init = idmap_ldap_alloc_init,
1518 .allocate_id = idmap_ldap_allocate_id,
1519 .get_id_hwm = idmap_ldap_get_hwm,
1520 .set_id_hwm = idmap_ldap_set_hwm,
1521 .close_fn = idmap_ldap_alloc_close,
1522 /* .dump_data = TODO */
1525 static NTSTATUS idmap_alloc_ldap_init(void)
1527 return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1528 &idmap_ldap_alloc_methods);
1531 NTSTATUS idmap_ldap_init(void);
1532 NTSTATUS idmap_ldap_init(void)
1534 NTSTATUS ret;
1536 /* FIXME: bad hack to actually register also the alloc_ldap module
1537 * without changining configure.in */
1538 ret = idmap_alloc_ldap_init();
1539 if (! NT_STATUS_IS_OK(ret)) {
1540 return ret;
1542 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1543 &idmap_ldap_methods);