2 Unix SMB/CIFS implementation.
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/>.
29 #define DBGC_CLASS DBGC_IDMAP
36 static char *idmap_fetch_secret(const char *backend, bool alloc,
37 const char *domain, const char *identity)
43 r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
45 r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
51 strupper_m(tmp); /* make sure the key is case insensitive */
52 ret = secrets_fetch_generic(tmp, identity);
59 struct idmap_ldap_context {
60 struct smbldap_state *smbldap_state;
67 struct idmap_ldap_alloc_context {
68 struct smbldap_state *smbldap_state;
74 #define CHECK_ALLOC_DONE(mem) do { \
76 DEBUG(0, ("Out of memory!\n")); \
77 ret = NT_STATUS_NO_MEMORY; \
81 /**********************************************************************
82 IDMAP ALLOC TDB BACKEND
83 **********************************************************************/
85 static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
87 /*********************************************************************
88 ********************************************************************/
90 static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
91 struct smbldap_state *ldap_state,
92 const char *config_option,
93 struct idmap_domain *dom,
96 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
98 const char *tmp = NULL;
102 /* assume anonymous if we don't have a specified user */
104 tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
108 /* only the alloc backend can pass in a NULL dom */
109 secret = idmap_fetch_secret("ldap", True,
112 secret = idmap_fetch_secret("ldap", False,
117 DEBUG(0, ("get_credentials: Unable to fetch "
118 "auth credentials for %s in %s\n",
119 tmp, (dom==NULL)?"ALLOC":dom->name));
120 ret = NT_STATUS_ACCESS_DENIED;
123 *dn = talloc_strdup(mem_ctx, tmp);
124 CHECK_ALLOC_DONE(*dn);
126 if (!fetch_ldap_pw(&user_dn, &secret)) {
127 DEBUG(2, ("get_credentials: Failed to lookup ldap "
128 "bind creds. Using anonymous connection.\n"));
131 *dn = talloc_strdup(mem_ctx, user_dn);
132 SAFE_FREE( user_dn );
133 CHECK_ALLOC_DONE(*dn);
137 smbldap_set_creds(ldap_state, anon, *dn, secret);
147 /**********************************************************************
148 Verify the sambaUnixIdPool entry in the directory.
149 **********************************************************************/
151 static NTSTATUS verify_idpool(struct idmap_domain *dom)
155 LDAPMessage *result = NULL;
156 LDAPMod **mods = NULL;
157 const char **attr_list;
162 if ( ! idmap_alloc_ldap) {
163 return NT_STATUS_UNSUCCESSFUL;
166 ctx = talloc_new(idmap_alloc_ldap);
168 DEBUG(0, ("Out of memory!\n"));
169 return NT_STATUS_NO_MEMORY;
172 filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
173 CHECK_ALLOC_DONE(filter);
175 attr_list = get_attr_list(ctx, idpool_attr_list);
176 CHECK_ALLOC_DONE(attr_list);
178 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
179 idmap_alloc_ldap->suffix,
186 if (rc != LDAP_SUCCESS) {
187 DEBUG(1, ("Unable to verify the idpool, "
188 "cannot continue initialization!\n"));
189 return NT_STATUS_UNSUCCESSFUL;
192 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
195 ldap_msgfree(result);
198 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
199 filter, idmap_alloc_ldap->suffix));
200 ret = NT_STATUS_UNSUCCESSFUL;
203 else if (count == 0) {
204 char *uid_str, *gid_str;
206 uid_str = talloc_asprintf(ctx, "%lu",
207 (unsigned long)dom->low_id);
208 gid_str = talloc_asprintf(ctx, "%lu",
209 (unsigned long)dom->low_id);
211 smbldap_set_mod(&mods, LDAP_MOD_ADD,
212 "objectClass", LDAP_OBJ_IDPOOL);
213 smbldap_set_mod(&mods, LDAP_MOD_ADD,
214 get_attr_key2string(idpool_attr_list,
215 LDAP_ATTR_UIDNUMBER),
217 smbldap_set_mod(&mods, LDAP_MOD_ADD,
218 get_attr_key2string(idpool_attr_list,
219 LDAP_ATTR_GIDNUMBER),
222 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
223 idmap_alloc_ldap->suffix,
225 ldap_mods_free(mods, True);
227 ret = NT_STATUS_UNSUCCESSFUL;
232 ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
238 /*****************************************************************************
239 Initialise idmap database.
240 *****************************************************************************/
242 static NTSTATUS idmap_ldap_alloc_init(struct idmap_domain *dom,
245 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
248 /* Only do init if we are online */
249 if (idmap_is_offline()) {
250 return NT_STATUS_FILE_IS_OFFLINE;
253 idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
254 CHECK_ALLOC_DONE( idmap_alloc_ldap );
256 if (params && *params) {
257 /* assume location is the only parameter */
258 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
260 tmp = lp_parm_const_string(-1, "idmap alloc config",
264 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
265 ret = NT_STATUS_UNSUCCESSFUL;
269 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
271 CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
273 trim_char(idmap_alloc_ldap->url, '\"', '\"');
275 tmp = lp_parm_const_string(-1, "idmap alloc config",
276 "ldap_base_dn", NULL);
277 if ( ! tmp || ! *tmp) {
278 tmp = lp_ldap_idmap_suffix();
280 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
281 ret = NT_STATUS_UNSUCCESSFUL;
286 idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
287 CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
289 ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
290 idmap_alloc_ldap->url,
291 &idmap_alloc_ldap->smbldap_state);
292 if (!NT_STATUS_IS_OK(ret)) {
293 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
294 idmap_alloc_ldap->url));
298 ret = get_credentials( idmap_alloc_ldap,
299 idmap_alloc_ldap->smbldap_state,
300 "idmap alloc config", NULL,
301 &idmap_alloc_ldap->user_dn );
302 if ( !NT_STATUS_IS_OK(ret) ) {
303 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
304 "credentials (%s)\n", nt_errstr(ret)));
308 /* see if the idmap suffix and sub entries exists */
310 ret = verify_idpool(dom);
313 if ( !NT_STATUS_IS_OK( ret ) )
314 TALLOC_FREE( idmap_alloc_ldap );
319 /********************************
320 Allocate a new uid or gid
321 ********************************/
323 static NTSTATUS idmap_ldap_allocate_id(struct idmap_domain *dom,
327 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
328 int rc = LDAP_SERVER_DOWN;
330 LDAPMessage *result = NULL;
331 LDAPMessage *entry = NULL;
332 LDAPMod **mods = NULL;
336 const char *dn = NULL;
337 const char **attr_list;
340 /* Only do query if we are online */
341 if (idmap_is_offline()) {
342 return NT_STATUS_FILE_IS_OFFLINE;
345 if ( ! idmap_alloc_ldap) {
346 return NT_STATUS_UNSUCCESSFUL;
349 ctx = talloc_new(idmap_alloc_ldap);
351 DEBUG(0, ("Out of memory!\n"));
352 return NT_STATUS_NO_MEMORY;
359 type = get_attr_key2string(idpool_attr_list,
360 LDAP_ATTR_UIDNUMBER);
364 type = get_attr_key2string(idpool_attr_list,
365 LDAP_ATTR_GIDNUMBER);
369 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
370 return NT_STATUS_INVALID_PARAMETER;
373 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
374 CHECK_ALLOC_DONE(filter);
376 attr_list = get_attr_list(ctx, idpool_attr_list);
377 CHECK_ALLOC_DONE(attr_list);
379 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
381 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
382 idmap_alloc_ldap->suffix,
383 LDAP_SCOPE_SUBTREE, filter,
384 attr_list, 0, &result);
386 if (rc != LDAP_SUCCESS) {
387 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
391 talloc_autofree_ldapmsg(ctx, result);
393 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
396 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
400 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
403 dn = smbldap_talloc_dn(ctx,
404 idmap_alloc_ldap->smbldap_state->ldap_struct,
410 if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
411 entry, type, ctx))) {
412 DEBUG(0,("%s attribute not found\n", type));
416 DEBUG(0,("Out of memory\n"));
417 ret = NT_STATUS_NO_MEMORY;
421 xid->id = strtoul(id_str, NULL, 10);
423 /* make sure we still have room to grow */
427 if (xid->id > dom->high_id) {
428 DEBUG(0,("Cannot allocate uid above %lu!\n",
429 (unsigned long)dom->high_id));
435 if (xid->id > dom->high_id) {
436 DEBUG(0,("Cannot allocate gid above %lu!\n",
437 (unsigned long)dom->high_id));
447 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
449 DEBUG(0,("Out of memory\n"));
450 ret = NT_STATUS_NO_MEMORY;
454 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
455 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
458 DEBUG(0,("smbldap_set_mod() failed.\n"));
462 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
463 id_str, new_id_str));
465 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
467 ldap_mods_free(mods, True);
469 if (rc != LDAP_SUCCESS) {
470 DEBUG(1,("Failed to allocate new %s. "
471 "smbldap_modify() failed.\n", type));
482 /**********************************
483 Close idmap ldap alloc
484 **********************************/
486 static NTSTATUS idmap_ldap_alloc_close(void)
488 if (idmap_alloc_ldap) {
489 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
490 DEBUG(5,("The connection to the LDAP server was closed\n"));
491 /* maybe free the results here --metze */
492 TALLOC_FREE(idmap_alloc_ldap);
498 /**********************************************************************
499 IDMAP MAPPING LDAP BACKEND
500 **********************************************************************/
502 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
504 smbldap_free_struct(&ctx->smbldap_state);
505 DEBUG(5,("The connection to the LDAP server was closed\n"));
506 /* maybe free the results here --metze */
511 /********************************
512 Initialise idmap database.
513 ********************************/
515 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
519 struct idmap_ldap_context *ctx = NULL;
520 char *config_option = NULL;
521 const char *tmp = NULL;
523 /* Only do init if we are online */
524 if (idmap_is_offline()) {
525 return NT_STATUS_FILE_IS_OFFLINE;
528 ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
530 DEBUG(0, ("Out of memory!\n"));
531 return NT_STATUS_NO_MEMORY;
534 if (strequal(dom->name, "*")) {
535 /* more specific configuration can go here */
537 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
538 if ( ! config_option) {
539 DEBUG(0, ("Out of memory!\n"));
540 ret = NT_STATUS_NO_MEMORY;
545 if (params != NULL) {
546 /* assume location is the only parameter */
547 ctx->url = talloc_strdup(ctx, params);
549 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
552 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
553 ret = NT_STATUS_UNSUCCESSFUL;
557 ctx->url = talloc_strdup(ctx, tmp);
559 CHECK_ALLOC_DONE(ctx->url);
561 trim_char(ctx->url, '\"', '\"');
563 tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
564 if ( ! tmp || ! *tmp) {
565 tmp = lp_ldap_idmap_suffix();
567 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
568 ret = NT_STATUS_UNSUCCESSFUL;
573 ctx->suffix = talloc_strdup(ctx, tmp);
574 CHECK_ALLOC_DONE(ctx->suffix);
576 ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
577 &ctx->smbldap_state);
578 if (!NT_STATUS_IS_OK(ret)) {
579 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
583 ret = get_credentials( ctx, ctx->smbldap_state, config_option,
584 dom, &ctx->user_dn );
585 if ( !NT_STATUS_IS_OK(ret) ) {
586 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
587 "credentials (%s)\n", nt_errstr(ret)));
591 /* set the destructor on the context, so that resource are properly
592 freed if the contexts is released */
594 talloc_set_destructor(ctx, idmap_ldap_close_destructor);
596 dom->private_data = ctx;
598 ret = idmap_ldap_alloc_init(dom, params);
599 if (!NT_STATUS_IS_OK(ret)) {
600 DEBUG(1, ("idmap_ldap_db_init: Failed to initialize alloc "
601 "subsystem: %s\n", nt_errstr(ret)));
605 talloc_free(config_option);
614 /* max number of ids requested per batch query */
615 #define IDMAP_LDAP_MAX_IDS 30
617 /**********************************
618 lookup a set of unix ids.
619 **********************************/
621 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
622 * in maps for a match */
623 static struct id_map *find_map_by_id(struct id_map **maps,
629 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
630 if (maps[i] == NULL) { /* end of the run */
633 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
641 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
646 struct idmap_ldap_context *ctx;
647 LDAPMessage *result = NULL;
648 LDAPMessage *entry = NULL;
649 const char *uidNumber;
650 const char *gidNumber;
651 const char **attr_list;
660 /* Only do query if we are online */
661 if (idmap_is_offline()) {
662 return NT_STATUS_FILE_IS_OFFLINE;
665 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
667 memctx = talloc_new(ctx);
669 DEBUG(0, ("Out of memory!\n"));
670 return NT_STATUS_NO_MEMORY;
673 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
674 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
676 attr_list = get_attr_list(memctx, sidmap_attr_list);
679 /* if we are requested just one mapping use the simple filter */
681 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
682 LDAP_OBJ_IDMAP_ENTRY,
683 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
684 (unsigned long)ids[0]->xid.id);
685 CHECK_ALLOC_DONE(filter);
686 DEBUG(10, ("Filter: [%s]\n", filter));
688 /* multiple mappings */
692 for (i = 0; ids[i]; i++) {
693 ids[i]->status = ID_UNKNOWN;
700 filter = talloc_asprintf(memctx,
701 "(&(objectClass=%s)(|",
702 LDAP_OBJ_IDMAP_ENTRY);
703 CHECK_ALLOC_DONE(filter);
706 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
707 filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
708 (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
709 (unsigned long)ids[idx]->xid.id);
710 CHECK_ALLOC_DONE(filter);
712 filter = talloc_asprintf_append_buffer(filter, "))");
713 CHECK_ALLOC_DONE(filter);
714 DEBUG(10, ("Filter: [%s]\n", filter));
720 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
721 filter, attr_list, 0, &result);
723 if (rc != LDAP_SUCCESS) {
724 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
725 ret = NT_STATUS_UNSUCCESSFUL;
729 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
732 DEBUG(10, ("NO SIDs found\n"));
735 for (i = 0; i < count; i++) {
742 if (i == 0) { /* first entry */
743 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
745 } else { /* following ones */
746 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
750 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
755 /* first check if the SID is present */
756 sidstr = smbldap_talloc_single_attribute(
757 ctx->smbldap_state->ldap_struct,
758 entry, LDAP_ATTRIBUTE_SID, memctx);
759 if ( ! sidstr) { /* no sid, skip entry */
760 DEBUG(2, ("WARNING SID not found on entry\n"));
764 /* now try to see if it is a uid, if not try with a gid
765 * (gid is more common, but in case both uidNumber and
766 * gidNumber are returned the SID is mapped to the uid
769 tmp = smbldap_talloc_single_attribute(
770 ctx->smbldap_state->ldap_struct,
771 entry, uidNumber, memctx);
774 tmp = smbldap_talloc_single_attribute(
775 ctx->smbldap_state->ldap_struct,
776 entry, gidNumber, memctx);
778 if ( ! tmp) { /* wow very strange entry, how did it match ? */
779 DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
780 "nor gidNumber returned\n", sidstr));
785 id = strtoul(tmp, NULL, 10);
786 if (!idmap_unix_id_is_in_range(id, dom)) {
787 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
789 dom->low_id, dom->high_id));
796 map = find_map_by_id(&ids[bidx], type, id);
798 DEBUG(2, ("WARNING: couldn't match sid (%s) "
799 "with requested ids\n", sidstr));
804 if ( ! string_to_sid(map->sid, sidstr)) {
805 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
810 if (map->status == ID_MAPPED) {
811 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
812 "overwriting mapping %u -> %s with %u -> %s\n",
813 (type == ID_TYPE_UID) ? "UID" : "GID",
814 id, sid_string_dbg(map->sid), id, sidstr));
820 map->status = ID_MAPPED;
822 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
823 (unsigned long)map->xid.id, map->xid.type));
826 /* free the ldap results */
828 ldap_msgfree(result);
832 if (multi && ids[idx]) { /* still some values to map */
838 /* mark all unknwon/expired ones as unmapped */
839 for (i = 0; ids[i]; i++) {
840 if (ids[i]->status != ID_MAPPED)
841 ids[i]->status = ID_UNMAPPED;
849 /**********************************
850 lookup a set of sids.
851 **********************************/
853 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
854 * in maps for a match */
855 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
859 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
860 if (maps[i] == NULL) { /* end of the run */
863 if (sid_equal(maps[i]->sid, sid)) {
871 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
874 LDAPMessage *entry = NULL;
877 struct idmap_ldap_context *ctx;
878 LDAPMessage *result = NULL;
879 const char *uidNumber;
880 const char *gidNumber;
881 const char **attr_list;
890 /* Only do query if we are online */
891 if (idmap_is_offline()) {
892 return NT_STATUS_FILE_IS_OFFLINE;
895 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
897 memctx = talloc_new(ctx);
899 DEBUG(0, ("Out of memory!\n"));
900 return NT_STATUS_NO_MEMORY;
903 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
904 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
906 attr_list = get_attr_list(memctx, sidmap_attr_list);
909 /* if we are requested just one mapping use the simple filter */
911 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
912 LDAP_OBJ_IDMAP_ENTRY,
914 sid_string_talloc(memctx, ids[0]->sid));
915 CHECK_ALLOC_DONE(filter);
916 DEBUG(10, ("Filter: [%s]\n", filter));
918 /* multiple mappings */
922 for (i = 0; ids[i]; i++) {
923 ids[i]->status = ID_UNKNOWN;
930 filter = talloc_asprintf(memctx,
931 "(&(objectClass=%s)(|",
932 LDAP_OBJ_IDMAP_ENTRY);
933 CHECK_ALLOC_DONE(filter);
936 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
937 filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
939 sid_string_talloc(memctx,
941 CHECK_ALLOC_DONE(filter);
943 filter = talloc_asprintf_append_buffer(filter, "))");
944 CHECK_ALLOC_DONE(filter);
945 DEBUG(10, ("Filter: [%s]", filter));
951 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
952 filter, attr_list, 0, &result);
954 if (rc != LDAP_SUCCESS) {
955 DEBUG(3,("Failure looking up sids (%s)\n",
956 ldap_err2string(rc)));
957 ret = NT_STATUS_UNSUCCESSFUL;
961 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
964 DEBUG(10, ("NO SIDs found\n"));
967 for (i = 0; i < count; i++) {
975 if (i == 0) { /* first entry */
976 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
978 } else { /* following ones */
979 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
983 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
988 /* first check if the SID is present */
989 sidstr = smbldap_talloc_single_attribute(
990 ctx->smbldap_state->ldap_struct,
991 entry, LDAP_ATTRIBUTE_SID, memctx);
992 if ( ! sidstr) { /* no sid ??, skip entry */
993 DEBUG(2, ("WARNING SID not found on entry\n"));
997 if ( ! string_to_sid(&sid, sidstr)) {
998 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1003 map = find_map_by_sid(&ids[bidx], &sid);
1005 DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1007 TALLOC_FREE(sidstr);
1011 /* now try to see if it is a uid, if not try with a gid
1012 * (gid is more common, but in case both uidNumber and
1013 * gidNumber are returned the SID is mapped to the uid
1016 tmp = smbldap_talloc_single_attribute(
1017 ctx->smbldap_state->ldap_struct,
1018 entry, uidNumber, memctx);
1021 tmp = smbldap_talloc_single_attribute(
1022 ctx->smbldap_state->ldap_struct,
1023 entry, gidNumber, memctx);
1025 if ( ! tmp) { /* no ids ?? */
1026 DEBUG(5, ("no uidNumber, "
1027 "nor gidNumber attributes found\n"));
1028 TALLOC_FREE(sidstr);
1032 id = strtoul(tmp, NULL, 10);
1033 if (!idmap_unix_id_is_in_range(id, dom)) {
1034 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1036 dom->low_id, dom->high_id));
1037 TALLOC_FREE(sidstr);
1043 if (map->status == ID_MAPPED) {
1044 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1045 "overwriting mapping %s -> %u with %s -> %u\n",
1046 (type == ID_TYPE_UID) ? "UID" : "GID",
1047 sidstr, map->xid.id, sidstr, id));
1050 TALLOC_FREE(sidstr);
1053 map->xid.type = type;
1055 map->status = ID_MAPPED;
1057 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1058 (unsigned long)map->xid.id, map->xid.type));
1061 /* free the ldap results */
1063 ldap_msgfree(result);
1067 if (multi && ids[idx]) { /* still some values to map */
1073 /* mark all unknwon/expired ones as unmapped */
1074 for (i = 0; ids[i]; i++) {
1075 if (ids[i]->status != ID_MAPPED)
1076 ids[i]->status = ID_UNMAPPED;
1080 talloc_free(memctx);
1084 /**********************************
1086 **********************************/
1088 /* TODO: change this: This function cannot be called to modify a mapping,
1089 * only set a new one */
1091 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
1092 const struct id_map *map)
1096 struct idmap_ldap_context *ctx;
1097 LDAPMessage *entry = NULL;
1098 LDAPMod **mods = NULL;
1105 /* Only do query if we are online */
1106 if (idmap_is_offline()) {
1107 return NT_STATUS_FILE_IS_OFFLINE;
1110 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1112 switch(map->xid.type) {
1114 type = get_attr_key2string(sidmap_attr_list,
1115 LDAP_ATTR_UIDNUMBER);
1119 type = get_attr_key2string(sidmap_attr_list,
1120 LDAP_ATTR_GIDNUMBER);
1124 return NT_STATUS_INVALID_PARAMETER;
1127 memctx = talloc_new(ctx);
1129 DEBUG(0, ("Out of memory!\n"));
1130 return NT_STATUS_NO_MEMORY;
1133 id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1134 CHECK_ALLOC_DONE(id_str);
1136 sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
1137 CHECK_ALLOC_DONE(sid);
1139 dn = talloc_asprintf(memctx, "%s=%s,%s",
1140 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1143 CHECK_ALLOC_DONE(dn);
1145 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1146 "objectClass", LDAP_OBJ_IDMAP_ENTRY);
1148 smbldap_make_mod(ctx->smbldap_state->ldap_struct,
1149 entry, &mods, type, id_str);
1151 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1152 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1156 DEBUG(2, ("ERROR: No mods?\n"));
1157 ret = NT_STATUS_UNSUCCESSFUL;
1161 /* TODO: remove conflicting mappings! */
1163 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1165 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1167 rc = smbldap_add(ctx->smbldap_state, dn, mods);
1168 ldap_mods_free(mods, True);
1170 if (rc != LDAP_SUCCESS) {
1171 char *ld_error = NULL;
1172 ldap_get_option(ctx->smbldap_state->ldap_struct,
1173 LDAP_OPT_ERROR_STRING, &ld_error);
1174 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
1175 "mapping [%s]\n", sid,
1176 (unsigned long)map->xid.id, type));
1177 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1178 ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1180 ldap_memfree(ld_error);
1182 ret = NT_STATUS_UNSUCCESSFUL;
1186 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
1187 "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
1192 talloc_free(memctx);
1196 /**********************************
1197 Close the idmap ldap instance
1198 **********************************/
1200 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1202 struct idmap_ldap_context *ctx;
1204 if (dom->private_data) {
1205 ctx = talloc_get_type(dom->private_data,
1206 struct idmap_ldap_context);
1209 dom->private_data = NULL;
1212 return NT_STATUS_OK;
1215 static struct idmap_methods idmap_ldap_methods = {
1217 .init = idmap_ldap_db_init,
1218 .unixids_to_sids = idmap_ldap_unixids_to_sids,
1219 .sids_to_unixids = idmap_ldap_sids_to_unixids,
1220 .allocate_id = idmap_ldap_get_new_id,
1221 .close_fn = idmap_ldap_close
1224 NTSTATUS idmap_ldap_init(void);
1225 NTSTATUS idmap_ldap_init(void)
1227 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1228 &idmap_ldap_methods);