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-2006
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 2 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, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define DBGC_CLASS DBGC_IDMAP
36 struct idmap_ldap_alloc_context {
37 struct smbldap_state *smbldap_state;
41 uid_t low_uid, high_uid; /* Range of uids */
42 gid_t low_gid, high_gid; /* Range of gids */
46 #define CHECK_ALLOC_DONE(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while (0)
48 /**********************************************************************
49 IDMAP ALLOC TDB BACKEND
50 **********************************************************************/
52 static struct idmap_ldap_alloc_context *idmap_alloc_ldap;
54 /**********************************************************************
55 Verify the sambaUnixIdPool entry in the directory.
56 **********************************************************************/
58 static NTSTATUS verify_idpool(void)
62 LDAPMessage *result = NULL;
63 LDAPMod **mods = NULL;
64 const char **attr_list;
69 if ( ! idmap_alloc_ldap) {
70 return NT_STATUS_UNSUCCESSFUL;
73 ctx = talloc_new(idmap_alloc_ldap);
75 DEBUG(0, ("Out of memory!\n"));
76 return NT_STATUS_NO_MEMORY;
79 filter = talloc_asprintf(ctx, "(objectclass=%s)", LDAP_OBJ_IDPOOL);
80 CHECK_ALLOC_DONE(filter);
82 attr_list = get_attr_list(ctx, idpool_attr_list);
83 CHECK_ALLOC_DONE(attr_list);
85 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
86 idmap_alloc_ldap->suffix,
93 if (rc != LDAP_SUCCESS) {
94 return NT_STATUS_UNSUCCESSFUL;
97 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
102 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
103 filter, idmap_alloc_ldap->suffix));
104 ret = NT_STATUS_UNSUCCESSFUL;
107 else if (count == 0) {
108 char *uid_str, *gid_str;
110 uid_str = talloc_asprintf(ctx, "%lu", (unsigned long)idmap_alloc_ldap->low_uid);
111 gid_str = talloc_asprintf(ctx, "%lu", (unsigned long)idmap_alloc_ldap->low_gid);
113 smbldap_set_mod(&mods, LDAP_MOD_ADD,
114 "objectClass", LDAP_OBJ_IDPOOL);
115 smbldap_set_mod(&mods, LDAP_MOD_ADD,
116 get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER),
118 smbldap_set_mod(&mods, LDAP_MOD_ADD,
119 get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER),
122 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state,
123 idmap_alloc_ldap->suffix,
125 ldap_mods_free(mods, True);
127 ret = NT_STATUS_UNSUCCESSFUL;
132 ret = (rc == LDAP_SUCCESS)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
138 /*****************************************************************************
139 Initialise idmap database.
140 *****************************************************************************/
142 static NTSTATUS idmap_ldap_alloc_init(const char *params)
153 idmap_alloc_ldap = talloc_zero(NULL, struct idmap_ldap_alloc_context);
154 if (!idmap_alloc_ldap) {
155 DEBUG(0, ("Out of memory!\n"));
156 return NT_STATUS_NO_MEMORY;
160 idmap_alloc_ldap->low_uid = 0;
161 idmap_alloc_ldap->high_uid = 0;
162 idmap_alloc_ldap->low_gid = 0;
163 idmap_alloc_ldap->high_gid = 0;
165 range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL);
166 if (range && range[0]) {
167 unsigned low_id, high_id;
169 if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) {
170 if (low_id < high_id) {
171 idmap_alloc_ldap->low_gid = idmap_alloc_ldap->low_uid = low_id;
172 idmap_alloc_ldap->high_gid = idmap_alloc_ldap->high_uid = high_id;
174 DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range));
177 DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range));
181 if (lp_idmap_uid(&low_uid, &high_uid)) {
182 idmap_alloc_ldap->low_uid = low_uid;
183 idmap_alloc_ldap->high_uid = high_uid;
186 if (lp_idmap_gid(&low_gid, &high_gid)) {
187 idmap_alloc_ldap->low_gid = low_gid;
188 idmap_alloc_ldap->high_gid= high_gid;
191 if (idmap_alloc_ldap->high_uid <= idmap_alloc_ldap->low_uid) {
192 DEBUG(1, ("idmap uid range missing or invalid\n"));
193 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
194 talloc_free(idmap_alloc_ldap);
195 return NT_STATUS_UNSUCCESSFUL;
198 if (idmap_alloc_ldap->high_gid <= idmap_alloc_ldap->low_gid) {
199 DEBUG(1, ("idmap gid range missing or invalid\n"));
200 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
201 talloc_free(idmap_alloc_ldap);
202 return NT_STATUS_UNSUCCESSFUL;
205 if (params && *params) {
206 /* assume location is the only parameter */
207 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, params);
209 tmp = lp_parm_const_string(-1, "idmap alloc config", "ldap_url", NULL);
212 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
213 talloc_free(idmap_alloc_ldap);
214 return NT_STATUS_UNSUCCESSFUL;
217 idmap_alloc_ldap->url = talloc_strdup(idmap_alloc_ldap, tmp);
219 if ( ! idmap_alloc_ldap->url) {
220 talloc_free(idmap_alloc_ldap);
221 DEBUG(0, ("Out of memory!\n"));
222 return NT_STATUS_NO_MEMORY;
225 tmp = lp_ldap_idmap_suffix();
226 if ( ! tmp || ! *tmp) {
227 tmp = lp_parm_const_string(-1, "idmap alloc config", "ldap_base_dn", NULL);
230 tmp = lp_ldap_suffix();
232 DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp));
233 DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
237 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
238 talloc_free(idmap_alloc_ldap);
239 return NT_STATUS_UNSUCCESSFUL;
241 idmap_alloc_ldap->suffix = talloc_strdup(idmap_alloc_ldap, tmp);
242 if ( ! idmap_alloc_ldap->suffix) {
243 talloc_free(idmap_alloc_ldap);
244 DEBUG(0, ("Out of memory!\n"));
245 return NT_STATUS_NO_MEMORY;
248 tmp = lp_parm_const_string(-1, "idmap alloc config", "ldap_user_dn", NULL);
251 tmp = lp_ldap_admin_dn();
253 if (! tmp || ! *tmp) {
254 DEBUG(1, ("ERROR: missing idmap ldap user dn\n"));
255 talloc_free(idmap_alloc_ldap);
256 return NT_STATUS_UNSUCCESSFUL;
259 idmap_alloc_ldap->user_dn = talloc_strdup(idmap_alloc_ldap, tmp);
260 if ( ! idmap_alloc_ldap->user_dn) {
261 talloc_free(idmap_alloc_ldap);
262 DEBUG(0, ("Out of memory!\n"));
263 return NT_STATUS_NO_MEMORY;
266 if (!NT_STATUS_IS_OK(nt_status =
267 smbldap_init(idmap_alloc_ldap, idmap_alloc_ldap->url,
268 &idmap_alloc_ldap->smbldap_state))) {
269 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
270 idmap_alloc_ldap->url));
271 talloc_free(idmap_alloc_ldap);
275 /* fetch credentials from secrets.tdb */
276 secret = idmap_fecth_secret("ldap", true, NULL, idmap_alloc_ldap->user_dn);
278 DEBUG(1, ("ERROR: unable to fetch auth credentials\n"));
279 talloc_free(idmap_alloc_ldap);
280 return NT_STATUS_ACCESS_DENIED;
282 /* now set credentials */
283 smbldap_set_creds(idmap_alloc_ldap->smbldap_state, false, idmap_alloc_ldap->user_dn, secret);
285 /* see if the idmap suffix and sub entries exists */
286 nt_status = verify_idpool();
287 if (!NT_STATUS_IS_OK(nt_status)) {
288 talloc_free(idmap_alloc_ldap);
295 /********************************
296 Allocate a new uid or gid
297 ********************************/
299 static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
302 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
303 int rc = LDAP_SERVER_DOWN;
305 LDAPMessage *result = NULL;
306 LDAPMessage *entry = NULL;
307 LDAPMod **mods = NULL;
311 const char *dn = NULL;
312 const char **attr_list;
315 if ( ! idmap_alloc_ldap) {
316 return NT_STATUS_UNSUCCESSFUL;
319 ctx = talloc_new(idmap_alloc_ldap);
321 DEBUG(0, ("Out of memory!\n"));
322 return NT_STATUS_NO_MEMORY;
329 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
333 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
337 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
338 return NT_STATUS_INVALID_PARAMETER;
341 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
342 CHECK_ALLOC_DONE(filter);
344 attr_list = get_attr_list(ctx, idpool_attr_list);
345 CHECK_ALLOC_DONE(attr_list);
347 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter));
349 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
350 idmap_alloc_ldap->suffix,
351 LDAP_SCOPE_SUBTREE, filter,
352 attr_list, 0, &result);
354 if (rc != LDAP_SUCCESS) {
355 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
359 talloc_autofree_ldapmsg(ctx, result);
361 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
363 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
367 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
369 dn = smbldap_talloc_dn(ctx, idmap_alloc_ldap->smbldap_state->ldap_struct, entry);
374 if ( ! (id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
375 entry, type, ctx))) {
376 DEBUG(0,("%s attribute not found\n", type));
380 DEBUG(0,("Out of memory\n"));
381 ret = NT_STATUS_NO_MEMORY;
385 xid->id = strtoul(id_str, NULL, 10);
387 /* make sure we still have room to grow */
391 if (xid->id > idmap_alloc_ldap->high_uid) {
392 DEBUG(0,("Cannot allocate uid above %lu!\n",
393 (unsigned long)idmap_alloc_ldap->high_uid));
399 if (xid->id > idmap_alloc_ldap->high_gid) {
400 DEBUG(0,("Cannot allocate gid above %lu!\n",
401 (unsigned long)idmap_alloc_ldap->high_uid));
411 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id + 1);
413 DEBUG(0,("Out of memory\n"));
414 ret = NT_STATUS_NO_MEMORY;
418 smbldap_set_mod(&mods, LDAP_MOD_DELETE, type, id_str);
419 smbldap_set_mod(&mods, LDAP_MOD_ADD, type, new_id_str);
422 DEBUG(0,("smbldap_set_mod() failed.\n"));
426 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n", id_str, new_id_str));
428 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
430 ldap_mods_free(mods, True);
432 if (rc != LDAP_SUCCESS) {
433 DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type));
444 /**********************************
445 Get current highest id.
446 **********************************/
448 static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
451 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
452 int rc = LDAP_SERVER_DOWN;
454 LDAPMessage *result = NULL;
455 LDAPMessage *entry = NULL;
458 const char **attr_list;
461 if ( ! idmap_alloc_ldap) {
462 return NT_STATUS_UNSUCCESSFUL;
465 memctx = talloc_new(idmap_alloc_ldap);
467 DEBUG(0, ("Out of memory!\n"));
468 return NT_STATUS_NO_MEMORY;
475 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
479 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
483 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
484 return NT_STATUS_INVALID_PARAMETER;
487 filter = talloc_asprintf(memctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
488 CHECK_ALLOC_DONE(filter);
490 attr_list = get_attr_list(memctx, idpool_attr_list);
491 CHECK_ALLOC_DONE(attr_list);
493 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
494 idmap_alloc_ldap->suffix,
495 LDAP_SCOPE_SUBTREE, filter,
496 attr_list, 0, &result);
498 if (rc != LDAP_SUCCESS) {
499 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
503 talloc_autofree_ldapmsg(memctx, result);
505 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
507 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
511 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
513 id_str = smbldap_talloc_single_attribute(idmap_alloc_ldap->smbldap_state->ldap_struct,
514 entry, type, memctx);
516 DEBUG(0,("%s attribute not found\n", type));
520 DEBUG(0,("Out of memory\n"));
521 ret = NT_STATUS_NO_MEMORY;
525 xid->id = strtoul(id_str, NULL, 10);
532 /**********************************
534 **********************************/
536 static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
539 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
540 int rc = LDAP_SERVER_DOWN;
542 LDAPMessage *result = NULL;
543 LDAPMessage *entry = NULL;
544 LDAPMod **mods = NULL;
547 const char *dn = NULL;
548 const char **attr_list;
551 if ( ! idmap_alloc_ldap) {
552 return NT_STATUS_UNSUCCESSFUL;
555 ctx = talloc_new(idmap_alloc_ldap);
557 DEBUG(0, ("Out of memory!\n"));
558 return NT_STATUS_NO_MEMORY;
565 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
569 type = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
573 DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
574 return NT_STATUS_INVALID_PARAMETER;
577 filter = talloc_asprintf(ctx, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
578 CHECK_ALLOC_DONE(filter);
580 attr_list = get_attr_list(ctx, idpool_attr_list);
581 CHECK_ALLOC_DONE(attr_list);
583 rc = smbldap_search(idmap_alloc_ldap->smbldap_state,
584 idmap_alloc_ldap->suffix,
585 LDAP_SCOPE_SUBTREE, filter,
586 attr_list, 0, &result);
588 if (rc != LDAP_SUCCESS) {
589 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL));
593 talloc_autofree_ldapmsg(ctx, result);
595 count = ldap_count_entries(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
597 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL));
601 entry = ldap_first_entry(idmap_alloc_ldap->smbldap_state->ldap_struct, result);
603 dn = smbldap_talloc_dn(ctx, idmap_alloc_ldap->smbldap_state->ldap_struct, entry);
608 new_id_str = talloc_asprintf(ctx, "%lu", (unsigned long)xid->id);
610 DEBUG(0,("Out of memory\n"));
611 ret = NT_STATUS_NO_MEMORY;
615 smbldap_set_mod(&mods, LDAP_MOD_REPLACE, type, new_id_str);
618 DEBUG(0,("smbldap_set_mod() failed.\n"));
622 rc = smbldap_modify(idmap_alloc_ldap->smbldap_state, dn, mods);
624 ldap_mods_free(mods, True);
626 if (rc != LDAP_SUCCESS) {
627 DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type));
638 /**********************************
639 Close idmap ldap alloc
640 **********************************/
642 static NTSTATUS idmap_ldap_alloc_close(void)
644 if (idmap_alloc_ldap) {
645 smbldap_free_struct(&idmap_alloc_ldap->smbldap_state);
646 DEBUG(5,("The connection to the LDAP server was closed\n"));
647 /* maybe free the results here --metze */
648 TALLOC_FREE(idmap_alloc_ldap);
654 /**********************************************************************
655 IDMAP MAPPING LDAP BACKEND
656 **********************************************************************/
658 struct idmap_ldap_context {
659 struct smbldap_state *smbldap_state;
663 uint32_t filter_low_id, filter_high_id; /* Filter range */
667 static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
669 smbldap_free_struct(&ctx->smbldap_state);
670 DEBUG(5,("The connection to the LDAP server was closed\n"));
671 /* maybe free the results here --metze */
676 /********************************
677 Initialise idmap database.
678 ********************************/
680 static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, const char *params)
683 struct idmap_ldap_context *ctx;
689 ctx = talloc_zero(dom, struct idmap_ldap_context);
691 DEBUG(0, ("Out of memory!\n"));
692 return NT_STATUS_NO_MEMORY;
695 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
696 if ( ! config_option) {
697 DEBUG(0, ("Out of memory!\n"));
698 ret = NT_STATUS_NO_MEMORY;
703 range = lp_parm_const_string(-1, config_option, "range", NULL);
704 if (range && range[0]) {
705 if ((sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
706 (ctx->filter_low_id > ctx->filter_high_id)) {
707 DEBUG(1, ("ERROR: invalid filter range [%s]", range));
708 ctx->filter_low_id = 0;
709 ctx->filter_high_id = 0;
713 if (params && *params) {
714 /* assume location is the only parameter */
715 ctx->url = talloc_strdup(ctx, params);
717 tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
720 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
721 ret = NT_STATUS_UNSUCCESSFUL;
725 ctx->url = talloc_strdup(ctx, tmp);
727 CHECK_ALLOC_DONE(ctx->url);
729 tmp = lp_ldap_idmap_suffix();
730 if ( ! tmp || ! *tmp) {
731 tmp = lp_parm_const_string(-1, config_option, "ldap_base_dn", NULL);
734 tmp = lp_ldap_suffix();
736 DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp));
737 DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
741 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
742 ret = NT_STATUS_UNSUCCESSFUL;
745 ctx->suffix = talloc_strdup(ctx, tmp);
746 CHECK_ALLOC_DONE(ctx->suffix);
748 ctx->anon = lp_parm_bool(-1, config_option, "ldap_anon", False);
750 ret = smbldap_init(ctx, ctx->url, &ctx->smbldap_state);
751 if (!NT_STATUS_IS_OK(ret)) {
752 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx->url));
757 tmp = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
760 tmp = lp_ldap_admin_dn();
762 if (! tmp || ! *tmp) {
763 DEBUG(1, ("ERROR: missing idmap ldap user dn\n"));
764 ret = NT_STATUS_UNSUCCESSFUL;
768 ctx->user_dn = talloc_strdup(ctx, tmp);
769 CHECK_ALLOC_DONE(ctx->user_dn);
771 /* fetch credentials */
772 secret = idmap_fecth_secret("ldap", false, dom->name, ctx->user_dn);
774 DEBUG(1, ("ERROR: unable to fetch auth credentials\n"));
775 ret = NT_STATUS_ACCESS_DENIED;
778 /* now set credentials */
779 smbldap_set_creds(ctx->smbldap_state, false, ctx->user_dn, secret);
781 smbldap_set_creds(ctx->smbldap_state, true, NULL, NULL);
784 /* set the destructor on the context, so that resource are properly
785 * freed if the contexts is released */
786 talloc_set_destructor(ctx, idmap_ldap_close_destructor);
788 dom->private_data = ctx;
790 talloc_free(config_option);
799 /* max number of ids requested per batch query */
800 #define IDMAP_LDAP_MAX_IDS 30
802 /**********************************
803 lookup a set of unix ids.
804 **********************************/
806 /* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
807 static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id)
811 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
812 if (maps[i] == NULL) { /* end of the run */
815 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
823 static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
827 struct idmap_ldap_context *ctx;
828 LDAPMessage *result = NULL;
829 const char *uidNumber;
830 const char *gidNumber;
831 const char **attr_list;
840 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
842 memctx = talloc_new(ctx);
844 DEBUG(0, ("Out of memory!\n"));
845 return NT_STATUS_NO_MEMORY;
848 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
849 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
851 attr_list = get_attr_list(ctx, sidmap_attr_list);
854 /* if we are requested just one mapping use the simple filter */
856 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%lu))",
857 LDAP_OBJ_IDMAP_ENTRY,
858 (ids[0]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
859 (unsigned long)ids[0]->xid.id);
860 CHECK_ALLOC_DONE(filter);
861 DEBUG(10, ("Filter: [%s]\n", filter));
863 /* multiple mappings */
871 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY);
872 CHECK_ALLOC_DONE(filter);
875 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
876 filter = talloc_asprintf_append(filter, "(%s=%lu)",
877 (ids[idx]->xid.type==ID_TYPE_UID)?uidNumber:gidNumber,
878 (unsigned long)ids[idx]->xid.id);
879 CHECK_ALLOC_DONE(filter);
881 filter = talloc_asprintf_append(filter, "))");
882 CHECK_ALLOC_DONE(filter);
883 DEBUG(10, ("Filter: [%s]\n", filter));
889 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
890 filter, attr_list, 0, &result);
892 if (rc != LDAP_SUCCESS) {
893 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc)));
894 ret = NT_STATUS_UNSUCCESSFUL;
898 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
901 DEBUG(10, ("NO SIDs found\n"));
904 for (i = 0; i < count; i++) {
905 LDAPMessage *entry = NULL;
912 if (i == 0) { /* first entry */
913 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result);
914 } else { /* following ones */
915 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, entry);
918 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
922 /* first check if the SID is present */
923 sidstr = smbldap_talloc_single_attribute(
924 ctx->smbldap_state->ldap_struct,
925 entry, LDAP_ATTRIBUTE_SID, memctx);
926 if ( ! sidstr) { /* no sid, skip entry */
927 DEBUG(2, ("WARNING SID not found on entry\n"));
931 /* now try to see if it is a uid, if not try with a gid
932 * (gid is more common, but in case both uidNumber and
933 * gidNumber are returned the SID is mapped to the uid not the gid) */
935 tmp = smbldap_talloc_single_attribute(
936 ctx->smbldap_state->ldap_struct,
937 entry, uidNumber, memctx);
940 tmp = smbldap_talloc_single_attribute(
941 ctx->smbldap_state->ldap_struct,
942 entry, gidNumber, memctx);
944 if ( ! tmp) { /* wow very strange entry, how did it match ? */
945 DEBUG(5, ("Unprobable match on (%s), no uidNumber, nor gidNumber returned\n", sidstr));
950 id = strtoul(tmp, NULL, 10);
952 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
953 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
954 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
955 id, ctx->filter_low_id, ctx->filter_high_id));
962 map = find_map_by_id(&ids[bidx], type, id);
964 DEBUG(2, ("WARNING: couldn't match sid (%s) with requested ids\n", sidstr));
969 if ( ! string_to_sid(map->sid, sidstr)) {
970 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
977 map->status = ID_MAPPED;
979 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map->sid), (unsigned long)map->xid.id, map->xid.type));
982 /* free the ldap results */
984 ldap_msgfree(result);
988 if (multi && ids[idx]) { /* still some values to map */
995 /* mark all unknwon ones as unmapped */
996 for (i = 0; ids[i]; i++) {
997 if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
1001 talloc_free(memctx);
1005 /**********************************
1006 lookup a set of sids.
1007 **********************************/
1009 /* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
1010 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
1014 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
1015 if (maps[i] == NULL) { /* end of the run */
1018 if (sid_equal(maps[i]->sid, sid)) {
1026 static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
1030 struct idmap_ldap_context *ctx;
1031 LDAPMessage *result = NULL;
1032 const char *uidNumber;
1033 const char *gidNumber;
1034 const char **attr_list;
1035 char *filter = NULL;
1043 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1045 memctx = talloc_new(ctx);
1047 DEBUG(0, ("Out of memory!\n"));
1048 return NT_STATUS_NO_MEMORY;
1051 uidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER);
1052 gidNumber = get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER);
1054 attr_list = get_attr_list(ctx, sidmap_attr_list);
1057 /* if we are requested just one mapping use the simple filter */
1059 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(%s=%s))",
1060 LDAP_OBJ_IDMAP_ENTRY,
1062 sid_string_static(ids[0]->sid));
1063 CHECK_ALLOC_DONE(filter);
1064 DEBUG(10, ("Filter: [%s]\n", filter));
1066 /* multiple mappings */
1073 TALLOC_FREE(filter);
1074 filter = talloc_asprintf(memctx, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY);
1075 CHECK_ALLOC_DONE(filter);
1078 for (i = 0; (i < IDMAP_LDAP_MAX_IDS) && ids[idx]; i++, idx++) {
1079 filter = talloc_asprintf_append(filter, "(%s=%s)",
1081 sid_string_static(ids[idx]->sid));
1082 CHECK_ALLOC_DONE(filter);
1084 filter = talloc_asprintf_append(filter, "))");
1085 CHECK_ALLOC_DONE(filter);
1086 DEBUG(10, ("Filter: [%s]", filter));
1092 rc = smbldap_search(ctx->smbldap_state, ctx->suffix, LDAP_SCOPE_SUBTREE,
1093 filter, attr_list, 0, &result);
1095 if (rc != LDAP_SUCCESS) {
1096 DEBUG(3,("Failure looking up sids (%s)\n", ldap_err2string(rc)));
1097 ret = NT_STATUS_UNSUCCESSFUL;
1101 count = ldap_count_entries(ctx->smbldap_state->ldap_struct, result);
1104 DEBUG(10, ("NO SIDs found\n"));
1107 for (i = 0; i < count; i++) {
1108 LDAPMessage *entry = NULL;
1109 char *sidstr = NULL;
1116 if (i == 0) { /* first entry */
1117 entry = ldap_first_entry(ctx->smbldap_state->ldap_struct, result);
1118 } else { /* following ones */
1119 entry = ldap_next_entry(ctx->smbldap_state->ldap_struct, entry);
1122 /* first check if the SID is present */
1123 sidstr = smbldap_talloc_single_attribute(
1124 ctx->smbldap_state->ldap_struct,
1125 entry, LDAP_ATTRIBUTE_SID, memctx);
1126 if ( ! sidstr) { /* no sid ??, skip entry */
1127 DEBUG(2, ("WARNING SID not found on entry\n"));
1131 if ( ! string_to_sid(&sid, sidstr)) {
1132 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1133 TALLOC_FREE(sidstr);
1137 map = find_map_by_sid(&ids[bidx], &sid);
1139 DEBUG(2, ("WARNING: couldn't find entry sid (%s) in ids", sidstr));
1140 TALLOC_FREE(sidstr);
1144 TALLOC_FREE(sidstr);
1146 /* now try to see if it is a uid, if not try with a gid
1147 * (gid is more common, but in case both uidNumber and
1148 * gidNumber are returned the SID is mapped to the uid not the gid) */
1150 tmp = smbldap_talloc_single_attribute(
1151 ctx->smbldap_state->ldap_struct,
1152 entry, uidNumber, memctx);
1155 tmp = smbldap_talloc_single_attribute(
1156 ctx->smbldap_state->ldap_struct,
1157 entry, gidNumber, memctx);
1159 if ( ! tmp) { /* no ids ?? */
1160 DEBUG(5, ("no uidNumber, nor gidNumber attributes found\n"));
1164 id = strtoul(tmp, NULL, 10);
1166 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
1167 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
1168 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
1169 id, ctx->filter_low_id, ctx->filter_high_id));
1176 map->xid.type = type;
1178 map->status = ID_MAPPED;
1180 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map->sid), (unsigned long)map->xid.id, map->xid.type));
1183 /* free the ldap results */
1185 ldap_msgfree(result);
1189 if (multi && ids[idx]) { /* still some values to map */
1195 /* mark all unknwon ones as unmapped */
1196 for (i = 0; ids[i]; i++) {
1197 if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
1201 talloc_free(memctx);
1205 /**********************************
1207 **********************************/
1209 /* TODO: change this: This function cannot be called to modify a mapping, only set a new one */
1211 static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id_map *map)
1215 struct idmap_ldap_context *ctx;
1216 LDAPMessage *entry = NULL;
1217 LDAPMod **mods = NULL;
1224 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1226 switch(map->xid.type) {
1228 type = get_attr_key2string(sidmap_attr_list, LDAP_ATTR_UIDNUMBER);
1232 type = get_attr_key2string(sidmap_attr_list, LDAP_ATTR_GIDNUMBER);
1236 return NT_STATUS_INVALID_PARAMETER;
1239 memctx = talloc_new(ctx);
1241 DEBUG(0, ("Out of memory!\n"));
1242 return NT_STATUS_NO_MEMORY;
1245 id_str = talloc_asprintf(memctx, "%lu", (unsigned long)map->xid.id);
1246 CHECK_ALLOC_DONE(id_str);
1248 sid = talloc_strdup(memctx, sid_string_static(map->sid));
1249 CHECK_ALLOC_DONE(sid);
1251 dn = talloc_asprintf(memctx, "%s=%s,%s",
1252 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
1255 CHECK_ALLOC_DONE(dn);
1257 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY);
1259 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods, type, id_str);
1261 smbldap_make_mod(ctx->smbldap_state->ldap_struct, entry, &mods,
1262 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), sid);
1265 DEBUG(2, ("ERROR: No mods?\n"));
1266 ret = NT_STATUS_UNSUCCESSFUL;
1270 /* TODO: remove conflicting mappings! */
1272 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY);
1274 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn, sid, id_str));
1276 rc = smbldap_add(ctx->smbldap_state, dn, mods);
1277 ldap_mods_free(mods, True);
1279 if (rc != LDAP_SUCCESS) {
1280 char *ld_error = NULL;
1281 ldap_get_option(ctx->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1282 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu mapping [%s]\n",
1283 sid, (unsigned long)map->xid.id, type));
1284 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1285 ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
1286 ret = NT_STATUS_UNSUCCESSFUL;
1290 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
1291 sid, (unsigned long)map->xid.id, type));
1296 talloc_free(memctx);
1300 /**********************************
1302 **********************************/
1304 static NTSTATUS idmap_ldap_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
1306 return NT_STATUS_UNSUCCESSFUL;
1309 /**********************************
1310 Close the idmap ldap instance
1311 **********************************/
1313 static NTSTATUS idmap_ldap_close(struct idmap_domain *dom)
1315 struct idmap_ldap_context *ctx;
1317 if (dom->private_data) {
1318 ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
1321 dom->private_data = NULL;
1324 return NT_STATUS_OK;
1327 static struct idmap_methods idmap_ldap_methods = {
1329 .init = idmap_ldap_db_init,
1330 .unixids_to_sids = idmap_ldap_unixids_to_sids,
1331 .sids_to_unixids = idmap_ldap_sids_to_unixids,
1332 .set_mapping = idmap_ldap_set_mapping,
1333 .remove_mapping = idmap_ldap_remove_mapping,
1334 /* .dump_data = TODO */
1335 .close_fn = idmap_ldap_close
1338 static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
1340 .init = idmap_ldap_alloc_init,
1341 .allocate_id = idmap_ldap_allocate_id,
1342 .get_id_hwm = idmap_ldap_get_hwm,
1343 .set_id_hwm = idmap_ldap_set_hwm,
1344 .close_fn = idmap_ldap_alloc_close,
1345 /* .dump_data = TODO */
1348 NTSTATUS idmap_alloc_ldap_init(void)
1350 return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "ldap", &idmap_ldap_alloc_methods);
1353 NTSTATUS idmap_ldap_init(void)
1357 /* FIXME: bad hack to actually register also the alloc_ldap module without changining configure.in */
1358 ret = idmap_alloc_ldap_init();
1359 if (! NT_STATUS_IS_OK(ret)) {
1362 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", &idmap_ldap_methods);