s3-winbind: Implemented samr backend function common_enum_local_groups.
[Samba/gebeck_regimport.git] / source3 / winbindd / idmap_ldap.c
blobe7928bf3f7815bb1849004b5e0753e862332e5ac
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 trim_char(idmap_alloc_ldap->url, '\"', '\"');
311 tmp = lp_parm_const_string(-1, "idmap alloc config",
312 "ldap_base_dn", NULL);
313 if ( ! tmp || ! *tmp) {
314 tmp = lp_ldap_idmap_suffix();
315 if ( ! tmp) {
316 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
317 ret = NT_STATUS_UNSUCCESSFUL;
318 goto done;
322 idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
323 CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
325 ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
326 idmap_alloc_ldap->url,
327 &idmap_alloc_ldap->smbldap_state);
328 if (!NT_STATUS_IS_OK(ret)) {
329 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
330 idmap_alloc_ldap->url));
331 goto done;
334 ret = get_credentials( idmap_alloc_ldap,
335 idmap_alloc_ldap->smbldap_state,
336 "idmap alloc config", NULL,
337 &idmap_alloc_ldap->user_dn );
338 if ( !NT_STATUS_IS_OK(ret) ) {
339 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
340 "credentials (%s)\n", nt_errstr(ret)));
341 goto done;
344 /* see if the idmap suffix and sub entries exists */
346 ret = verify_idpool();
348 done:
349 if ( !NT_STATUS_IS_OK( ret ) )
350 TALLOC_FREE( idmap_alloc_ldap );
352 return ret;
355 /********************************
356 Allocate a new uid or gid
357 ********************************/
359 static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
361 TALLOC_CTX *ctx;
362 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
363 int rc = LDAP_SERVER_DOWN;
364 int count = 0;
365 LDAPMessage *result = NULL;
366 LDAPMessage *entry = NULL;
367 LDAPMod **mods = NULL;
368 char *id_str;
369 char *new_id_str;
370 char *filter = NULL;
371 const char *dn = NULL;
372 const char **attr_list;
373 const char *type;
375 /* Only do query if we are online */
376 if (idmap_is_offline()) {
377 return NT_STATUS_FILE_IS_OFFLINE;
380 if ( ! idmap_alloc_ldap) {
381 return NT_STATUS_UNSUCCESSFUL;
384 ctx = talloc_new(idmap_alloc_ldap);
385 if ( ! ctx) {
386 DEBUG(0, ("Out of memory!\n"));
387 return NT_STATUS_NO_MEMORY;
390 /* get type */
391 switch (xid->type) {
393 case ID_TYPE_UID:
394 type = get_attr_key2string(idpool_attr_list,
395 LDAP_ATTR_UIDNUMBER);
396 break;
398 case ID_TYPE_GID:
399 type = get_attr_key2string(idpool_attr_list,
400 LDAP_ATTR_GIDNUMBER);
401 break;
403 default:
404 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
405 return NT_STATUS_INVALID_PARAMETER;
408 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
409 CHECK_ALLOC_DONE(filter);
411 attr_list = get_attr_list(ctx, idpool_attr_list);
412 CHECK_ALLOC_DONE(attr_list);
414 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
416 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
417 idmap_alloc_ldap->suffix,
418 LDAP_SCOPE_SUBTREE, filter,
419 attr_list, 0, &result);
421 if (rc != LDAP_SUCCESS) {
422 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
423 goto done;
426 talloc_autofree_ldapmsg(ctx, result);
428 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
429 result);
430 if (count != 1) {
431 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
432 goto done;
435 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
436 result);
438 dn = smbldap_talloc_dn(ctx,
439 idmap_alloc_ldap->smbldap_state->ldap_struct,
440 entry);
441 if ( ! dn) {
442 goto done;
445 if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
446 entry, type, ctx))) {
447 DEBUG(0,("%s attribute not found\n", type));
448 ret = NT_STATUS_UNSUCCESSFUL;
449 goto done;
452 xid->id = strtoul(id_str, NULL, 10);
454 /* make sure we still have room to grow */
456 switch (xid->type) {
457 case ID_TYPE_UID:
458 if (xid->id > idmap_alloc_ldap->high_uid) {
459 DEBUG(0,("Cannot allocate uid above %lu!\n",
460 (unsigned long)idmap_alloc_ldap->high_uid));
461 goto done;
463 break;
465 case ID_TYPE_GID:
466 if (xid->id > idmap_alloc_ldap->high_gid) {
467 DEBUG(0,("Cannot allocate gid above %lu!\n",
468 (unsigned long)idmap_alloc_ldap->high_uid));
469 goto done;
471 break;
473 default:
474 /* impossible */
475 goto done;
478 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
479 if ( ! new_id_str) {
480 DEBUG(0,("Out of memory\n"));
481 ret = NT_STATUS_NO_MEMORY;
482 goto done;
485 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
486 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
488 if (mods == NULL) {
489 DEBUG(0,("smbldap_set_mod() failed.\n"));
490 goto done;
493 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
494 id_str, new_id_str));
496 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
498 ldap_mods_free(mods, True);
500 if (rc != LDAP_SUCCESS) {
501 DEBUG(1,("Failed to allocate new %s. "
502 "smbldap_modify() failed.\n", type));
503 goto done;
506 ret = NT_STATUS_OK;
508 done:
509 talloc_free(ctx);
510 return ret;
513 /**********************************
514 Get current highest id.
515 **********************************/
517 static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
519 TALLOC_CTX *memctx;
520 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
521 int rc = LDAP_SERVER_DOWN;
522 int count = 0;
523 LDAPMessage *result = NULL;
524 LDAPMessage *entry = NULL;
525 char *id_str;
526 char *filter = NULL;
527 const char **attr_list;
528 const char *type;
530 /* Only do query if we are online */
531 if (idmap_is_offline()) {
532 return NT_STATUS_FILE_IS_OFFLINE;
535 if ( ! idmap_alloc_ldap) {
536 return NT_STATUS_UNSUCCESSFUL;
539 memctx = talloc_new(idmap_alloc_ldap);
540 if ( ! memctx) {
541 DEBUG(0, ("Out of memory!\n"));
542 return NT_STATUS_NO_MEMORY;
545 /* get type */
546 switch (xid->type) {
548 case ID_TYPE_UID:
549 type = get_attr_key2string(idpool_attr_list,
550 LDAP_ATTR_UIDNUMBER);
551 break;
553 case ID_TYPE_GID:
554 type = get_attr_key2string(idpool_attr_list,
555 LDAP_ATTR_GIDNUMBER);
556 break;
558 default:
559 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
560 return NT_STATUS_INVALID_PARAMETER;
563 filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
564 CHECK_ALLOC_DONE(filter);
566 attr_list = get_attr_list(memctx, idpool_attr_list);
567 CHECK_ALLOC_DONE(attr_list);
569 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
570 idmap_alloc_ldap->suffix,
571 LDAP_SCOPE_SUBTREE, filter,
572 attr_list, 0, &result);
574 if (rc != LDAP_SUCCESS) {
575 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
576 goto done;
579 talloc_autofree_ldapmsg(memctx, result);
581 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
582 result);
583 if (count != 1) {
584 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
585 goto done;
588 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
589 result);
591 id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
592 entry, type, memctx);
593 if ( ! id_str) {
594 DEBUG(0,("%s attribute not found\n", type));
595 goto done;
597 if ( ! id_str) {
598 DEBUG(0,("Out of memory\n"));
599 ret = NT_STATUS_NO_MEMORY;
600 goto done;
603 xid->id = strtoul(id_str, NULL, 10);
605 ret = NT_STATUS_OK;
606 done:
607 talloc_free(memctx);
608 return ret;
610 /**********************************
611 Set highest id.
612 **********************************/
614 static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
616 TALLOC_CTX *ctx;
617 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
618 int rc = LDAP_SERVER_DOWN;
619 int count = 0;
620 LDAPMessage *result = NULL;
621 LDAPMessage *entry = NULL;
622 LDAPMod **mods = NULL;
623 char *new_id_str;
624 char *filter = NULL;
625 const char *dn = NULL;
626 const char **attr_list;
627 const char *type;
629 /* Only do query if we are online */
630 if (idmap_is_offline()) {
631 return NT_STATUS_FILE_IS_OFFLINE;
634 if ( ! idmap_alloc_ldap) {
635 return NT_STATUS_UNSUCCESSFUL;
638 ctx = talloc_new(idmap_alloc_ldap);
639 if ( ! ctx) {
640 DEBUG(0, ("Out of memory!\n"));
641 return NT_STATUS_NO_MEMORY;
644 /* get type */
645 switch (xid->type) {
647 case ID_TYPE_UID:
648 type = get_attr_key2string(idpool_attr_list,
649 LDAP_ATTR_UIDNUMBER);
650 break;
652 case ID_TYPE_GID:
653 type = get_attr_key2string(idpool_attr_list,
654 LDAP_ATTR_GIDNUMBER);
655 break;
657 default:
658 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
659 return NT_STATUS_INVALID_PARAMETER;
662 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
663 CHECK_ALLOC_DONE(filter);
665 attr_list = get_attr_list(ctx, idpool_attr_list);
666 CHECK_ALLOC_DONE(attr_list);
668 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
669 idmap_alloc_ldap->suffix,
670 LDAP_SCOPE_SUBTREE, filter,
671 attr_list, 0, &result);
673 if (rc != LDAP_SUCCESS) {
674 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
675 goto done;
678 talloc_autofree_ldapmsg(ctx, result);
680 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
681 result);
682 if (count != 1) {
683 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
684 goto done;
687 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
688 result);
690 dn = smbldap_talloc_dn(ctx,
691 idmap_alloc_ldap->smbldap_state->ldap_struct,
692 entry);
693 if ( ! dn) {
694 goto done;
697 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
698 if ( ! new_id_str) {
699 DEBUG(0,("Out of memory\n"));
700 ret = NT_STATUS_NO_MEMORY;
701 goto done;
704 smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
706 if (mods == NULL) {
707 DEBUG(0,("smbldap_set_mod() failed.\n"));
708 goto done;
711 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
713 ldap_mods_free(mods, True);
715 if (rc != LDAP_SUCCESS) {
716 DEBUG(1,("Failed to allocate new %s. "
717 "smbldap_modify() failed.\n", type));
718 goto done;
721 ret = NT_STATUS_OK;
723 done:
724 talloc_free(ctx);
725 return ret;
728 /**********************************
729 Close idmap ldap alloc
730 **********************************/
732 static NTSTATUS idmap_ldap_alloc_close(void)
734 if (idmap_alloc_ldap) {
735 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
736 DEBUG(5,("The connection to the LDAP server was closed\n"));
737 /* maybe free the results here --metze */
738 TALLOC_FREE(idmap_alloc_ldap);
740 return NT_STATUS_OK;
744 /**********************************************************************
745 IDMAP MAPPING LDAP BACKEND
746 **********************************************************************/
748 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
750 smbldap_free_struct(&ctx->smbldap_state);
751 DEBUG(5,("The connection to the LDAP server was closed\n"));
752 /* maybe free the results here --metze */
754 return 0;
757 /********************************
758 Initialise idmap database.
759 ********************************/
761 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
762 const char *params)
764 NTSTATUS ret;
765 struct idmap_ldap_context *ctx = NULL;
766 char *config_option = NULL;
767 const char *tmp = NULL;
769 /* Only do init if we are online */
770 if (idmap_is_offline()) {
771 return NT_STATUS_FILE_IS_OFFLINE;
774 ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
775 if ( ! ctx) {
776 DEBUG(0, ("Out of memory!\n"));
777 return NT_STATUS_NO_MEMORY;
780 if (strequal(dom->name, "*")) {
781 uid_t low_uid = 0;
782 uid_t high_uid = 0;
783 gid_t low_gid = 0;
784 gid_t high_gid = 0;
786 ctx->filter_low_id = 0;
787 ctx->filter_high_id = 0;
789 if (lp_idmap_uid(&low_uid, &high_uid)) {
790 ctx->filter_low_id = low_uid;
791 ctx->filter_high_id = high_uid;
792 } else {
793 DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
796 if (lp_idmap_gid(&low_gid, &high_gid)) {
797 if ((low_gid != low_uid) || (high_gid != high_uid)) {
798 DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
799 " ranges do not agree -- building "
800 "intersection\n"));
801 ctx->filter_low_id = MAX(ctx->filter_low_id,
802 low_gid);
803 ctx->filter_high_id = MIN(ctx->filter_high_id,
804 high_gid);
806 } else {
807 DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
809 } else {
810 const char *range = NULL;
812 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
813 if ( ! config_option) {
814 DEBUG(0, ("Out of memory!\n"));
815 ret = NT_STATUS_NO_MEMORY;
816 goto done;
819 /* load ranges */
820 range = lp_parm_const_string(-1, config_option, "range", NULL);
821 if (range && range[0]) {
822 if ((sscanf(range, "%u - %u", &ctx->filter_low_id,
823 &ctx->filter_high_id) != 2))
825 DEBUG(1, ("ERROR: invalid filter range [%s]", range));
826 ctx->filter_low_id = 0;
827 ctx->filter_high_id = 0;
832 if (ctx->filter_low_id > ctx->filter_high_id) {
833 DEBUG(1, ("ERROR: invalid filter range [%u-%u]",
834 ctx->filter_low_id, ctx->filter_high_id));
835 ctx->filter_low_id = 0;
836 ctx->filter_high_id = 0;
839 if (params != NULL) {
840 /* assume location is the only parameter */
841 ctx->url = talloc_strdup(ctx, params);
842 } else {
843 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
845 if ( ! tmp) {
846 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
847 ret = NT_STATUS_UNSUCCESSFUL;
848 goto done;
851 ctx->url = talloc_strdup(ctx, tmp);
853 CHECK_ALLOC_DONE(ctx->url);
855 trim_char(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, struct 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 struct 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);