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;
64 uint32_t filter_low_id, filter_high_id; /* Filter range */
68 struct idmap_ldap_alloc_context {
69 struct smbldap_state *smbldap_state;
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 { \
80 DEBUG(0, ("Out of memory!\n")); \
81 ret = NT_STATUS_NO_MEMORY; \
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,
100 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
102 const char *tmp = NULL;
103 char *user_dn = NULL;
106 /* assume anonymous if we don't have a specified user */
108 tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
112 /* only the alloc backend can pass in a NULL dom */
113 secret = idmap_fetch_secret("ldap", True,
116 secret = idmap_fetch_secret("ldap", False,
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;
127 *dn = talloc_strdup(mem_ctx, tmp);
128 CHECK_ALLOC_DONE(*dn);
130 if (!fetch_ldap_pw(&user_dn, &secret)) {
131 DEBUG(2, ("get_credentials: Failed to lookup ldap "
132 "bind creds. Using anonymous connection.\n"));
135 *dn = talloc_strdup(mem_ctx, user_dn);
136 SAFE_FREE( user_dn );
137 CHECK_ALLOC_DONE(*dn);
141 smbldap_set_creds(ldap_state, anon, *dn, secret);
151 /**********************************************************************
152 Verify the sambaUnixIdPool entry in the directory.
153 **********************************************************************/
155 static NTSTATUS verify_idpool(void)
159 LDAPMessage *result = NULL;
160 LDAPMod **mods = NULL;
161 const char **attr_list;
166 if ( ! idmap_alloc_ldap) {
167 return NT_STATUS_UNSUCCESSFUL;
170 ctx = talloc_new(idmap_alloc_ldap);
172 DEBUG(0, ("Out of memory!\n"));
173 return NT_STATUS_NO_MEMORY;
176 filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
177 CHECK_ALLOC_DONE(filter);
179 attr_list = get_attr_list(ctx, idpool_attr_list);
180 CHECK_ALLOC_DONE(attr_list);
182 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
183 idmap_alloc_ldap->suffix,
190 if (rc != LDAP_SUCCESS) {
191 DEBUG(1, ("Unable to verify the idpool, "
192 "cannot continue initialization!\n"));
193 return NT_STATUS_UNSUCCESSFUL;
196 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
199 ldap_msgfree(result);
202 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
203 filter, idmap_alloc_ldap->suffix));
204 ret = NT_STATUS_UNSUCCESSFUL;
207 else if (count == 0) {
208 char *uid_str, *gid_str;
210 uid_str = talloc_asprintf(ctx, "%lu",
211 (unsigned long)idmap_alloc_ldap->low_uid);
212 gid_str = talloc_asprintf(ctx, "%lu",
213 (unsigned long)idmap_alloc_ldap->low_gid);
215 smbldap_set_mod(&mods, LDAP_MOD_ADD,
216 "objectClass", LDAP_OBJ_IDPOOL);
217 smbldap_set_mod(&mods, LDAP_MOD_ADD,
218 get_attr_key2string(idpool_attr_list,
219 LDAP_ATTR_UIDNUMBER),
221 smbldap_set_mod(&mods, LDAP_MOD_ADD,
222 get_attr_key2string(idpool_attr_list,
223 LDAP_ATTR_GIDNUMBER),
226 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
227 idmap_alloc_ldap->suffix,
229 ldap_mods_free(mods, True);
231 ret = NT_STATUS_UNSUCCESSFUL;
236 ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
242 /*****************************************************************************
243 Initialise idmap database.
244 *****************************************************************************/
246 static NTSTATUS idmap_ldap_alloc_init(const char *params)
248 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
255 /* Only do init if we are online */
256 if (idmap_is_offline()) {
257 return NT_STATUS_FILE_IS_OFFLINE;
260 idmap_alloc_ldap = TALLOC_ZERO_P(NULL, struct idmap_ldap_alloc_context);
261 CHECK_ALLOC_DONE( idmap_alloc_ldap );
265 if (!lp_idmap_uid(&low_uid, &high_uid)
266 || !lp_idmap_gid(&low_gid, &high_gid)) {
267 DEBUG(1, ("idmap uid or idmap gid missing\n"));
268 ret = NT_STATUS_UNSUCCESSFUL;
272 idmap_alloc_ldap->low_uid = low_uid;
273 idmap_alloc_ldap->high_uid = high_uid;
274 idmap_alloc_ldap->low_gid = low_gid;
275 idmap_alloc_ldap->high_gid= high_gid;
277 if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) {
278 DEBUG(1, ("idmap uid range invalid\n"));
279 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
280 ret = NT_STATUS_UNSUCCESSFUL;
284 if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) {
285 DEBUG(1, ("idmap gid range invalid\n"));
286 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
287 ret = NT_STATUS_UNSUCCESSFUL;
291 if (params && *params) {
292 /* assume location is the only parameter */
293 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
295 tmp = lp_parm_const_string(-1, "idmap alloc config",
299 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
300 ret = NT_STATUS_UNSUCCESSFUL;
304 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
306 CHECK_ALLOC_DONE( idmap_alloc_ldap->url );
308 trim_char(idmap_alloc_ldap->url, '\"', '\"');
310 tmp = lp_parm_const_string(-1, "idmap alloc config",
311 "ldap_base_dn", NULL);
312 if ( ! tmp || ! *tmp) {
313 tmp = lp_ldap_idmap_suffix();
315 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
316 ret = NT_STATUS_UNSUCCESSFUL;
321 idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
322 CHECK_ALLOC_DONE( idmap_alloc_ldap->suffix );
324 ret = smbldap_init(idmap_alloc_ldap, winbind_event_context(),
325 idmap_alloc_ldap->url,
326 &idmap_alloc_ldap->smbldap_state);
327 if (!NT_STATUS_IS_OK(ret)) {
328 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
329 idmap_alloc_ldap->url));
333 ret = get_credentials( idmap_alloc_ldap,
334 idmap_alloc_ldap->smbldap_state,
335 "idmap alloc config", NULL,
336 &idmap_alloc_ldap->user_dn );
337 if ( !NT_STATUS_IS_OK(ret) ) {
338 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
339 "credentials (%s)\n", nt_errstr(ret)));
343 /* see if the idmap suffix and sub entries exists */
345 ret = verify_idpool();
348 if ( !NT_STATUS_IS_OK( ret ) )
349 TALLOC_FREE( idmap_alloc_ldap );
354 /********************************
355 Allocate a new uid or gid
356 ********************************/
358 static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
361 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
362 int rc = LDAP_SERVER_DOWN;
364 LDAPMessage *result = NULL;
365 LDAPMessage *entry = NULL;
366 LDAPMod **mods = NULL;
370 const char *dn = NULL;
371 const char **attr_list;
374 /* Only do query if we are online */
375 if (idmap_is_offline()) {
376 return NT_STATUS_FILE_IS_OFFLINE;
379 if ( ! idmap_alloc_ldap) {
380 return NT_STATUS_UNSUCCESSFUL;
383 ctx = talloc_new(idmap_alloc_ldap);
385 DEBUG(0, ("Out of memory!\n"));
386 return NT_STATUS_NO_MEMORY;
393 type = get_attr_key2string(idpool_attr_list,
394 LDAP_ATTR_UIDNUMBER);
398 type = get_attr_key2string(idpool_attr_list,
399 LDAP_ATTR_GIDNUMBER);
403 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
404 return NT_STATUS_INVALID_PARAMETER;
407 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
408 CHECK_ALLOC_DONE(filter);
410 attr_list = get_attr_list(ctx, idpool_attr_list);
411 CHECK_ALLOC_DONE(attr_list);
413 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
415 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
416 idmap_alloc_ldap->suffix,
417 LDAP_SCOPE_SUBTREE, filter,
418 attr_list, 0, &result);
420 if (rc != LDAP_SUCCESS) {
421 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
425 talloc_autofree_ldapmsg(ctx, result);
427 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct,
430 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
434 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct,
437 dn = smbldap_talloc_dn(ctx,
438 idmap_alloc_ldap->smbldap_state->ldap_struct,
444 if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
445 entry, type, ctx))) {
446 DEBUG(0,("%s attribute not found\n", type));
450 DEBUG(0,("Out of memory\n"));
451 ret = NT_STATUS_NO_MEMORY;
455 xid->id = strtoul(id_str, NULL, 10);
457 /* make sure we still have room to grow */
461 if (xid->id > idmap_alloc_ldap->high_uid) {
462 DEBUG(0,("Cannot allocate uid above %lu!\n",
463 (unsigned long)idmap_alloc_ldap->high_uid));
469 if (xid->id > idmap_alloc_ldap->high_gid) {
470 DEBUG(0,("Cannot allocate gid above %lu!\n",
471 (unsigned long)idmap_alloc_ldap->high_uid));
481 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
483 DEBUG(0,("Out of memory\n"));
484 ret = NT_STATUS_NO_MEMORY;
488 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
489 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
492 DEBUG(0,("smbldap_set_mod() failed.\n"));
496 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
497 id_str, new_id_str));
499 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
501 ldap_mods_free(mods, True);
503 if (rc != LDAP_SUCCESS) {
504 DEBUG(1,("Failed to allocate new %s. "
505 "smbldap_modify() failed.\n", type));
516 /**********************************
517 Close idmap ldap alloc
518 **********************************/
520 static NTSTATUS idmap_ldap_alloc_close(void)
522 if (idmap_alloc_ldap) {
523 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
524 DEBUG(5,("The connection to the LDAP server was closed\n"));
525 /* maybe free the results here --metze */
526 TALLOC_FREE(idmap_alloc_ldap);
532 /**********************************************************************
533 IDMAP MAPPING LDAP BACKEND
534 **********************************************************************/
536 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
538 smbldap_free_struct(&ctx->smbldap_state);
539 DEBUG(5,("The connection to the LDAP server was closed\n"));
540 /* maybe free the results here --metze */
545 /********************************
546 Initialise idmap database.
547 ********************************/
549 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom,
553 struct idmap_ldap_context *ctx = NULL;
554 char *config_option = NULL;
555 const char *tmp = NULL;
557 /* Only do init if we are online */
558 if (idmap_is_offline()) {
559 return NT_STATUS_FILE_IS_OFFLINE;
562 ctx = TALLOC_ZERO_P(dom, struct idmap_ldap_context);
564 DEBUG(0, ("Out of memory!\n"));
565 return NT_STATUS_NO_MEMORY;
568 if (strequal(dom->name, "*")) {
569 /* more specific configuration can go here */
571 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
572 if ( ! config_option) {
573 DEBUG(0, ("Out of memory!\n"));
574 ret = NT_STATUS_NO_MEMORY;
579 if (params != NULL) {
580 /* assume location is the only parameter */
581 ctx->url = talloc_strdup(ctx, params);
583 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
586 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
587 ret = NT_STATUS_UNSUCCESSFUL;
591 ctx->url = talloc_strdup(ctx, tmp);
593 CHECK_ALLOC_DONE(ctx->url);
595 trim_char(ctx->url, '\"', '\"');
597 tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
598 if ( ! tmp || ! *tmp) {
599 tmp = lp_ldap_idmap_suffix();
601 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
602 ret = NT_STATUS_UNSUCCESSFUL;
607 ctx->suffix = talloc_strdup(ctx, tmp);
608 CHECK_ALLOC_DONE(ctx->suffix);
610 ret = smbldap_init(ctx, winbind_event_context(), ctx->url,
611 &ctx->smbldap_state);
612 if (!NT_STATUS_IS_OK(ret)) {
613 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
617 ret = get_credentials( ctx, ctx->smbldap_state, config_option,
618 dom, &ctx->user_dn );
619 if ( !NT_STATUS_IS_OK(ret) ) {
620 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
621 "credentials (%s)\n", nt_errstr(ret)));
625 /* set the destructor on the context, so that resource are properly
626 freed if the contexts is released */
628 talloc_set_destructor(ctx, idmap_ldap_close_destructor);
630 dom->private_data = ctx;
632 talloc_free(config_option);
641 /* max number of ids requested per batch query */
642 #define IDMAP_LDAP_MAX_IDS 30
644 /**********************************
645 lookup a set of unix ids.
646 **********************************/
648 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
649 * in maps for a match */
650 static struct id_map *find_map_by_id(struct id_map **maps,
656 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
657 if (maps[i] == NULL) { /* end of the run */
660 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
668 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
673 struct idmap_ldap_context *ctx;
674 LDAPMessage *result = NULL;
675 LDAPMessage *entry = NULL;
676 const char *uidNumber;
677 const char *gidNumber;
678 const char **attr_list;
687 /* Only do query if we are online */
688 if (idmap_is_offline()) {
689 return NT_STATUS_FILE_IS_OFFLINE;
692 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
694 memctx = talloc_new(ctx);
696 DEBUG(0, ("Out of memory!\n"));
697 return NT_STATUS_NO_MEMORY;
700 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
701 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
703 attr_list = get_attr_list(memctx, sidmap_attr_list);
706 /* if we are requested just one mapping use the simple filter */
708 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
709 LDAP_OBJ_IDMAP_ENTRY,
710 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
711 (unsigned long)ids[0]->xid.id);
712 CHECK_ALLOC_DONE(filter);
713 DEBUG(10, ("Filter: [%s]\n", filter));
715 /* multiple mappings */
719 for (i = 0; ids[i]; i++) {
720 ids[i]->status = ID_UNKNOWN;
727 filter = talloc_asprintf(memctx,
728 "(&(objectClass=%s)(|",
729 LDAP_OBJ_IDMAP_ENTRY);
730 CHECK_ALLOC_DONE(filter);
733 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
734 filter = talloc_asprintf_append_buffer(filter, "(%s=%lu)",
735 (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
736 (unsigned long)ids[idx]->xid.id);
737 CHECK_ALLOC_DONE(filter);
739 filter = talloc_asprintf_append_buffer(filter, "))");
740 CHECK_ALLOC_DONE(filter);
741 DEBUG(10, ("Filter: [%s]\n", filter));
747 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
748 filter, attr_list, 0, &result);
750 if (rc != LDAP_SUCCESS) {
751 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
752 ret = NT_STATUS_UNSUCCESSFUL;
756 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
759 DEBUG(10, ("NO SIDs found\n"));
762 for (i = 0; i < count; i++) {
769 if (i == 0) { /* first entry */
770 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
772 } else { /* following ones */
773 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
777 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
782 /* first check if the SID is present */
783 sidstr = smbldap_talloc_single_attribute(
784 ctx->smbldap_state->ldap_struct,
785 entry, LDAP_ATTRIBUTE_SID, memctx);
786 if ( ! sidstr) { /* no sid, skip entry */
787 DEBUG(2, ("WARNING SID not found on entry\n"));
791 /* now try to see if it is a uid, if not try with a gid
792 * (gid is more common, but in case both uidNumber and
793 * gidNumber are returned the SID is mapped to the uid
796 tmp = smbldap_talloc_single_attribute(
797 ctx->smbldap_state->ldap_struct,
798 entry, uidNumber, memctx);
801 tmp = smbldap_talloc_single_attribute(
802 ctx->smbldap_state->ldap_struct,
803 entry, gidNumber, memctx);
805 if ( ! tmp) { /* wow very strange entry, how did it match ? */
806 DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
807 "nor gidNumber returned\n", sidstr));
812 id = strtoul(tmp, NULL, 10);
813 if (!idmap_unix_id_is_in_range(id, dom)) {
814 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
816 dom->low_id, dom->high_id));
823 map = find_map_by_id(&ids[bidx], type, id);
825 DEBUG(2, ("WARNING: couldn't match sid (%s) "
826 "with requested ids\n", sidstr));
831 if ( ! string_to_sid(map->sid, sidstr)) {
832 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
837 if (map->status == ID_MAPPED) {
838 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
839 "overwriting mapping %u -> %s with %u -> %s\n",
840 (type == ID_TYPE_UID) ? "UID" : "GID",
841 id, sid_string_dbg(map->sid), id, sidstr));
847 map->status = ID_MAPPED;
849 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
850 (unsigned long)map->xid.id, map->xid.type));
853 /* free the ldap results */
855 ldap_msgfree(result);
859 if (multi && ids[idx]) { /* still some values to map */
865 /* mark all unknwon/expired ones as unmapped */
866 for (i = 0; ids[i]; i++) {
867 if (ids[i]->status != ID_MAPPED)
868 ids[i]->status = ID_UNMAPPED;
876 /**********************************
877 lookup a set of sids.
878 **********************************/
880 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
881 * in maps for a match */
882 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
886 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
887 if (maps[i] == NULL) { /* end of the run */
890 if (sid_equal(maps[i]->sid, sid)) {
898 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
901 LDAPMessage *entry = NULL;
904 struct idmap_ldap_context *ctx;
905 LDAPMessage *result = NULL;
906 const char *uidNumber;
907 const char *gidNumber;
908 const char **attr_list;
917 /* Only do query if we are online */
918 if (idmap_is_offline()) {
919 return NT_STATUS_FILE_IS_OFFLINE;
922 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
924 memctx = talloc_new(ctx);
926 DEBUG(0, ("Out of memory!\n"));
927 return NT_STATUS_NO_MEMORY;
930 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
931 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
933 attr_list = get_attr_list(memctx, sidmap_attr_list);
936 /* if we are requested just one mapping use the simple filter */
938 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
939 LDAP_OBJ_IDMAP_ENTRY,
941 sid_string_talloc(memctx, ids[0]->sid));
942 CHECK_ALLOC_DONE(filter);
943 DEBUG(10, ("Filter: [%s]\n", filter));
945 /* multiple mappings */
949 for (i = 0; ids[i]; i++) {
950 ids[i]->status = ID_UNKNOWN;
957 filter = talloc_asprintf(memctx,
958 "(&(objectClass=%s)(|",
959 LDAP_OBJ_IDMAP_ENTRY);
960 CHECK_ALLOC_DONE(filter);
963 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
964 filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
966 sid_string_talloc(memctx,
968 CHECK_ALLOC_DONE(filter);
970 filter = talloc_asprintf_append_buffer(filter, "))");
971 CHECK_ALLOC_DONE(filter);
972 DEBUG(10, ("Filter: [%s]", filter));
978 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
979 filter, attr_list, 0, &result);
981 if (rc != LDAP_SUCCESS) {
982 DEBUG(3,("Failure looking up sids (%s)\n",
983 ldap_err2string(rc)));
984 ret = NT_STATUS_UNSUCCESSFUL;
988 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
991 DEBUG(10, ("NO SIDs found\n"));
994 for (i = 0; i < count; i++) {
1002 if (i == 0) { /* first entry */
1003 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct,
1005 } else { /* following ones */
1006 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct,
1010 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1015 /* first check if the SID is present */
1016 sidstr = smbldap_talloc_single_attribute(
1017 ctx->smbldap_state->ldap_struct,
1018 entry, LDAP_ATTRIBUTE_SID, memctx);
1019 if ( ! sidstr) { /* no sid ??, skip entry */
1020 DEBUG(2, ("WARNING SID not found on entry\n"));
1024 if ( ! string_to_sid(&sid, sidstr)) {
1025 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1026 TALLOC_FREE(sidstr);
1030 map = find_map_by_sid(&ids[bidx], &sid);
1032 DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1034 TALLOC_FREE(sidstr);
1038 /* now try to see if it is a uid, if not try with a gid
1039 * (gid is more common, but in case both uidNumber and
1040 * gidNumber are returned the SID is mapped to the uid
1043 tmp = smbldap_talloc_single_attribute(
1044 ctx->smbldap_state->ldap_struct,
1045 entry, uidNumber, memctx);
1048 tmp = smbldap_talloc_single_attribute(
1049 ctx->smbldap_state->ldap_struct,
1050 entry, gidNumber, memctx);
1052 if ( ! tmp) { /* no ids ?? */
1053 DEBUG(5, ("no uidNumber, "
1054 "nor gidNumber attributes found\n"));
1055 TALLOC_FREE(sidstr);
1059 id = strtoul(tmp, NULL, 10);
1060 if (!idmap_unix_id_is_in_range(id, dom)) {
1061 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1063 dom->low_id, dom->high_id));
1064 TALLOC_FREE(sidstr);
1070 if (map->status == ID_MAPPED) {
1071 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1072 "overwriting mapping %s -> %u with %s -> %u\n",
1073 (type == ID_TYPE_UID) ? "UID" : "GID",
1074 sidstr, map->xid.id, sidstr, id));
1077 TALLOC_FREE(sidstr);
1080 map->xid.type = type;
1082 map->status = ID_MAPPED;
1084 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
1085 (unsigned long)map->xid.id, map->xid.type));
1088 /* free the ldap results */
1090 ldap_msgfree(result);
1094 if (multi && ids[idx]) { /* still some values to map */
1100 /* mark all unknwon/expired ones as unmapped */
1101 for (i = 0; ids[i]; i++) {
1102 if (ids[i]->status != ID_MAPPED)
1103 ids[i]->status = ID_UNMAPPED;
1107 talloc_free(memctx);
1111 /**********************************
1113 **********************************/
1115 /* TODO: change this: This function cannot be called to modify a mapping,
1116 * only set a new one */
1118 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom,
1119 const struct id_map *map)
1123 struct idmap_ldap_context *ctx;
1124 LDAPMessage *entry = NULL;
1125 LDAPMod **mods = NULL;
1132 /* Only do query if we are online */
1133 if (idmap_is_offline()) {
1134 return NT_STATUS_FILE_IS_OFFLINE;
1137 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1139 switch(map->xid.type) {
1141 type = get_attr_key2string(sidmap_attr_list,
1142 LDAP_ATTR_UIDNUMBER);
1146 type = get_attr_key2string(sidmap_attr_list,
1147 LDAP_ATTR_GIDNUMBER);
1151 return NT_STATUS_INVALID_PARAMETER;
1154 memctx = talloc_new(ctx);
1156 DEBUG(0, ("Out of memory!\n"));
1157 return NT_STATUS_NO_MEMORY;
1160 id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1161 CHECK_ALLOC_DONE(id_str);
1163 sid = talloc_strdup(memctx, sid_string_talloc(memctx, map->sid));
1164 CHECK_ALLOC_DONE(sid);
1166 dn = talloc_asprintf(memctx, "%s=%s,%s",
1167 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1170 CHECK_ALLOC_DONE(dn);
1172 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1173 "objectClass", LDAP_OBJ_IDMAP_ENTRY);
1175 smbldap_make_mod(ctx->smbldap_state->ldap_struct,
1176 entry, &mods, type, id_str);
1178 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1179 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1183 DEBUG(2, ("ERROR: No mods?\n"));
1184 ret = NT_STATUS_UNSUCCESSFUL;
1188 /* TODO: remove conflicting mappings! */
1190 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1192 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1194 rc = smbldap_add(ctx->smbldap_state, dn, mods);
1195 ldap_mods_free(mods, True);
1197 if (rc != LDAP_SUCCESS) {
1198 char *ld_error = NULL;
1199 ldap_get_option(ctx->smbldap_state->ldap_struct,
1200 LDAP_OPT_ERROR_STRING, &ld_error);
1201 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
1202 "mapping [%s]\n", sid,
1203 (unsigned long)map->xid.id, type));
1204 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1205 ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1207 ldap_memfree(ld_error);
1209 ret = NT_STATUS_UNSUCCESSFUL;
1213 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
1214 "%lu [%s]\n", sid, (unsigned long)map->xid.id, type));
1219 talloc_free(memctx);
1223 /**********************************
1224 Close the idmap ldap instance
1225 **********************************/
1227 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1229 struct idmap_ldap_context *ctx;
1231 if (dom->private_data) {
1232 ctx = talloc_get_type(dom->private_data,
1233 struct idmap_ldap_context);
1236 dom->private_data = NULL;
1239 return NT_STATUS_OK;
1242 static struct idmap_methods idmap_ldap_methods = {
1244 .init = idmap_ldap_db_init,
1245 .unixids_to_sids = idmap_ldap_unixids_to_sids,
1246 .sids_to_unixids = idmap_ldap_sids_to_unixids,
1247 .allocate_id = idmap_ldap_get_new_id,
1248 .close_fn = idmap_ldap_close
1251 NTSTATUS idmap_ldap_init(void);
1252 NTSTATUS idmap_ldap_init(void)
1254 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap",
1255 &idmap_ldap_methods);