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
10 Copyright (C) Michael Adam 2010
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 #include "../libcli/security/security.h"
34 #define DBGC_CLASS DBGC_IDMAP
41 static char *idmap_fetch_secret(const char *backend, bool alloc,
42 const char *domain, const char *identity)
48 r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
50 r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
56 strupper_m(tmp); /* make sure the key is case insensitive */
57 ret = secrets_fetch_generic(tmp, identity);
64 struct idmap_ldap_alloc_context {
65 struct smbldap_state *smbldap_state;
71 struct idmap_ldap_context {
72 struct smbldap_state *smbldap_state;
77 struct idmap_ldap_alloc_context *alloc;
78 struct idmap_rw_ops *rw_ops;
81 #define CHECK_ALLOC_DONE(mem) do { \
83 DEBUG(0, ("Out of memory!\n")); \
84 ret = NT_STATUS_NO_MEMORY; \
88 /**********************************************************************
89 IDMAP ALLOC TDB BACKEND
90 **********************************************************************/
92 /*********************************************************************
93 ********************************************************************/
95 static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
96 struct smbldap_state *ldap_state,
97 const char *config_option,
98 struct idmap_domain *dom,
101 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
103 const char *tmp = NULL;
104 char *user_dn = NULL;
107 /* assume anonymous if we don't have a specified user */
109 tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
113 /* only the alloc backend can pass in a NULL dom */
114 secret = idmap_fetch_secret("ldap", True,
117 secret = idmap_fetch_secret("ldap", False,
122 DEBUG(0, ("get_credentials: Unable to fetch "
123 "auth credentials for %s in %s\n",
124 tmp, (dom==NULL)?"ALLOC":dom->name));
125 ret = NT_STATUS_ACCESS_DENIED;
128 *dn = talloc_strdup(mem_ctx, tmp);
129 CHECK_ALLOC_DONE(*dn);
131 if (!fetch_ldap_pw(&user_dn, &secret)) {
132 DEBUG(2, ("get_credentials: Failed to lookup ldap "
133 "bind creds. Using anonymous connection.\n"));
137 *dn = talloc_strdup(mem_ctx, user_dn);
138 SAFE_FREE( user_dn );
139 CHECK_ALLOC_DONE(*dn);
143 smbldap_set_creds(ldap_state, anon, *dn, secret);
153 /**********************************************************************
154 Verify the sambaUnixIdPool entry in the directory.
155 **********************************************************************/
157 static NTSTATUS verify_idpool(struct idmap_domain *dom)
161 LDAPMessage *result = NULL;
162 LDAPMod **mods = NULL;
163 const char **attr_list;
167 struct idmap_ldap_context *ctx;
169 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
171 mem_ctx = talloc_new(ctx);
172 if (mem_ctx == NULL) {
173 DEBUG(0, ("Out of memory!\n"));
174 return NT_STATUS_NO_MEMORY;
177 filter = talloc_asprintf(mem_ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
178 CHECK_ALLOC_DONE(filter);
180 attr_list = get_attr_list(mem_ctx, idpool_attr_list);
181 CHECK_ALLOC_DONE(attr_list);
183 rc = smbldap_search(ctx->smbldap_state,
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(ctx->smbldap_state->ldap_struct, result);
199 ldap_msgfree(result);
202 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
203 filter, ctx->suffix));
204 ret = NT_STATUS_UNSUCCESSFUL;
207 else if (count == 0) {
208 char *uid_str, *gid_str;
210 uid_str = talloc_asprintf(mem_ctx, "%lu",
211 (unsigned long)dom->low_id);
212 gid_str = talloc_asprintf(mem_ctx, "%lu",
213 (unsigned long)dom->low_id);
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),
221 smbldap_set_mod(&mods, LDAP_MOD_ADD,
222 get_attr_key2string(idpool_attr_list,
223 LDAP_ATTR_GIDNUMBER),
226 rc = smbldap_modify(ctx->smbldap_state,
229 ldap_mods_free(mods, True);
231 ret = NT_STATUS_UNSUCCESSFUL;
236 ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
238 talloc_free(mem_ctx);
242 /********************************
243 Allocate a new uid or gid
244 ********************************/
246 static NTSTATUS idmap_ldap_allocate_id(struct idmap_domain *dom,
250 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
251 int rc = LDAP_SERVER_DOWN;
253 LDAPMessage *result = NULL;
254 LDAPMessage *entry = NULL;
255 LDAPMod **mods = NULL;
259 const char *dn = NULL;
260 const char **attr_list;
262 struct idmap_ldap_context *ctx;
264 /* Only do query if we are online */
265 if (idmap_is_offline()) {
266 return NT_STATUS_FILE_IS_OFFLINE;
269 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
271 mem_ctx = talloc_new(ctx);
273 DEBUG(0, ("Out of memory!\n"));
274 return NT_STATUS_NO_MEMORY;
281 type = get_attr_key2string(idpool_attr_list,
282 LDAP_ATTR_UIDNUMBER);
286 type = get_attr_key2string(idpool_attr_list,
287 LDAP_ATTR_GIDNUMBER);
291 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
292 return NT_STATUS_INVALID_PARAMETER;
295 filter = talloc_asprintf(mem_ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
296 CHECK_ALLOC_DONE(filter);
298 attr_list = get_attr_list(mem_ctx, idpool_attr_list);
299 CHECK_ALLOC_DONE(attr_list);
301 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
303 rc = smbldap_search(ctx->smbldap_state,
305 LDAP_SCOPE_SUBTREE, filter,
306 attr_list, 0, &result);
308 if (rc != LDAP_SUCCESS) {
309 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
313 talloc_autofree_ldapmsg(mem_ctx, result);
315 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
317 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
321 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result);
323 dn = smbldap_talloc_dn(mem_ctx,
324 ctx->smbldap_state->ldap_struct,
330 id_str = smbldap_talloc_single_attribute(
331 ctx->smbldap_state->ldap_struct,
332 entry, type, mem_ctx);
333 if (id_str == NULL) {
334 DEBUG(0,("%s attribute not found\n", type));
335 ret = NT_STATUS_UNSUCCESSFUL;
339 xid->id = strtoul(id_str, NULL, 10);
341 /* make sure we still have room to grow */
345 if (xid->id > dom->high_id) {
346 DEBUG(0,("Cannot allocate uid above %lu!\n",
347 (unsigned long)dom->high_id));
353 if (xid->id > dom->high_id) {
354 DEBUG(0,("Cannot allocate gid above %lu!\n",
355 (unsigned long)dom->high_id));
365 new_id_str = talloc_asprintf(mem_ctx, "%lu", (unsigned long)xid->id + 1);
367 DEBUG(0,("Out of memory\n"));
368 ret = NT_STATUS_NO_MEMORY;
372 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
373 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
376 DEBUG(0,("smbldap_set_mod() failed.\n"));
380 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
381 id_str, new_id_str));
383 rc = smbldap_modify(ctx->smbldap_state, dn, mods);
385 ldap_mods_free(mods, True);
387 if (rc != LDAP_SUCCESS) {
388 DEBUG(1,("Failed to allocate new %s. "
389 "smbldap_modify() failed.\n", type));
396 talloc_free(mem_ctx);
401 * Allocate a new unix-ID.
402 * For now this is for the default idmap domain only.
403 * Should be extended later on.
405 static NTSTATUS idmap_ldap_get_new_id(struct idmap_domain *dom,
410 if (!strequal(dom->name, "*")) {
411 DEBUG(3, ("idmap_ldap_get_new_id: "
412 "Refusing allocation of a new unixid for domain'%s'. "
413 "Currently only supported for the default "
416 return NT_STATUS_NOT_IMPLEMENTED;
419 ret = idmap_ldap_allocate_id(dom, id);
425 /**********************************************************************
426 IDMAP MAPPING LDAP BACKEND
427 **********************************************************************/
429 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
431 smbldap_free_struct(&ctx->smbldap_state);
432 DEBUG(5,("The connection to the LDAP server was closed\n"));
433 /* maybe free the results here --metze */
438 /********************************
439 Initialise idmap database.
440 ********************************/
442 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
443 const struct id_map *map);
445 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
449 struct idmap_ldap_context *ctx = NULL;
450 char *config_option = NULL;
451 const char *tmp = NULL;
453 /* Only do init if we are online */
454 if (idmap_is_offline()) {
455 return NT_STATUS_FILE_IS_OFFLINE;
458 ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
460 DEBUG(0, ("Out of memory!\n"));
461 return NT_STATUS_NO_MEMORY;
464 if (strequal(dom->name, "*")) {
465 /* more specific configuration can go here */
467 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
468 if ( ! config_option) {
469 DEBUG(0, ("Out of memory!\n"));
470 ret = NT_STATUS_NO_MEMORY;
475 if (params != NULL) {
476 /* assume location is the only parameter */
477 ctx->url = talloc_strdup(ctx, params);
479 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
482 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
483 ret = NT_STATUS_UNSUCCESSFUL;
487 ctx->url = talloc_strdup(ctx, tmp);
489 CHECK_ALLOC_DONE(ctx->url);
491 trim_char(ctx->url, '\"', '\"');
493 tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
494 if ( ! tmp || ! *tmp) {
495 tmp = lp_ldap_idmap_suffix();
497 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
498 ret = NT_STATUS_UNSUCCESSFUL;
503 ctx->suffix = talloc_strdup(ctx, tmp);
504 CHECK_ALLOC_DONE(ctx->suffix);
506 ctx->rw_ops = talloc_zero(ctx, struct idmap_rw_ops);
507 CHECK_ALLOC_DONE(ctx->rw_ops);
509 ctx->rw_ops->get_new_id = idmap_ldap_get_new_id;
510 ctx->rw_ops->set_mapping = idmap_ldap_set_mapping;
512 ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
513 &ctx->smbldap_state);
514 if (!NT_STATUS_IS_OK(ret)) {
515 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
519 ret = get_credentials( ctx, ctx->smbldap_state, config_option,
520 dom, &ctx->user_dn );
521 if ( !NT_STATUS_IS_OK(ret) ) {
522 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
523 "credentials (%s)\n", nt_errstr(ret)));
527 /* set the destructor on the context, so that resource are properly
528 freed if the contexts is released */
530 talloc_set_destructor(ctx, idmap_ldap_close_destructor);
532 dom->private_data = ctx;
534 ret = verify_idpool(dom);
535 if (!NT_STATUS_IS_OK(ret)) {
536 DEBUG(1, ("idmap_ldap_db_init: failed to verify ID pool (%s)\n",
541 talloc_free(config_option);
554 /* TODO: change this: This function cannot be called to modify a mapping,
555 * only set a new one */
557 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
558 const struct id_map *map)
562 struct idmap_ldap_context *ctx;
563 LDAPMessage *entry = NULL;
564 LDAPMod **mods = NULL;
571 /* Only do query if we are online */
572 if (idmap_is_offline()) {
573 return NT_STATUS_FILE_IS_OFFLINE;
576 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
578 switch(map->xid.type) {
580 type = get_attr_key2string(sidmap_attr_list,
581 LDAP_ATTR_UIDNUMBER);
585 type = get_attr_key2string(sidmap_attr_list,
586 LDAP_ATTR_GIDNUMBER);
590 return NT_STATUS_INVALID_PARAMETER;
593 memctx = talloc_new(ctx);
595 DEBUG(0, ("Out of memory!\n"));
596 return NT_STATUS_NO_MEMORY;
599 id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
600 CHECK_ALLOC_DONE(id_str);
602 sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
603 CHECK_ALLOC_DONE(sid);
605 dn = talloc_asprintf(memctx, "%s=%s,%s",
606 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
609 CHECK_ALLOC_DONE(dn);
611 smbldap_set_mod(&mods, LDAP_MOD_ADD,
612 "objectClass", LDAP_OBJ_IDMAP_ENTRY);
614 smbldap_make_mod(ctx->smbldap_state->ldap_struct,
615 entry, &mods, type, id_str);
617 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
618 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
622 DEBUG(2, ("ERROR: No mods?\n"));
623 ret = NT_STATUS_UNSUCCESSFUL;
627 /* TODO: remove conflicting mappings! */
629 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
631 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
633 rc = smbldap_add(ctx->smbldap_state, dn, mods);
634 ldap_mods_free(mods, True);
636 if (rc != LDAP_SUCCESS) {
637 char *ld_error = NULL;
638 ldap_get_option(ctx->smbldap_state->ldap_struct,
639 LDAP_OPT_ERROR_STRING, &ld_error);
640 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
641 "mapping [%s]\n", sid,
642 (unsigned long)map->xid.id, type));
643 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
644 ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
646 ldap_memfree(ld_error);
648 ret = NT_STATUS_UNSUCCESSFUL;
652 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
653 "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
663 * Create a new mapping for an unmapped SID, also allocating a new ID.
664 * If possible, this should be run inside a transaction to make the
667 static NTSTATUS idmap_ldap_new_mapping(struct idmap_domain *dom, struct id_map *map)
670 struct idmap_ldap_context *ctx;
672 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
674 ret = idmap_rw_new_mapping(dom, ctx->rw_ops, map);
680 /* max number of ids requested per batch query */
681 #define IDMAP_LDAP_MAX_IDS 30
683 /**********************************
684 lookup a set of unix ids.
685 **********************************/
687 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
688 * in maps for a match */
689 static struct id_map *find_map_by_id(struct id_map **maps,
695 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
696 if (maps[i] == NULL) { /* end of the run */
699 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
707 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
712 struct idmap_ldap_context *ctx;
713 LDAPMessage *result = NULL;
714 LDAPMessage *entry = NULL;
715 const char *uidNumber;
716 const char *gidNumber;
717 const char **attr_list;
726 /* Only do query if we are online */
727 if (idmap_is_offline()) {
728 return NT_STATUS_FILE_IS_OFFLINE;
731 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
733 memctx = talloc_new(ctx);
735 DEBUG(0, ("Out of memory!\n"));
736 return NT_STATUS_NO_MEMORY;
739 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
740 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
742 attr_list = get_attr_list(memctx, sidmap_attr_list);
745 /* if we are requested just one mapping use the simple filter */
747 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
748 LDAP_OBJ_IDMAP_ENTRY,
749 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
750 (unsigned long)ids[0]->xid.id);
751 CHECK_ALLOC_DONE(filter);
752 DEBUG(10, ("Filter: [%s]\n", filter));
754 /* multiple mappings */
758 for (i = 0; ids[i]; i++) {
759 ids[i]->status = ID_UNKNOWN;
766 filter = talloc_asprintf(memctx,
767 "(&(objectClass=%s)(|",
768 LDAP_OBJ_IDMAP_ENTRY);
769 CHECK_ALLOC_DONE(filter);
772 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
773 filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
774 (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
775 (unsigned long)ids[idx]->xid.id);
776 CHECK_ALLOC_DONE(filter);
778 filter = talloc_asprintf_append_buffer(filter, "))");
779 CHECK_ALLOC_DONE(filter);
780 DEBUG(10, ("Filter: [%s]\n", filter));
786 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
787 filter, attr_list, 0, &result);
789 if (rc != LDAP_SUCCESS) {
790 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
791 ret = NT_STATUS_UNSUCCESSFUL;
795 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
798 DEBUG(10, ("NO SIDs found\n"));
801 for (i = 0; i < count; i++) {
808 if (i == 0) { /* first entry */
809 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
811 } else { /* following ones */
812 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
816 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
821 /* first check if the SID is present */
822 sidstr = smbldap_talloc_single_attribute(
823 ctx->smbldap_state->ldap_struct,
824 entry, LDAP_ATTRIBUTE_SID, memctx);
825 if ( ! sidstr) { /* no sid, skip entry */
826 DEBUG(2, ("WARNING SID not found on entry\n"));
830 /* now try to see if it is a uid, if not try with a gid
831 * (gid is more common, but in case both uidNumber and
832 * gidNumber are returned the SID is mapped to the uid
835 tmp = smbldap_talloc_single_attribute(
836 ctx->smbldap_state->ldap_struct,
837 entry, uidNumber, memctx);
840 tmp = smbldap_talloc_single_attribute(
841 ctx->smbldap_state->ldap_struct,
842 entry, gidNumber, memctx);
844 if ( ! tmp) { /* wow very strange entry, how did it match ? */
845 DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
846 "nor gidNumber returned\n", sidstr));
851 id = strtoul(tmp, NULL, 10);
852 if (!idmap_unix_id_is_in_range(id, dom)) {
853 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
855 dom->low_id, dom->high_id));
862 map = find_map_by_id(&ids[bidx], type, id);
864 DEBUG(2, ("WARNING: couldn't match sid (%s) "
865 "with requested ids\n", sidstr));
870 if ( ! string_to_sid(map->sid, sidstr)) {
871 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
876 if (map->status == ID_MAPPED) {
877 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
878 "overwriting mapping %u -> %s with %u -> %s\n",
879 (type == ID_TYPE_UID) ? "UID" : "GID",
880 id, sid_string_dbg(map->sid), id, sidstr));
886 map->status = ID_MAPPED;
888 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
889 (unsigned long)map->xid.id, map->xid.type));
892 /* free the ldap results */
894 ldap_msgfree(result);
898 if (multi && ids[idx]) { /* still some values to map */
904 /* mark all unknwon/expired ones as unmapped */
905 for (i = 0; ids[i]; i++) {
906 if (ids[i]->status != ID_MAPPED)
907 ids[i]->status = ID_UNMAPPED;
915 /**********************************
916 lookup a set of sids.
917 **********************************/
919 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
920 * in maps for a match */
921 static struct id_map *find_map_by_sid(struct id_map **maps, struct dom_sid *sid)
925 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
926 if (maps[i] == NULL) { /* end of the run */
929 if (dom_sid_equal(maps[i]->sid, sid)) {
937 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
940 LDAPMessage *entry = NULL;
943 struct idmap_ldap_context *ctx;
944 LDAPMessage *result = NULL;
945 const char *uidNumber;
946 const char *gidNumber;
947 const char **attr_list;
956 /* Only do query if we are online */
957 if (idmap_is_offline()) {
958 return NT_STATUS_FILE_IS_OFFLINE;
961 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
963 memctx = talloc_new(ctx);
965 DEBUG(0, ("Out of memory!\n"));
966 return NT_STATUS_NO_MEMORY;
969 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
970 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
972 attr_list = get_attr_list(memctx, sidmap_attr_list);
975 /* if we are requested just one mapping use the simple filter */
977 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
978 LDAP_OBJ_IDMAP_ENTRY,
980 sid_string_talloc(memctx, ids[0]->sid));
981 CHECK_ALLOC_DONE(filter);
982 DEBUG(10, ("Filter: [%s]\n", filter));
984 /* multiple mappings */
988 for (i = 0; ids[i]; i++) {
989 ids[i]->status = ID_UNKNOWN;
996 filter = talloc_asprintf(memctx,
997 "(&(objectClass=%s)(|",
998 LDAP_OBJ_IDMAP_ENTRY);
999 CHECK_ALLOC_DONE(filter);
1002 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
1003 filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
1005 sid_string_talloc(memctx,
1007 CHECK_ALLOC_DONE(filter);
1009 filter = talloc_asprintf_append_buffer(filter, "))");
1010 CHECK_ALLOC_DONE(filter);
1011 DEBUG(10, ("Filter: [%s]", filter));
1017 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1018 filter, attr_list, 0, &result);
1020 if (rc != LDAP_SUCCESS) {
1021 DEBUG(3,("Failure looking up sids (%s)\n",
1022 ldap_err2string(rc)));
1023 ret = NT_STATUS_UNSUCCESSFUL;
1027 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1030 DEBUG(10, ("NO SIDs found\n"));
1033 for (i = 0; i < count; i++) {
1034 char *sidstr = NULL;
1041 if (i == 0) { /* first entry */
1042 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1044 } else { /* following ones */
1045 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1049 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1054 /* first check if the SID is present */
1055 sidstr = smbldap_talloc_single_attribute(
1056 ctx->smbldap_state->ldap_struct,
1057 entry, LDAP_ATTRIBUTE_SID, memctx);
1058 if ( ! sidstr) { /* no sid ??, skip entry */
1059 DEBUG(2, ("WARNING SID not found on entry\n"));
1063 if ( ! string_to_sid(&sid, sidstr)) {
1064 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1065 TALLOC_FREE(sidstr);
1069 map = find_map_by_sid(&ids[bidx], &sid);
1071 DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1073 TALLOC_FREE(sidstr);
1077 /* now try to see if it is a uid, if not try with a gid
1078 * (gid is more common, but in case both uidNumber and
1079 * gidNumber are returned the SID is mapped to the uid
1082 tmp = smbldap_talloc_single_attribute(
1083 ctx->smbldap_state->ldap_struct,
1084 entry, uidNumber, memctx);
1087 tmp = smbldap_talloc_single_attribute(
1088 ctx->smbldap_state->ldap_struct,
1089 entry, gidNumber, memctx);
1091 if ( ! tmp) { /* no ids ?? */
1092 DEBUG(5, ("no uidNumber, "
1093 "nor gidNumber attributes found\n"));
1094 TALLOC_FREE(sidstr);
1098 id = strtoul(tmp, NULL, 10);
1099 if (!idmap_unix_id_is_in_range(id, dom)) {
1100 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1102 dom->low_id, dom->high_id));
1103 TALLOC_FREE(sidstr);
1109 if (map->status == ID_MAPPED) {
1110 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1111 "overwriting mapping %s -> %u with %s -> %u\n",
1112 (type == ID_TYPE_UID) ? "UID" : "GID",
1113 sidstr, map->xid.id, sidstr, id));
1116 TALLOC_FREE(sidstr);
1119 map->xid.type = type;
1121 map->status = ID_MAPPED;
1123 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1124 (unsigned long)map->xid.id, map->xid.type));
1127 /* free the ldap results */
1129 ldap_msgfree(result);
1133 if (multi && ids[idx]) { /* still some values to map */
1138 * try to create new mappings for unmapped sids
1140 for (i = 0; ids[i]; i++) {
1141 if (ids[i]->status != ID_MAPPED) {
1142 ids[i]->status = ID_UNMAPPED;
1143 if (ids[i]->sid != NULL) {
1144 ret = idmap_ldap_new_mapping(dom, ids[i]);
1145 if (!NT_STATUS_IS_OK(ret)) {
1155 talloc_free(memctx);
1159 /**********************************
1160 Close the idmap ldap instance
1161 **********************************/
1163 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1165 struct idmap_ldap_context *ctx;
1167 if (dom->private_data) {
1168 ctx = talloc_get_type(dom->private_data,
1169 struct idmap_ldap_context);
1172 dom->private_data = NULL;
1175 return NT_STATUS_OK;
1178 static struct idmap_methods idmap_ldap_methods = {
1180 .init = idmap_ldap_db_init,
1181 .unixids_to_sids = idmap_ldap_unixids_to_sids,
1182 .sids_to_unixids = idmap_ldap_sids_to_unixids,
1183 .allocate_id = idmap_ldap_get_new_id,
1184 .close_fn = idmap_ldap_close
1187 NTSTATUS idmap_ldap_init(void);
1188 NTSTATUS idmap_ldap_init(void)
1190 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1191 &idmap_ldap_methods);