WHATSNEW: Update release notes.
[Samba.git] / source3 / winbindd / idmap_ldap.c
blobcdab0f0407b74d130737eb7e0267303b7bd2f560
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 } else {
135 *dn = talloc_strdup(mem_ctx, user_dn);
136 SAFE_FREE( user_dn );
137 CHECK_ALLOC_DONE(*dn);
141 smbldap_set_creds(ldap_state, anon, *dn, secret);
142 ret = NT_STATUS_OK;
144 done:
145 SAFE_FREE(secret);
147 return ret;
151 /**********************************************************************
152 Verify the sambaUnixIdPool entry in the directory.
153 **********************************************************************/
155 static NTSTATUS verify_idpool(void)
157 NTSTATUS ret;
158 TALLOC_CTX *ctx;
159 LDAPMessage *result = NULL;
160 LDAPMod **mods = NULL;
161 const char **attr_list;
162 char *filter;
163 int count;
164 int rc;
166 if ( ! idmap_alloc_ldap) {
167 return NT_STATUS_UNSUCCESSFUL;
170 ctx = talloc_new(idmap_alloc_ldap);
171 if ( ! ctx) {
172 DEBUG(0, ("Out of memory!\n"));
173 return NT_STATUS_NO_MEMORY;
176 filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
177 CHECK_ALLOC_DONE(filter);
179 attr_list = get_attr_list(ctx, idpool_attr_list);
180 CHECK_ALLOC_DONE(attr_list);
182 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
183 idmap_alloc_ldap->suffix,
184 LDAP_SCOPE_SUBTREE,
185 filter,
186 attr_list,
188 &result);
190 if (rc != LDAP_SUCCESS) {
191 DEBUG(1, ("Unable to verify the idpool, "
192 "cannot continue initialization!\n"));
193 return NT_STATUS_UNSUCCESSFUL;
196 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
197 result);
199 ldap_msgfree(result);
201 if ( count > 1 ) {
202 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
203 filter, idmap_alloc_ldap->suffix));
204 ret = NT_STATUS_UNSUCCESSFUL;
205 goto done;
207 else if (count == 0) {
208 char *uid_str, *gid_str;
210 uid_str = talloc_asprintf(ctx, "%lu",
211 (unsigned long)idmap_alloc_ldap->low_uid);
212 gid_str = talloc_asprintf(ctx, "%lu",
213 (unsigned long)idmap_alloc_ldap->low_gid);
215 smbldap_set_mod(&mods, LDAP_MOD_ADD,
216 "objectClass", LDAP_OBJ_IDPOOL);
217 smbldap_set_mod(&mods, LDAP_MOD_ADD,
218 get_attr_key2string(idpool_attr_list,
219 LDAP_ATTR_UIDNUMBER),
220 uid_str);
221 smbldap_set_mod(&mods, LDAP_MOD_ADD,
222 get_attr_key2string(idpool_attr_list,
223 LDAP_ATTR_GIDNUMBER),
224 gid_str);
225 if (mods) {
226 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
227 idmap_alloc_ldap->suffix,
228 mods);
229 ldap_mods_free(mods, True);
230 } else {
231 ret = NT_STATUS_UNSUCCESSFUL;
232 goto done;
236 ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
237 done:
238 talloc_free(ctx);
239 return ret;
242 /*****************************************************************************
243 Initialise idmap database.
244 *****************************************************************************/
246 static NTSTATUS idmap_ldap_alloc_init(const char *params)
248 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
249 const char *tmp;
250 uid_t low_uid = 0;
251 uid_t high_uid = 0;
252 gid_t low_gid = 0;
253 gid_t high_gid = 0;
255 /* Only do init if we are online */
256 if (idmap_is_offline()) {
257 return NT_STATUS_FILE_IS_OFFLINE;
260 idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
261 CHECK_ALLOC_DONE( idmap_alloc_ldap );
263 /* load ranges */
265 if (!lp_idmap_uid(&low_uid, &high_uid)
266 || !lp_idmap_gid(&low_gid, &high_gid)) {
267 DEBUG(1, ("idmap uid or idmap gid missing\n"));
268 ret = NT_STATUS_UNSUCCESSFUL;
269 goto done;
272 idmap_alloc_ldap->low_uid = low_uid;
273 idmap_alloc_ldap->high_uid = high_uid;
274 idmap_alloc_ldap->low_gid = low_gid;
275 idmap_alloc_ldap->high_gid= high_gid;
277 if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) {
278 DEBUG(1, ("idmap uid range invalid\n"));
279 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
280 ret = NT_STATUS_UNSUCCESSFUL;
281 goto done;
284 if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) {
285 DEBUG(1, ("idmap gid range invalid\n"));
286 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
287 ret = NT_STATUS_UNSUCCESSFUL;
288 goto done;
291 if (params && *params) {
292 /* assume location is the only parameter */
293 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
294 } else {
295 tmp = lp_parm_const_string(-1, "idmap alloc config",
296 "ldap_url", NULL);
298 if ( ! tmp) {
299 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
300 ret = NT_STATUS_UNSUCCESSFUL;
301 goto done;
304 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
306 CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
308 trim_char(idmap_alloc_ldap->url, '\"', '\"');
310 tmp = lp_parm_const_string(-1, "idmap alloc config",
311 "ldap_base_dn", NULL);
312 if ( ! tmp || ! *tmp) {
313 tmp = lp_ldap_idmap_suffix();
314 if ( ! tmp) {
315 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
316 ret = NT_STATUS_UNSUCCESSFUL;
317 goto done;
321 idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
322 CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
324 ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
325 idmap_alloc_ldap->url,
326 &idmap_alloc_ldap->smbldap_state);
327 if (!NT_STATUS_IS_OK(ret)) {
328 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
329 idmap_alloc_ldap->url));
330 goto done;
333 ret = get_credentials( idmap_alloc_ldap,
334 idmap_alloc_ldap->smbldap_state,
335 "idmap alloc config", NULL,
336 &idmap_alloc_ldap->user_dn );
337 if ( !NT_STATUS_IS_OK(ret) ) {
338 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
339 "credentials (%s)\n", nt_errstr(ret)));
340 goto done;
343 /* see if the idmap suffix and sub entries exists */
345 ret = verify_idpool();
347 done:
348 if ( !NT_STATUS_IS_OK( ret ) )
349 TALLOC_FREE( idmap_alloc_ldap );
351 return ret;
354 /********************************
355 Allocate a new uid or gid
356 ********************************/
358 static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
360 TALLOC_CTX *ctx;
361 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
362 int rc = LDAP_SERVER_DOWN;
363 int count = 0;
364 LDAPMessage *result = NULL;
365 LDAPMessage *entry = NULL;
366 LDAPMod **mods = NULL;
367 char *id_str;
368 char *new_id_str;
369 char *filter = NULL;
370 const char *dn = NULL;
371 const char **attr_list;
372 const char *type;
374 /* Only do query if we are online */
375 if (idmap_is_offline()) {
376 return NT_STATUS_FILE_IS_OFFLINE;
379 if ( ! idmap_alloc_ldap) {
380 return NT_STATUS_UNSUCCESSFUL;
383 ctx = talloc_new(idmap_alloc_ldap);
384 if ( ! ctx) {
385 DEBUG(0, ("Out of memory!\n"));
386 return NT_STATUS_NO_MEMORY;
389 /* get type */
390 switch (xid->type) {
392 case ID_TYPE_UID:
393 type = get_attr_key2string(idpool_attr_list,
394 LDAP_ATTR_UIDNUMBER);
395 break;
397 case ID_TYPE_GID:
398 type = get_attr_key2string(idpool_attr_list,
399 LDAP_ATTR_GIDNUMBER);
400 break;
402 default:
403 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
404 return NT_STATUS_INVALID_PARAMETER;
407 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
408 CHECK_ALLOC_DONE(filter);
410 attr_list = get_attr_list(ctx, idpool_attr_list);
411 CHECK_ALLOC_DONE(attr_list);
413 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
415 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
416 idmap_alloc_ldap->suffix,
417 LDAP_SCOPE_SUBTREE, filter,
418 attr_list, 0, &result);
420 if (rc != LDAP_SUCCESS) {
421 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
422 goto done;
425 talloc_autofree_ldapmsg(ctx, result);
427 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
428 result);
429 if (count != 1) {
430 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
431 goto done;
434 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
435 result);
437 dn = smbldap_talloc_dn(ctx,
438 idmap_alloc_ldap->smbldap_state->ldap_struct,
439 entry);
440 if ( ! dn) {
441 goto done;
444 if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
445 entry, type, ctx))) {
446 DEBUG(0,("%s attribute not found\n", type));
447 goto done;
449 if ( ! id_str) {
450 DEBUG(0,("Out of memory\n"));
451 ret = NT_STATUS_NO_MEMORY;
452 goto done;
455 xid->id = strtoul(id_str, NULL, 10);
457 /* make sure we still have room to grow */
459 switch (xid->type) {
460 case ID_TYPE_UID:
461 if (xid->id > idmap_alloc_ldap->high_uid) {
462 DEBUG(0,("Cannot allocate uid above %lu!\n",
463 (unsigned long)idmap_alloc_ldap->high_uid));
464 goto done;
466 break;
468 case ID_TYPE_GID:
469 if (xid->id > idmap_alloc_ldap->high_gid) {
470 DEBUG(0,("Cannot allocate gid above %lu!\n",
471 (unsigned long)idmap_alloc_ldap->high_uid));
472 goto done;
474 break;
476 default:
477 /* impossible */
478 goto done;
481 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
482 if ( ! new_id_str) {
483 DEBUG(0,("Out of memory\n"));
484 ret = NT_STATUS_NO_MEMORY;
485 goto done;
488 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
489 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
491 if (mods == NULL) {
492 DEBUG(0,("smbldap_set_mod() failed.\n"));
493 goto done;
496 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
497 id_str, new_id_str));
499 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
501 ldap_mods_free(mods, True);
503 if (rc != LDAP_SUCCESS) {
504 DEBUG(1,("Failed to allocate new %s. "
505 "smbldap_modify() failed.\n", type));
506 goto done;
509 ret = NT_STATUS_OK;
511 done:
512 talloc_free(ctx);
513 return ret;
516 /**********************************
517 Get current highest id.
518 **********************************/
520 static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
522 TALLOC_CTX *memctx;
523 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
524 int rc = LDAP_SERVER_DOWN;
525 int count = 0;
526 LDAPMessage *result = NULL;
527 LDAPMessage *entry = NULL;
528 char *id_str;
529 char *filter = NULL;
530 const char **attr_list;
531 const char *type;
533 /* Only do query if we are online */
534 if (idmap_is_offline()) {
535 return NT_STATUS_FILE_IS_OFFLINE;
538 if ( ! idmap_alloc_ldap) {
539 return NT_STATUS_UNSUCCESSFUL;
542 memctx = talloc_new(idmap_alloc_ldap);
543 if ( ! memctx) {
544 DEBUG(0, ("Out of memory!\n"));
545 return NT_STATUS_NO_MEMORY;
548 /* get type */
549 switch (xid->type) {
551 case ID_TYPE_UID:
552 type = get_attr_key2string(idpool_attr_list,
553 LDAP_ATTR_UIDNUMBER);
554 break;
556 case ID_TYPE_GID:
557 type = get_attr_key2string(idpool_attr_list,
558 LDAP_ATTR_GIDNUMBER);
559 break;
561 default:
562 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
563 return NT_STATUS_INVALID_PARAMETER;
566 filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
567 CHECK_ALLOC_DONE(filter);
569 attr_list = get_attr_list(memctx, idpool_attr_list);
570 CHECK_ALLOC_DONE(attr_list);
572 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
573 idmap_alloc_ldap->suffix,
574 LDAP_SCOPE_SUBTREE, filter,
575 attr_list, 0, &result);
577 if (rc != LDAP_SUCCESS) {
578 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
579 goto done;
582 talloc_autofree_ldapmsg(memctx, result);
584 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
585 result);
586 if (count != 1) {
587 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
588 goto done;
591 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
592 result);
594 id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
595 entry, type, memctx);
596 if ( ! id_str) {
597 DEBUG(0,("%s attribute not found\n", type));
598 goto done;
600 if ( ! id_str) {
601 DEBUG(0,("Out of memory\n"));
602 ret = NT_STATUS_NO_MEMORY;
603 goto done;
606 xid->id = strtoul(id_str, NULL, 10);
608 ret = NT_STATUS_OK;
609 done:
610 talloc_free(memctx);
611 return ret;
613 /**********************************
614 Set highest id.
615 **********************************/
617 static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
619 TALLOC_CTX *ctx;
620 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
621 int rc = LDAP_SERVER_DOWN;
622 int count = 0;
623 LDAPMessage *result = NULL;
624 LDAPMessage *entry = NULL;
625 LDAPMod **mods = NULL;
626 char *new_id_str;
627 char *filter = NULL;
628 const char *dn = NULL;
629 const char **attr_list;
630 const char *type;
632 /* Only do query if we are online */
633 if (idmap_is_offline()) {
634 return NT_STATUS_FILE_IS_OFFLINE;
637 if ( ! idmap_alloc_ldap) {
638 return NT_STATUS_UNSUCCESSFUL;
641 ctx = talloc_new(idmap_alloc_ldap);
642 if ( ! ctx) {
643 DEBUG(0, ("Out of memory!\n"));
644 return NT_STATUS_NO_MEMORY;
647 /* get type */
648 switch (xid->type) {
650 case ID_TYPE_UID:
651 type = get_attr_key2string(idpool_attr_list,
652 LDAP_ATTR_UIDNUMBER);
653 break;
655 case ID_TYPE_GID:
656 type = get_attr_key2string(idpool_attr_list,
657 LDAP_ATTR_GIDNUMBER);
658 break;
660 default:
661 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
662 return NT_STATUS_INVALID_PARAMETER;
665 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
666 CHECK_ALLOC_DONE(filter);
668 attr_list = get_attr_list(ctx, idpool_attr_list);
669 CHECK_ALLOC_DONE(attr_list);
671 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
672 idmap_alloc_ldap->suffix,
673 LDAP_SCOPE_SUBTREE, filter,
674 attr_list, 0, &result);
676 if (rc != LDAP_SUCCESS) {
677 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
678 goto done;
681 talloc_autofree_ldapmsg(ctx, result);
683 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
684 result);
685 if (count != 1) {
686 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
687 goto done;
690 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
691 result);
693 dn = smbldap_talloc_dn(ctx,
694 idmap_alloc_ldap->smbldap_state->ldap_struct,
695 entry);
696 if ( ! dn) {
697 goto done;
700 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
701 if ( ! new_id_str) {
702 DEBUG(0,("Out of memory\n"));
703 ret = NT_STATUS_NO_MEMORY;
704 goto done;
707 smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
709 if (mods == NULL) {
710 DEBUG(0,("smbldap_set_mod() failed.\n"));
711 goto done;
714 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
716 ldap_mods_free(mods, True);
718 if (rc != LDAP_SUCCESS) {
719 DEBUG(1,("Failed to allocate new %s. "
720 "smbldap_modify() failed.\n", type));
721 goto done;
724 ret = NT_STATUS_OK;
726 done:
727 talloc_free(ctx);
728 return ret;
731 /**********************************
732 Close idmap ldap alloc
733 **********************************/
735 static NTSTATUS idmap_ldap_alloc_close(void)
737 if (idmap_alloc_ldap) {
738 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
739 DEBUG(5,("The connection to the LDAP server was closed\n"));
740 /* maybe free the results here --metze */
741 TALLOC_FREE(idmap_alloc_ldap);
743 return NT_STATUS_OK;
747 /**********************************************************************
748 IDMAP MAPPING LDAP BACKEND
749 **********************************************************************/
751 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
753 smbldap_free_struct(&ctx->smbldap_state);
754 DEBUG(5,("The connection to the LDAP server was closed\n"));
755 /* maybe free the results here --metze */
757 return 0;
760 /********************************
761 Initialise idmap database.
762 ********************************/
764 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
765 const char *params)
767 NTSTATUS ret;
768 struct idmap_ldap_context *ctx = NULL;
769 char *config_option = NULL;
770 const char *tmp = NULL;
772 /* Only do init if we are online */
773 if (idmap_is_offline()) {
774 return NT_STATUS_FILE_IS_OFFLINE;
777 ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
778 if ( ! ctx) {
779 DEBUG(0, ("Out of memory!\n"));
780 return NT_STATUS_NO_MEMORY;
783 if (strequal(dom->name, "*")) {
784 uid_t low_uid = 0;
785 uid_t high_uid = 0;
786 gid_t low_gid = 0;
787 gid_t high_gid = 0;
789 ctx->filter_low_id = 0;
790 ctx->filter_high_id = 0;
792 if (lp_idmap_uid(&low_uid, &high_uid)) {
793 ctx->filter_low_id = low_uid;
794 ctx->filter_high_id = high_uid;
795 } else {
796 DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
799 if (lp_idmap_gid(&low_gid, &high_gid)) {
800 if ((low_gid != low_uid) || (high_gid != high_uid)) {
801 DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
802 " ranges do not agree -- building "
803 "intersection\n"));
804 ctx->filter_low_id = MAX(ctx->filter_low_id,
805 low_gid);
806 ctx->filter_high_id = MIN(ctx->filter_high_id,
807 high_gid);
809 } else {
810 DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
812 } else {
813 const char *range = NULL;
815 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
816 if ( ! config_option) {
817 DEBUG(0, ("Out of memory!\n"));
818 ret = NT_STATUS_NO_MEMORY;
819 goto done;
822 /* load ranges */
823 range = lp_parm_const_string(-1, config_option, "range", NULL);
824 if (range && range[0]) {
825 if ((sscanf(range, "%u - %u", &ctx->filter_low_id,
826 &ctx->filter_high_id) != 2))
828 DEBUG(1, ("ERROR: invalid filter range [%s]", range));
829 ctx->filter_low_id = 0;
830 ctx->filter_high_id = 0;
835 if (ctx->filter_low_id > ctx->filter_high_id) {
836 DEBUG(1, ("ERROR: invalid filter range [%u-%u]",
837 ctx->filter_low_id, ctx->filter_high_id));
838 ctx->filter_low_id = 0;
839 ctx->filter_high_id = 0;
842 if (params != NULL) {
843 /* assume location is the only parameter */
844 ctx->url = talloc_strdup(ctx, params);
845 } else {
846 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
848 if ( ! tmp) {
849 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
850 ret = NT_STATUS_UNSUCCESSFUL;
851 goto done;
854 ctx->url = talloc_strdup(ctx, tmp);
856 CHECK_ALLOC_DONE(ctx->url);
858 trim_char(ctx->url, '\"', '\"');
860 tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
861 if ( ! tmp || ! *tmp) {
862 tmp = lp_ldap_idmap_suffix();
863 if ( ! tmp) {
864 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
865 ret = NT_STATUS_UNSUCCESSFUL;
866 goto done;
870 ctx->suffix = talloc_strdup(ctx, tmp);
871 CHECK_ALLOC_DONE(ctx->suffix);
873 ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
874 &ctx->smbldap_state);
875 if (!NT_STATUS_IS_OK(ret)) {
876 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
877 goto done;
880 ret = get_credentials( ctx, ctx->smbldap_state, config_option,
881 dom, &ctx->user_dn );
882 if ( !NT_STATUS_IS_OK(ret) ) {
883 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
884 "credentials (%s)\n", nt_errstr(ret)));
885 goto done;
888 /* set the destructor on the context, so that resource are properly
889 freed if the contexts is released */
891 talloc_set_destructor(ctx, idmap_ldap_close_destructor);
893 dom->private_data = ctx;
895 talloc_free(config_option);
896 return NT_STATUS_OK;
898 /*failed */
899 done:
900 talloc_free(ctx);
901 return ret;
904 /* max number of ids requested per batch query */
905 #define IDMAP_LDAP_MAX_IDS 30
907 /**********************************
908 lookup a set of unix ids.
909 **********************************/
911 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
912 * in maps for a match */
913 static struct id_map *find_map_by_id(struct id_map **maps,
914 enum id_type type,
915 uint32_t id)
917 int i;
919 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
920 if (maps[i] == NULL) { /* end of the run */
921 return NULL;
923 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
924 return maps[i];
928 return NULL;
931 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
932 struct id_map **ids)
934 NTSTATUS ret;
935 TALLOC_CTX *memctx;
936 struct idmap_ldap_context *ctx;
937 LDAPMessage *result = NULL;
938 LDAPMessage *entry = NULL;
939 const char *uidNumber;
940 const char *gidNumber;
941 const char **attr_list;
942 char *filter = NULL;
943 bool multi = False;
944 int idx = 0;
945 int bidx = 0;
946 int count;
947 int rc;
948 int i;
950 /* Only do query if we are online */
951 if (idmap_is_offline()) {
952 return NT_STATUS_FILE_IS_OFFLINE;
955 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
957 memctx = talloc_new(ctx);
958 if ( ! memctx) {
959 DEBUG(0, ("Out of memory!\n"));
960 return NT_STATUS_NO_MEMORY;
963 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
964 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
966 attr_list = get_attr_list(memctx, sidmap_attr_list);
968 if ( ! ids[1]) {
969 /* if we are requested just one mapping use the simple filter */
971 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
972 LDAP_OBJ_IDMAP_ENTRY,
973 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
974 (unsigned long)ids[0]->xid.id);
975 CHECK_ALLOC_DONE(filter);
976 DEBUG(10, ("Filter: [%s]\n", filter));
977 } else {
978 /* multiple mappings */
979 multi = True;
982 for (i = 0; ids[i]; i++) {
983 ids[i]->status = ID_UNKNOWN;
986 again:
987 if (multi) {
989 talloc_free(filter);
990 filter = talloc_asprintf(memctx,
991 "(&(objectClass=%s)(|",
992 LDAP_OBJ_IDMAP_ENTRY);
993 CHECK_ALLOC_DONE(filter);
995 bidx = idx;
996 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
997 filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
998 (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
999 (unsigned long)ids[idx]->xid.id);
1000 CHECK_ALLOC_DONE(filter);
1002 filter = talloc_asprintf_append_buffer(filter, "))");
1003 CHECK_ALLOC_DONE(filter);
1004 DEBUG(10, ("Filter: [%s]\n", filter));
1005 } else {
1006 bidx = 0;
1007 idx = 1;
1010 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1011 filter, attr_list, 0, &result);
1013 if (rc != LDAP_SUCCESS) {
1014 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
1015 ret = NT_STATUS_UNSUCCESSFUL;
1016 goto done;
1019 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1021 if (count == 0) {
1022 DEBUG(10, ("NO SIDs found\n"));
1025 for (i = 0; i < count; i++) {
1026 char *sidstr = NULL;
1027 char *tmp = NULL;
1028 enum id_type type;
1029 struct id_map *map;
1030 uint32_t id;
1032 if (i == 0) { /* first entry */
1033 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1034 result);
1035 } else { /* following ones */
1036 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1037 entry);
1039 if ( ! entry) {
1040 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1041 "from results\n"));
1042 break;
1045 /* first check if the SID is present */
1046 sidstr = smbldap_talloc_single_attribute(
1047 ctx->smbldap_state->ldap_struct,
1048 entry, LDAP_ATTRIBUTE_SID, memctx);
1049 if ( ! sidstr) { /* no sid, skip entry */
1050 DEBUG(2, ("WARNING SID not found on entry\n"));
1051 continue;
1054 /* now try to see if it is a uid, if not try with a gid
1055 * (gid is more common, but in case both uidNumber and
1056 * gidNumber are returned the SID is mapped to the uid
1057 *not the gid) */
1058 type = ID_TYPE_UID;
1059 tmp = smbldap_talloc_single_attribute(
1060 ctx->smbldap_state->ldap_struct,
1061 entry, uidNumber, memctx);
1062 if ( ! tmp) {
1063 type = ID_TYPE_GID;
1064 tmp = smbldap_talloc_single_attribute(
1065 ctx->smbldap_state->ldap_struct,
1066 entry, gidNumber, memctx);
1068 if ( ! tmp) { /* wow very strange entry, how did it match ? */
1069 DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
1070 "nor gidNumber returned\n", sidstr));
1071 TALLOC_FREE(sidstr);
1072 continue;
1075 id = strtoul(tmp, NULL, 10);
1076 if ((id == 0) ||
1077 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1078 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1079 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1080 "Filtered!\n", id,
1081 ctx->filter_low_id, ctx->filter_high_id));
1082 TALLOC_FREE(sidstr);
1083 TALLOC_FREE(tmp);
1084 continue;
1086 TALLOC_FREE(tmp);
1088 map = find_map_by_id(&ids[bidx], type, id);
1089 if (!map) {
1090 DEBUG(2, ("WARNING: couldn't match sid (%s) "
1091 "with requested ids\n", sidstr));
1092 TALLOC_FREE(sidstr);
1093 continue;
1096 if ( ! string_to_sid(map->sid, sidstr)) {
1097 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1098 TALLOC_FREE(sidstr);
1099 continue;
1102 if (map->status == ID_MAPPED) {
1103 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1104 "overwriting mapping %u -> %s with %u -> %s\n",
1105 (type == ID_TYPE_UID) ? "UID" : "GID",
1106 id, sid_string_dbg(map->sid), id, sidstr));
1109 TALLOC_FREE(sidstr);
1111 /* mapped */
1112 map->status = ID_MAPPED;
1114 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1115 (unsigned long)map->xid.id, map->xid.type));
1118 /* free the ldap results */
1119 if (result) {
1120 ldap_msgfree(result);
1121 result = NULL;
1124 if (multi && ids[idx]) { /* still some values to map */
1125 goto again;
1128 ret = NT_STATUS_OK;
1130 /* mark all unknwon/expired ones as unmapped */
1131 for (i = 0; ids[i]; i++) {
1132 if (ids[i]->status != ID_MAPPED)
1133 ids[i]->status = ID_UNMAPPED;
1136 done:
1137 talloc_free(memctx);
1138 return ret;
1141 /**********************************
1142 lookup a set of sids.
1143 **********************************/
1145 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
1146 * in maps for a match */
1147 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
1149 int i;
1151 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
1152 if (maps[i] == NULL) { /* end of the run */
1153 return NULL;
1155 if (sid_equal(maps[i]->sid, sid)) {
1156 return maps[i];
1160 return NULL;
1163 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
1164 struct id_map **ids)
1166 LDAPMessage *entry = NULL;
1167 NTSTATUS ret;
1168 TALLOC_CTX *memctx;
1169 struct idmap_ldap_context *ctx;
1170 LDAPMessage *result = NULL;
1171 const char *uidNumber;
1172 const char *gidNumber;
1173 const char **attr_list;
1174 char *filter = NULL;
1175 bool multi = False;
1176 int idx = 0;
1177 int bidx = 0;
1178 int count;
1179 int rc;
1180 int i;
1182 /* Only do query if we are online */
1183 if (idmap_is_offline()) {
1184 return NT_STATUS_FILE_IS_OFFLINE;
1187 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1189 memctx = talloc_new(ctx);
1190 if ( ! memctx) {
1191 DEBUG(0, ("Out of memory!\n"));
1192 return NT_STATUS_NO_MEMORY;
1195 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
1196 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
1198 attr_list = get_attr_list(memctx, sidmap_attr_list);
1200 if ( ! ids[1]) {
1201 /* if we are requested just one mapping use the simple filter */
1203 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
1204 LDAP_OBJ_IDMAP_ENTRY,
1205 LDAP_ATTRIBUTE_SID,
1206 sid_string_talloc(memctx, ids[0]->sid));
1207 CHECK_ALLOC_DONE(filter);
1208 DEBUG(10, ("Filter: [%s]\n", filter));
1209 } else {
1210 /* multiple mappings */
1211 multi = True;
1214 for (i = 0; ids[i]; i++) {
1215 ids[i]->status = ID_UNKNOWN;
1218 again:
1219 if (multi) {
1221 TALLOC_FREE(filter);
1222 filter = talloc_asprintf(memctx,
1223 "(&(objectClass=%s)(|",
1224 LDAP_OBJ_IDMAP_ENTRY);
1225 CHECK_ALLOC_DONE(filter);
1227 bidx = idx;
1228 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
1229 filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
1230 LDAP_ATTRIBUTE_SID,
1231 sid_string_talloc(memctx,
1232 ids[idx]->sid));
1233 CHECK_ALLOC_DONE(filter);
1235 filter = talloc_asprintf_append_buffer(filter, "))");
1236 CHECK_ALLOC_DONE(filter);
1237 DEBUG(10, ("Filter: [%s]", filter));
1238 } else {
1239 bidx = 0;
1240 idx = 1;
1243 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1244 filter, attr_list, 0, &result);
1246 if (rc != LDAP_SUCCESS) {
1247 DEBUG(3,("Failure looking up sids (%s)\n",
1248 ldap_err2string(rc)));
1249 ret = NT_STATUS_UNSUCCESSFUL;
1250 goto done;
1253 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1255 if (count == 0) {
1256 DEBUG(10, ("NO SIDs found\n"));
1259 for (i = 0; i < count; i++) {
1260 char *sidstr = NULL;
1261 char *tmp = NULL;
1262 enum id_type type;
1263 struct id_map *map;
1264 DOM_SID sid;
1265 uint32_t id;
1267 if (i == 0) { /* first entry */
1268 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1269 result);
1270 } else { /* following ones */
1271 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1272 entry);
1274 if ( ! entry) {
1275 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1276 "from results\n"));
1277 break;
1280 /* first check if the SID is present */
1281 sidstr = smbldap_talloc_single_attribute(
1282 ctx->smbldap_state->ldap_struct,
1283 entry, LDAP_ATTRIBUTE_SID, memctx);
1284 if ( ! sidstr) { /* no sid ??, skip entry */
1285 DEBUG(2, ("WARNING SID not found on entry\n"));
1286 continue;
1289 if ( ! string_to_sid(&sid, sidstr)) {
1290 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1291 TALLOC_FREE(sidstr);
1292 continue;
1295 map = find_map_by_sid(&ids[bidx], &sid);
1296 if (!map) {
1297 DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1298 "in ids", sidstr));
1299 TALLOC_FREE(sidstr);
1300 continue;
1303 /* now try to see if it is a uid, if not try with a gid
1304 * (gid is more common, but in case both uidNumber and
1305 * gidNumber are returned the SID is mapped to the uid
1306 * not the gid) */
1307 type = ID_TYPE_UID;
1308 tmp = smbldap_talloc_single_attribute(
1309 ctx->smbldap_state->ldap_struct,
1310 entry, uidNumber, memctx);
1311 if ( ! tmp) {
1312 type = ID_TYPE_GID;
1313 tmp = smbldap_talloc_single_attribute(
1314 ctx->smbldap_state->ldap_struct,
1315 entry, gidNumber, memctx);
1317 if ( ! tmp) { /* no ids ?? */
1318 DEBUG(5, ("no uidNumber, "
1319 "nor gidNumber attributes found\n"));
1320 TALLOC_FREE(sidstr);
1321 continue;
1324 id = strtoul(tmp, NULL, 10);
1325 if ((id == 0) ||
1326 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1327 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1328 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1329 "Filtered!\n", id,
1330 ctx->filter_low_id, ctx->filter_high_id));
1331 TALLOC_FREE(sidstr);
1332 TALLOC_FREE(tmp);
1333 continue;
1335 TALLOC_FREE(tmp);
1337 if (map->status == ID_MAPPED) {
1338 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1339 "overwriting mapping %s -> %u with %s -> %u\n",
1340 (type == ID_TYPE_UID) ? "UID" : "GID",
1341 sidstr, map->xid.id, sidstr, id));
1344 TALLOC_FREE(sidstr);
1346 /* mapped */
1347 map->xid.type = type;
1348 map->xid.id = id;
1349 map->status = ID_MAPPED;
1351 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1352 (unsigned long)map->xid.id, map->xid.type));
1355 /* free the ldap results */
1356 if (result) {
1357 ldap_msgfree(result);
1358 result = NULL;
1361 if (multi && ids[idx]) { /* still some values to map */
1362 goto again;
1365 ret = NT_STATUS_OK;
1367 /* mark all unknwon/expired ones as unmapped */
1368 for (i = 0; ids[i]; i++) {
1369 if (ids[i]->status != ID_MAPPED)
1370 ids[i]->status = ID_UNMAPPED;
1373 done:
1374 talloc_free(memctx);
1375 return ret;
1378 /**********************************
1379 set a mapping.
1380 **********************************/
1382 /* TODO: change this: This function cannot be called to modify a mapping,
1383 * only set a new one */
1385 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
1386 const struct id_map *map)
1388 NTSTATUS ret;
1389 TALLOC_CTX *memctx;
1390 struct idmap_ldap_context *ctx;
1391 LDAPMessage *entry = NULL;
1392 LDAPMod **mods = NULL;
1393 const char *type;
1394 char *id_str;
1395 char *sid;
1396 char *dn;
1397 int rc = -1;
1399 /* Only do query if we are online */
1400 if (idmap_is_offline()) {
1401 return NT_STATUS_FILE_IS_OFFLINE;
1404 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1406 switch(map->xid.type) {
1407 case ID_TYPE_UID:
1408 type = get_attr_key2string(sidmap_attr_list,
1409 LDAP_ATTR_UIDNUMBER);
1410 break;
1412 case ID_TYPE_GID:
1413 type = get_attr_key2string(sidmap_attr_list,
1414 LDAP_ATTR_GIDNUMBER);
1415 break;
1417 default:
1418 return NT_STATUS_INVALID_PARAMETER;
1421 memctx = talloc_new(ctx);
1422 if ( ! memctx) {
1423 DEBUG(0, ("Out of memory!\n"));
1424 return NT_STATUS_NO_MEMORY;
1427 id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1428 CHECK_ALLOC_DONE(id_str);
1430 sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
1431 CHECK_ALLOC_DONE(sid);
1433 dn = talloc_asprintf(memctx, "%s=%s,%s",
1434 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1435 sid,
1436 ctx->suffix);
1437 CHECK_ALLOC_DONE(dn);
1439 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1440 "objectClass", LDAP_OBJ_IDMAP_ENTRY);
1442 smbldap_make_mod(ctx->smbldap_state->ldap_struct,
1443 entry, &mods, type, id_str);
1445 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1446 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1447 sid);
1449 if ( ! mods) {
1450 DEBUG(2, ("ERROR: No mods?\n"));
1451 ret = NT_STATUS_UNSUCCESSFUL;
1452 goto done;
1455 /* TODO: remove conflicting mappings! */
1457 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1459 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1461 rc = smbldap_add(ctx->smbldap_state, dn, mods);
1462 ldap_mods_free(mods, True);
1464 if (rc != LDAP_SUCCESS) {
1465 char *ld_error = NULL;
1466 ldap_get_option(ctx->smbldap_state->ldap_struct,
1467 LDAP_OPT_ERROR_STRING, &ld_error);
1468 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
1469 "mapping [%s]\n", sid,
1470 (unsigned long)map->xid.id, type));
1471 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1472 ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1473 if (ld_error) {
1474 ldap_memfree(ld_error);
1476 ret = NT_STATUS_UNSUCCESSFUL;
1477 goto done;
1480 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
1481 "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
1483 ret = NT_STATUS_OK;
1485 done:
1486 talloc_free(memctx);
1487 return ret;
1490 /**********************************
1491 Close the idmap ldap instance
1492 **********************************/
1494 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1496 struct idmap_ldap_context *ctx;
1498 if (dom->private_data) {
1499 ctx = talloc_get_type(dom->private_data,
1500 struct idmap_ldap_context);
1502 talloc_free(ctx);
1503 dom->private_data = NULL;
1506 return NT_STATUS_OK;
1509 static struct idmap_methods idmap_ldap_methods = {
1511 .init = idmap_ldap_db_init,
1512 .unixids_to_sids = idmap_ldap_unixids_to_sids,
1513 .sids_to_unixids = idmap_ldap_sids_to_unixids,
1514 .set_mapping = idmap_ldap_set_mapping,
1515 .close_fn = idmap_ldap_close
1518 static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
1520 .init = idmap_ldap_alloc_init,
1521 .allocate_id = idmap_ldap_allocate_id,
1522 .get_id_hwm = idmap_ldap_get_hwm,
1523 .set_id_hwm = idmap_ldap_set_hwm,
1524 .close_fn = idmap_ldap_alloc_close,
1525 /* .dump_data = TODO */
1528 static NTSTATUS idmap_alloc_ldap_init(void)
1530 return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1531 &idmap_ldap_alloc_methods);
1534 NTSTATUS idmap_ldap_init(void);
1535 NTSTATUS idmap_ldap_init(void)
1537 NTSTATUS ret;
1539 /* FIXME: bad hack to actually register also the alloc_ldap module
1540 * without changining configure.in */
1541 ret = idmap_alloc_ldap_init();
1542 if (! NT_STATUS_IS_OK(ret)) {
1543 return ret;
1545 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1546 &idmap_ldap_methods);