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;
72 uid_t low_uid, high_uid; /* Range of uids */
73 gid_t low_gid, high_gid; /* Range of gids */
77 #define CHECK_ALLOC_DONE(mem) do { \
79 DEBUG(0, ("Out of memory!\n")); \
80 ret = NT_STATUS_NO_MEMORY; \
84 /**********************************************************************
85 IDMAP ALLOC TDB BACKEND
86 **********************************************************************/
88 static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
90 /*********************************************************************
91 ********************************************************************/
93 static NTSTATUS get_credentials( TALLOC_CTX *mem_ctx,
94 struct smbldap_state *ldap_state,
95 const char *config_option,
96 struct idmap_domain *dom,
99 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
101 const char *tmp = NULL;
102 char *user_dn = NULL;
105 /* assume anonymous if we don't have a specified user */
107 tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
111 /* only the alloc backend can pass in a NULL dom */
112 secret = idmap_fetch_secret("ldap", True,
115 secret = idmap_fetch_secret("ldap", False,
120 DEBUG(0, ("get_credentials: Unable to fetch "
121 "auth credentials for %s in %s\n",
122 tmp, (dom==NULL)?"ALLOC":dom->name));
123 ret = NT_STATUS_ACCESS_DENIED;
126 *dn = talloc_strdup(mem_ctx, tmp);
127 CHECK_ALLOC_DONE(*dn);
129 if (!fetch_ldap_pw(&user_dn, &secret)) {
130 DEBUG(2, ("get_credentials: Failed to lookup ldap "
131 "bind creds. Using anonymous connection.\n"));
134 *dn = talloc_strdup(mem_ctx, user_dn);
135 SAFE_FREE( user_dn );
136 CHECK_ALLOC_DONE(*dn);
140 smbldap_set_creds(ldap_state, anon, *dn, secret);
150 /**********************************************************************
151 Verify the sambaUnixIdPool entry in the directory.
152 **********************************************************************/
154 static NTSTATUS verify_idpool(struct idmap_domain *dom)
158 LDAPMessage *result = NULL;
159 LDAPMod **mods = NULL;
160 const char **attr_list;
165 if ( ! idmap_alloc_ldap) {
166 return NT_STATUS_UNSUCCESSFUL;
169 ctx = talloc_new(idmap_alloc_ldap);
171 DEBUG(0, ("Out of memory!\n"));
172 return NT_STATUS_NO_MEMORY;
175 filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
176 CHECK_ALLOC_DONE(filter);
178 attr_list = get_attr_list(ctx, idpool_attr_list);
179 CHECK_ALLOC_DONE(attr_list);
181 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
182 idmap_alloc_ldap->suffix,
189 if (rc != LDAP_SUCCESS) {
190 DEBUG(1, ("Unable to verify the idpool, "
191 "cannot continue initialization!\n"));
192 return NT_STATUS_UNSUCCESSFUL;
195 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
198 ldap_msgfree(result);
201 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
202 filter, idmap_alloc_ldap->suffix));
203 ret = NT_STATUS_UNSUCCESSFUL;
206 else if (count == 0) {
207 char *uid_str, *gid_str;
209 uid_str = talloc_asprintf(ctx, "%lu",
210 (unsigned long)dom->low_id);
211 gid_str = talloc_asprintf(ctx, "%lu",
212 (unsigned long)dom->low_id);
214 smbldap_set_mod(&mods, LDAP_MOD_ADD,
215 "objectClass", LDAP_OBJ_IDPOOL);
216 smbldap_set_mod(&mods, LDAP_MOD_ADD,
217 get_attr_key2string(idpool_attr_list,
218 LDAP_ATTR_UIDNUMBER),
220 smbldap_set_mod(&mods, LDAP_MOD_ADD,
221 get_attr_key2string(idpool_attr_list,
222 LDAP_ATTR_GIDNUMBER),
225 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
226 idmap_alloc_ldap->suffix,
228 ldap_mods_free(mods, True);
230 ret = NT_STATUS_UNSUCCESSFUL;
235 ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
241 /*****************************************************************************
242 Initialise idmap database.
243 *****************************************************************************/
245 static NTSTATUS idmap_ldap_alloc_init(struct idmap_domain *dom,
248 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
251 /* Only do init if we are online */
252 if (idmap_is_offline()) {
253 return NT_STATUS_FILE_IS_OFFLINE;
256 idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
257 CHECK_ALLOC_DONE( idmap_alloc_ldap );
259 if (params && *params) {
260 /* assume location is the only parameter */
261 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
263 tmp = lp_parm_const_string(-1, "idmap alloc config",
267 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
268 ret = NT_STATUS_UNSUCCESSFUL;
272 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
274 CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
276 trim_char(idmap_alloc_ldap->url, '\"', '\"');
278 tmp = lp_parm_const_string(-1, "idmap alloc config",
279 "ldap_base_dn", NULL);
280 if ( ! tmp || ! *tmp) {
281 tmp = lp_ldap_idmap_suffix();
283 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
284 ret = NT_STATUS_UNSUCCESSFUL;
289 idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
290 CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
292 ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
293 idmap_alloc_ldap->url,
294 &idmap_alloc_ldap->smbldap_state);
295 if (!NT_STATUS_IS_OK(ret)) {
296 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
297 idmap_alloc_ldap->url));
301 ret = get_credentials( idmap_alloc_ldap,
302 idmap_alloc_ldap->smbldap_state,
303 "idmap alloc config", NULL,
304 &idmap_alloc_ldap->user_dn );
305 if ( !NT_STATUS_IS_OK(ret) ) {
306 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
307 "credentials (%s)\n", nt_errstr(ret)));
311 /* see if the idmap suffix and sub entries exists */
313 ret = verify_idpool(dom);
316 if ( !NT_STATUS_IS_OK( ret ) )
317 TALLOC_FREE( idmap_alloc_ldap );
322 /********************************
323 Allocate a new uid or gid
324 ********************************/
326 static NTSTATUS idmap_ldap_allocate_id(struct idmap_domain *dom,
330 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
331 int rc = LDAP_SERVER_DOWN;
333 LDAPMessage *result = NULL;
334 LDAPMessage *entry = NULL;
335 LDAPMod **mods = NULL;
339 const char *dn = NULL;
340 const char **attr_list;
343 /* Only do query if we are online */
344 if (idmap_is_offline()) {
345 return NT_STATUS_FILE_IS_OFFLINE;
348 if ( ! idmap_alloc_ldap) {
349 return NT_STATUS_UNSUCCESSFUL;
352 ctx = talloc_new(idmap_alloc_ldap);
354 DEBUG(0, ("Out of memory!\n"));
355 return NT_STATUS_NO_MEMORY;
362 type = get_attr_key2string(idpool_attr_list,
363 LDAP_ATTR_UIDNUMBER);
367 type = get_attr_key2string(idpool_attr_list,
368 LDAP_ATTR_GIDNUMBER);
372 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
373 return NT_STATUS_INVALID_PARAMETER;
376 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
377 CHECK_ALLOC_DONE(filter);
379 attr_list = get_attr_list(ctx, idpool_attr_list);
380 CHECK_ALLOC_DONE(attr_list);
382 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
384 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
385 idmap_alloc_ldap->suffix,
386 LDAP_SCOPE_SUBTREE, filter,
387 attr_list, 0, &result);
389 if (rc != LDAP_SUCCESS) {
390 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
394 talloc_autofree_ldapmsg(ctx, result);
396 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
399 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
403 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
406 dn = smbldap_talloc_dn(ctx,
407 idmap_alloc_ldap->smbldap_state->ldap_struct,
413 if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
414 entry, type, ctx))) {
415 DEBUG(0,("%s attribute not found\n", type));
419 DEBUG(0,("Out of memory\n"));
420 ret = NT_STATUS_NO_MEMORY;
424 xid->id = strtoul(id_str, NULL, 10);
426 /* make sure we still have room to grow */
430 if (xid->id > dom->high_id) {
431 DEBUG(0,("Cannot allocate uid above %lu!\n",
432 (unsigned long)dom->high_id));
438 if (xid->id > dom->high_id) {
439 DEBUG(0,("Cannot allocate gid above %lu!\n",
440 (unsigned long)dom->high_id));
450 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
452 DEBUG(0,("Out of memory\n"));
453 ret = NT_STATUS_NO_MEMORY;
457 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
458 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
461 DEBUG(0,("smbldap_set_mod() failed.\n"));
465 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
466 id_str, new_id_str));
468 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
470 ldap_mods_free(mods, True);
472 if (rc != LDAP_SUCCESS) {
473 DEBUG(1,("Failed to allocate new %s. "
474 "smbldap_modify() failed.\n", type));
485 /**********************************
486 Close idmap ldap alloc
487 **********************************/
489 static NTSTATUS idmap_ldap_alloc_close(void)
491 if (idmap_alloc_ldap) {
492 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
493 DEBUG(5,("The connection to the LDAP server was closed\n"));
494 /* maybe free the results here --metze */
495 TALLOC_FREE(idmap_alloc_ldap);
501 /**********************************************************************
502 IDMAP MAPPING LDAP BACKEND
503 **********************************************************************/
505 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
507 smbldap_free_struct(&ctx->smbldap_state);
508 DEBUG(5,("The connection to the LDAP server was closed\n"));
509 /* maybe free the results here --metze */
514 /********************************
515 Initialise idmap database.
516 ********************************/
518 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
522 struct idmap_ldap_context *ctx = NULL;
523 char *config_option = NULL;
524 const char *tmp = NULL;
526 /* Only do init if we are online */
527 if (idmap_is_offline()) {
528 return NT_STATUS_FILE_IS_OFFLINE;
531 ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
533 DEBUG(0, ("Out of memory!\n"));
534 return NT_STATUS_NO_MEMORY;
537 if (strequal(dom->name, "*")) {
538 /* more specific configuration can go here */
540 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
541 if ( ! config_option) {
542 DEBUG(0, ("Out of memory!\n"));
543 ret = NT_STATUS_NO_MEMORY;
548 if (params != NULL) {
549 /* assume location is the only parameter */
550 ctx->url = talloc_strdup(ctx, params);
552 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
555 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
556 ret = NT_STATUS_UNSUCCESSFUL;
560 ctx->url = talloc_strdup(ctx, tmp);
562 CHECK_ALLOC_DONE(ctx->url);
564 trim_char(ctx->url, '\"', '\"');
566 tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
567 if ( ! tmp || ! *tmp) {
568 tmp = lp_ldap_idmap_suffix();
570 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
571 ret = NT_STATUS_UNSUCCESSFUL;
576 ctx->suffix = talloc_strdup(ctx, tmp);
577 CHECK_ALLOC_DONE(ctx->suffix);
579 ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
580 &ctx->smbldap_state);
581 if (!NT_STATUS_IS_OK(ret)) {
582 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
586 ret = get_credentials( ctx, ctx->smbldap_state, config_option,
587 dom, &ctx->user_dn );
588 if ( !NT_STATUS_IS_OK(ret) ) {
589 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
590 "credentials (%s)\n", nt_errstr(ret)));
594 /* set the destructor on the context, so that resource are properly
595 freed if the contexts is released */
597 talloc_set_destructor(ctx, idmap_ldap_close_destructor);
599 dom->private_data = ctx;
601 talloc_free(config_option);
610 /* max number of ids requested per batch query */
611 #define IDMAP_LDAP_MAX_IDS 30
613 /**********************************
614 lookup a set of unix ids.
615 **********************************/
617 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
618 * in maps for a match */
619 static struct id_map *find_map_by_id(struct id_map **maps,
625 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
626 if (maps[i] == NULL) { /* end of the run */
629 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
637 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
642 struct idmap_ldap_context *ctx;
643 LDAPMessage *result = NULL;
644 LDAPMessage *entry = NULL;
645 const char *uidNumber;
646 const char *gidNumber;
647 const char **attr_list;
656 /* Only do query if we are online */
657 if (idmap_is_offline()) {
658 return NT_STATUS_FILE_IS_OFFLINE;
661 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
663 memctx = talloc_new(ctx);
665 DEBUG(0, ("Out of memory!\n"));
666 return NT_STATUS_NO_MEMORY;
669 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
670 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
672 attr_list = get_attr_list(memctx, sidmap_attr_list);
675 /* if we are requested just one mapping use the simple filter */
677 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
678 LDAP_OBJ_IDMAP_ENTRY,
679 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
680 (unsigned long)ids[0]->xid.id);
681 CHECK_ALLOC_DONE(filter);
682 DEBUG(10, ("Filter: [%s]\n", filter));
684 /* multiple mappings */
688 for (i = 0; ids[i]; i++) {
689 ids[i]->status = ID_UNKNOWN;
696 filter = talloc_asprintf(memctx,
697 "(&(objectClass=%s)(|",
698 LDAP_OBJ_IDMAP_ENTRY);
699 CHECK_ALLOC_DONE(filter);
702 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
703 filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
704 (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
705 (unsigned long)ids[idx]->xid.id);
706 CHECK_ALLOC_DONE(filter);
708 filter = talloc_asprintf_append_buffer(filter, "))");
709 CHECK_ALLOC_DONE(filter);
710 DEBUG(10, ("Filter: [%s]\n", filter));
716 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
717 filter, attr_list, 0, &result);
719 if (rc != LDAP_SUCCESS) {
720 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
721 ret = NT_STATUS_UNSUCCESSFUL;
725 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
728 DEBUG(10, ("NO SIDs found\n"));
731 for (i = 0; i < count; i++) {
738 if (i == 0) { /* first entry */
739 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
741 } else { /* following ones */
742 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
746 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
751 /* first check if the SID is present */
752 sidstr = smbldap_talloc_single_attribute(
753 ctx->smbldap_state->ldap_struct,
754 entry, LDAP_ATTRIBUTE_SID, memctx);
755 if ( ! sidstr) { /* no sid, skip entry */
756 DEBUG(2, ("WARNING SID not found on entry\n"));
760 /* now try to see if it is a uid, if not try with a gid
761 * (gid is more common, but in case both uidNumber and
762 * gidNumber are returned the SID is mapped to the uid
765 tmp = smbldap_talloc_single_attribute(
766 ctx->smbldap_state->ldap_struct,
767 entry, uidNumber, memctx);
770 tmp = smbldap_talloc_single_attribute(
771 ctx->smbldap_state->ldap_struct,
772 entry, gidNumber, memctx);
774 if ( ! tmp) { /* wow very strange entry, how did it match ? */
775 DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
776 "nor gidNumber returned\n", sidstr));
781 id = strtoul(tmp, NULL, 10);
782 if (!idmap_unix_id_is_in_range(id, dom)) {
783 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
785 dom->low_id, dom->high_id));
792 map = find_map_by_id(&ids[bidx], type, id);
794 DEBUG(2, ("WARNING: couldn't match sid (%s) "
795 "with requested ids\n", sidstr));
800 if ( ! string_to_sid(map->sid, sidstr)) {
801 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
806 if (map->status == ID_MAPPED) {
807 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
808 "overwriting mapping %u -> %s with %u -> %s\n",
809 (type == ID_TYPE_UID) ? "UID" : "GID",
810 id, sid_string_dbg(map->sid), id, sidstr));
816 map->status = ID_MAPPED;
818 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
819 (unsigned long)map->xid.id, map->xid.type));
822 /* free the ldap results */
824 ldap_msgfree(result);
828 if (multi && ids[idx]) { /* still some values to map */
834 /* mark all unknwon/expired ones as unmapped */
835 for (i = 0; ids[i]; i++) {
836 if (ids[i]->status != ID_MAPPED)
837 ids[i]->status = ID_UNMAPPED;
845 /**********************************
846 lookup a set of sids.
847 **********************************/
849 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
850 * in maps for a match */
851 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
855 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
856 if (maps[i] == NULL) { /* end of the run */
859 if (sid_equal(maps[i]->sid, sid)) {
867 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
870 LDAPMessage *entry = NULL;
873 struct idmap_ldap_context *ctx;
874 LDAPMessage *result = NULL;
875 const char *uidNumber;
876 const char *gidNumber;
877 const char **attr_list;
886 /* Only do query if we are online */
887 if (idmap_is_offline()) {
888 return NT_STATUS_FILE_IS_OFFLINE;
891 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
893 memctx = talloc_new(ctx);
895 DEBUG(0, ("Out of memory!\n"));
896 return NT_STATUS_NO_MEMORY;
899 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
900 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
902 attr_list = get_attr_list(memctx, sidmap_attr_list);
905 /* if we are requested just one mapping use the simple filter */
907 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
908 LDAP_OBJ_IDMAP_ENTRY,
910 sid_string_talloc(memctx, ids[0]->sid));
911 CHECK_ALLOC_DONE(filter);
912 DEBUG(10, ("Filter: [%s]\n", filter));
914 /* multiple mappings */
918 for (i = 0; ids[i]; i++) {
919 ids[i]->status = ID_UNKNOWN;
926 filter = talloc_asprintf(memctx,
927 "(&(objectClass=%s)(|",
928 LDAP_OBJ_IDMAP_ENTRY);
929 CHECK_ALLOC_DONE(filter);
932 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
933 filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
935 sid_string_talloc(memctx,
937 CHECK_ALLOC_DONE(filter);
939 filter = talloc_asprintf_append_buffer(filter, "))");
940 CHECK_ALLOC_DONE(filter);
941 DEBUG(10, ("Filter: [%s]", filter));
947 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
948 filter, attr_list, 0, &result);
950 if (rc != LDAP_SUCCESS) {
951 DEBUG(3,("Failure looking up sids (%s)\n",
952 ldap_err2string(rc)));
953 ret = NT_STATUS_UNSUCCESSFUL;
957 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
960 DEBUG(10, ("NO SIDs found\n"));
963 for (i = 0; i < count; i++) {
971 if (i == 0) { /* first entry */
972 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
974 } else { /* following ones */
975 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
979 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
984 /* first check if the SID is present */
985 sidstr = smbldap_talloc_single_attribute(
986 ctx->smbldap_state->ldap_struct,
987 entry, LDAP_ATTRIBUTE_SID, memctx);
988 if ( ! sidstr) { /* no sid ??, skip entry */
989 DEBUG(2, ("WARNING SID not found on entry\n"));
993 if ( ! string_to_sid(&sid, sidstr)) {
994 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
999 map = find_map_by_sid(&ids[bidx], &sid);
1001 DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1003 TALLOC_FREE(sidstr);
1007 /* now try to see if it is a uid, if not try with a gid
1008 * (gid is more common, but in case both uidNumber and
1009 * gidNumber are returned the SID is mapped to the uid
1012 tmp = smbldap_talloc_single_attribute(
1013 ctx->smbldap_state->ldap_struct,
1014 entry, uidNumber, memctx);
1017 tmp = smbldap_talloc_single_attribute(
1018 ctx->smbldap_state->ldap_struct,
1019 entry, gidNumber, memctx);
1021 if ( ! tmp) { /* no ids ?? */
1022 DEBUG(5, ("no uidNumber, "
1023 "nor gidNumber attributes found\n"));
1024 TALLOC_FREE(sidstr);
1028 id = strtoul(tmp, NULL, 10);
1029 if (!idmap_unix_id_is_in_range(id, dom)) {
1030 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1032 dom->low_id, dom->high_id));
1033 TALLOC_FREE(sidstr);
1039 if (map->status == ID_MAPPED) {
1040 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1041 "overwriting mapping %s -> %u with %s -> %u\n",
1042 (type == ID_TYPE_UID) ? "UID" : "GID",
1043 sidstr, map->xid.id, sidstr, id));
1046 TALLOC_FREE(sidstr);
1049 map->xid.type = type;
1051 map->status = ID_MAPPED;
1053 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1054 (unsigned long)map->xid.id, map->xid.type));
1057 /* free the ldap results */
1059 ldap_msgfree(result);
1063 if (multi && ids[idx]) { /* still some values to map */
1069 /* mark all unknwon/expired ones as unmapped */
1070 for (i = 0; ids[i]; i++) {
1071 if (ids[i]->status != ID_MAPPED)
1072 ids[i]->status = ID_UNMAPPED;
1076 talloc_free(memctx);
1080 /**********************************
1082 **********************************/
1084 /* TODO: change this: This function cannot be called to modify a mapping,
1085 * only set a new one */
1087 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
1088 const struct id_map *map)
1092 struct idmap_ldap_context *ctx;
1093 LDAPMessage *entry = NULL;
1094 LDAPMod **mods = NULL;
1101 /* Only do query if we are online */
1102 if (idmap_is_offline()) {
1103 return NT_STATUS_FILE_IS_OFFLINE;
1106 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1108 switch(map->xid.type) {
1110 type = get_attr_key2string(sidmap_attr_list,
1111 LDAP_ATTR_UIDNUMBER);
1115 type = get_attr_key2string(sidmap_attr_list,
1116 LDAP_ATTR_GIDNUMBER);
1120 return NT_STATUS_INVALID_PARAMETER;
1123 memctx = talloc_new(ctx);
1125 DEBUG(0, ("Out of memory!\n"));
1126 return NT_STATUS_NO_MEMORY;
1129 id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1130 CHECK_ALLOC_DONE(id_str);
1132 sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
1133 CHECK_ALLOC_DONE(sid);
1135 dn = talloc_asprintf(memctx, "%s=%s,%s",
1136 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1139 CHECK_ALLOC_DONE(dn);
1141 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1142 "objectClass", LDAP_OBJ_IDMAP_ENTRY);
1144 smbldap_make_mod(ctx->smbldap_state->ldap_struct,
1145 entry, &mods, type, id_str);
1147 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1148 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1152 DEBUG(2, ("ERROR: No mods?\n"));
1153 ret = NT_STATUS_UNSUCCESSFUL;
1157 /* TODO: remove conflicting mappings! */
1159 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1161 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1163 rc = smbldap_add(ctx->smbldap_state, dn, mods);
1164 ldap_mods_free(mods, True);
1166 if (rc != LDAP_SUCCESS) {
1167 char *ld_error = NULL;
1168 ldap_get_option(ctx->smbldap_state->ldap_struct,
1169 LDAP_OPT_ERROR_STRING, &ld_error);
1170 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
1171 "mapping [%s]\n", sid,
1172 (unsigned long)map->xid.id, type));
1173 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1174 ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1176 ldap_memfree(ld_error);
1178 ret = NT_STATUS_UNSUCCESSFUL;
1182 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
1183 "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
1188 talloc_free(memctx);
1192 /**********************************
1193 Close the idmap ldap instance
1194 **********************************/
1196 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1198 struct idmap_ldap_context *ctx;
1200 if (dom->private_data) {
1201 ctx = talloc_get_type(dom->private_data,
1202 struct idmap_ldap_context);
1205 dom->private_data = NULL;
1208 return NT_STATUS_OK;
1211 static struct idmap_methods idmap_ldap_methods = {
1213 .init = idmap_ldap_db_init,
1214 .unixids_to_sids = idmap_ldap_unixids_to_sids,
1215 .sids_to_unixids = idmap_ldap_sids_to_unixids,
1216 .allocate_id = idmap_ldap_get_new_id,
1217 .close_fn = idmap_ldap_close
1220 NTSTATUS idmap_ldap_init(void);
1221 NTSTATUS idmap_ldap_init(void)
1223 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1224 &idmap_ldap_methods);