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
40 #include "passdb/pdb_ldap_schema.h"
42 struct idmap_ldap_context
{
43 struct smbldap_state
*smbldap_state
;
48 struct idmap_rw_ops
*rw_ops
;
51 #define CHECK_ALLOC_DONE(mem) do { \
53 DEBUG(0, ("Out of memory!\n")); \
54 ret = NT_STATUS_NO_MEMORY; \
58 /**********************************************************************
59 IDMAP ALLOC TDB BACKEND
60 **********************************************************************/
62 /*********************************************************************
63 ********************************************************************/
65 static NTSTATUS
get_credentials( TALLOC_CTX
*mem_ctx
,
66 struct smbldap_state
*ldap_state
,
67 const char *config_option
,
68 struct idmap_domain
*dom
,
71 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
73 const char *tmp
= NULL
;
77 /* assume anonymous if we don't have a specified user */
79 tmp
= lp_parm_const_string(-1, config_option
, "ldap_user_dn", NULL
);
83 DEBUG(0, ("get_credentials: Invalid domain 'NULL' "
84 "encountered for user DN %s\n",
86 ret
= NT_STATUS_UNSUCCESSFUL
;
89 secret
= idmap_fetch_secret("ldap", dom
->name
, tmp
);
93 DEBUG(0, ("get_credentials: Unable to fetch "
94 "auth credentials for %s in %s\n",
95 tmp
, (dom
==NULL
)?"ALLOC":dom
->name
));
96 ret
= NT_STATUS_ACCESS_DENIED
;
99 *dn
= talloc_strdup(mem_ctx
, tmp
);
100 CHECK_ALLOC_DONE(*dn
);
102 if (!fetch_ldap_pw(&user_dn
, &secret
)) {
103 DEBUG(2, ("get_credentials: Failed to lookup ldap "
104 "bind creds. Using anonymous connection.\n"));
108 *dn
= talloc_strdup(mem_ctx
, user_dn
);
109 SAFE_FREE( user_dn
);
110 CHECK_ALLOC_DONE(*dn
);
114 smbldap_set_creds(ldap_state
, anon
, *dn
, secret
);
124 /**********************************************************************
125 Verify the sambaUnixIdPool entry in the directory.
126 **********************************************************************/
128 static NTSTATUS
verify_idpool(struct idmap_domain
*dom
)
132 LDAPMessage
*result
= NULL
;
133 LDAPMod
**mods
= NULL
;
134 const char **attr_list
;
138 struct idmap_ldap_context
*ctx
;
140 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
142 mem_ctx
= talloc_new(ctx
);
143 if (mem_ctx
== NULL
) {
144 DEBUG(0, ("Out of memory!\n"));
145 return NT_STATUS_NO_MEMORY
;
148 filter
= talloc_asprintf(mem_ctx
, "(objectclass=%s)", LDAP_OBJ_IDPOOL
);
149 CHECK_ALLOC_DONE(filter
);
151 attr_list
= get_attr_list(mem_ctx
, idpool_attr_list
);
152 CHECK_ALLOC_DONE(attr_list
);
154 rc
= smbldap_search(ctx
->smbldap_state
,
162 if (rc
!= LDAP_SUCCESS
) {
163 DEBUG(1, ("Unable to verify the idpool, "
164 "cannot continue initialization!\n"));
165 return NT_STATUS_UNSUCCESSFUL
;
168 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
170 ldap_msgfree(result
);
173 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
174 filter
, ctx
->suffix
));
175 ret
= NT_STATUS_UNSUCCESSFUL
;
178 else if (count
== 0) {
179 char *uid_str
, *gid_str
;
181 uid_str
= talloc_asprintf(mem_ctx
, "%lu",
182 (unsigned long)dom
->low_id
);
183 gid_str
= talloc_asprintf(mem_ctx
, "%lu",
184 (unsigned long)dom
->low_id
);
186 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
187 "objectClass", LDAP_OBJ_IDPOOL
);
188 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
189 get_attr_key2string(idpool_attr_list
,
190 LDAP_ATTR_UIDNUMBER
),
192 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
193 get_attr_key2string(idpool_attr_list
,
194 LDAP_ATTR_GIDNUMBER
),
197 rc
= smbldap_modify(ctx
->smbldap_state
,
200 ldap_mods_free(mods
, True
);
202 ret
= NT_STATUS_UNSUCCESSFUL
;
207 ret
= (rc
== LDAP_SUCCESS
)?NT_STATUS_OK
:NT_STATUS_UNSUCCESSFUL
;
209 talloc_free(mem_ctx
);
213 /********************************
214 Allocate a new uid or gid
215 ********************************/
217 static NTSTATUS
idmap_ldap_allocate_id_internal(struct idmap_domain
*dom
,
221 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
222 int rc
= LDAP_SERVER_DOWN
;
224 LDAPMessage
*result
= NULL
;
225 LDAPMessage
*entry
= NULL
;
226 LDAPMod
**mods
= NULL
;
230 const char *dn
= NULL
;
231 const char **attr_list
;
233 struct idmap_ldap_context
*ctx
;
235 /* Only do query if we are online */
236 if (idmap_is_offline()) {
237 return NT_STATUS_FILE_IS_OFFLINE
;
240 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
242 mem_ctx
= talloc_new(ctx
);
244 DEBUG(0, ("Out of memory!\n"));
245 return NT_STATUS_NO_MEMORY
;
252 type
= get_attr_key2string(idpool_attr_list
,
253 LDAP_ATTR_UIDNUMBER
);
257 type
= get_attr_key2string(idpool_attr_list
,
258 LDAP_ATTR_GIDNUMBER
);
262 DEBUG(2, ("Invalid ID type (0x%x)\n", xid
->type
));
263 return NT_STATUS_INVALID_PARAMETER
;
266 filter
= talloc_asprintf(mem_ctx
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
267 CHECK_ALLOC_DONE(filter
);
269 attr_list
= get_attr_list(mem_ctx
, idpool_attr_list
);
270 CHECK_ALLOC_DONE(attr_list
);
272 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter
));
274 rc
= smbldap_search(ctx
->smbldap_state
,
276 LDAP_SCOPE_SUBTREE
, filter
,
277 attr_list
, 0, &result
);
279 if (rc
!= LDAP_SUCCESS
) {
280 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL
));
284 smbldap_talloc_autofree_ldapmsg(mem_ctx
, result
);
286 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
288 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL
));
292 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
, result
);
294 dn
= smbldap_talloc_dn(mem_ctx
,
295 ctx
->smbldap_state
->ldap_struct
,
301 id_str
= smbldap_talloc_single_attribute(
302 ctx
->smbldap_state
->ldap_struct
,
303 entry
, type
, mem_ctx
);
304 if (id_str
== NULL
) {
305 DEBUG(0,("%s attribute not found\n", type
));
306 ret
= NT_STATUS_UNSUCCESSFUL
;
310 xid
->id
= strtoul(id_str
, NULL
, 10);
312 /* make sure we still have room to grow */
316 if (xid
->id
> dom
->high_id
) {
317 DEBUG(0,("Cannot allocate uid above %lu!\n",
318 (unsigned long)dom
->high_id
));
324 if (xid
->id
> dom
->high_id
) {
325 DEBUG(0,("Cannot allocate gid above %lu!\n",
326 (unsigned long)dom
->high_id
));
336 new_id_str
= talloc_asprintf(mem_ctx
, "%lu", (unsigned long)xid
->id
+ 1);
338 DEBUG(0,("Out of memory\n"));
339 ret
= NT_STATUS_NO_MEMORY
;
343 smbldap_set_mod(&mods
, LDAP_MOD_DELETE
, type
, id_str
);
344 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, type
, new_id_str
);
347 DEBUG(0,("smbldap_set_mod() failed.\n"));
351 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
352 id_str
, new_id_str
));
354 rc
= smbldap_modify(ctx
->smbldap_state
, dn
, mods
);
356 ldap_mods_free(mods
, True
);
358 if (rc
!= LDAP_SUCCESS
) {
359 DEBUG(1,("Failed to allocate new %s. "
360 "smbldap_modify() failed.\n", type
));
367 talloc_free(mem_ctx
);
372 * Allocate a new unix-ID.
373 * For now this is for the default idmap domain only.
374 * Should be extended later on.
376 static NTSTATUS
idmap_ldap_allocate_id(struct idmap_domain
*dom
,
381 if (!strequal(dom
->name
, "*")) {
382 DEBUG(3, ("idmap_ldap_allocate_id: "
383 "Refusing allocation of a new unixid for domain'%s'. "
384 "This is only supported for the default "
387 return NT_STATUS_NOT_IMPLEMENTED
;
390 ret
= idmap_ldap_allocate_id_internal(dom
, id
);
396 /**********************************************************************
397 IDMAP MAPPING LDAP BACKEND
398 **********************************************************************/
400 static int idmap_ldap_close_destructor(struct idmap_ldap_context
*ctx
)
402 smbldap_free_struct(&ctx
->smbldap_state
);
403 DEBUG(5,("The connection to the LDAP server was closed\n"));
404 /* maybe free the results here --metze */
409 /********************************
410 Initialise idmap database.
411 ********************************/
413 static NTSTATUS
idmap_ldap_set_mapping(struct idmap_domain
*dom
,
414 const struct id_map
*map
);
416 static NTSTATUS
idmap_ldap_db_init(struct idmap_domain
*dom
)
419 struct idmap_ldap_context
*ctx
= NULL
;
420 char *config_option
= NULL
;
421 const char *tmp
= NULL
;
423 /* Only do init if we are online */
424 if (idmap_is_offline()) {
425 return NT_STATUS_FILE_IS_OFFLINE
;
428 ctx
= talloc_zero(dom
, struct idmap_ldap_context
);
430 DEBUG(0, ("Out of memory!\n"));
431 return NT_STATUS_NO_MEMORY
;
434 config_option
= talloc_asprintf(ctx
, "idmap config %s", dom
->name
);
435 if (!config_option
) {
436 DEBUG(0, ("Out of memory!\n"));
437 ret
= NT_STATUS_NO_MEMORY
;
441 tmp
= lp_parm_const_string(-1, config_option
, "ldap_url", NULL
);
444 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
445 ret
= NT_STATUS_UNSUCCESSFUL
;
449 ctx
->url
= talloc_strdup(ctx
, tmp
);
451 trim_char(ctx
->url
, '\"', '\"');
453 tmp
= lp_parm_const_string(-1, config_option
, "ldap_base_dn", NULL
);
454 if ( ! tmp
|| ! *tmp
) {
455 tmp
= lp_ldap_idmap_suffix(talloc_tos());
457 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
458 ret
= NT_STATUS_UNSUCCESSFUL
;
463 ctx
->suffix
= talloc_strdup(ctx
, tmp
);
464 CHECK_ALLOC_DONE(ctx
->suffix
);
466 ctx
->rw_ops
= talloc_zero(ctx
, struct idmap_rw_ops
);
467 CHECK_ALLOC_DONE(ctx
->rw_ops
);
469 ctx
->rw_ops
->get_new_id
= idmap_ldap_allocate_id_internal
;
470 ctx
->rw_ops
->set_mapping
= idmap_ldap_set_mapping
;
472 /* get_credentials deals with setting up creds */
474 ret
= smbldap_init(ctx
, winbind_event_context(), ctx
->url
,
475 false, NULL
, NULL
, &ctx
->smbldap_state
);
476 if (!NT_STATUS_IS_OK(ret
)) {
477 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx
->url
));
481 ret
= get_credentials( ctx
, ctx
->smbldap_state
, config_option
,
482 dom
, &ctx
->user_dn
);
483 if ( !NT_STATUS_IS_OK(ret
) ) {
484 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
485 "credentials (%s)\n", nt_errstr(ret
)));
490 * Set the destructor on the context, so that resources are
491 * properly freed when the context is released.
493 talloc_set_destructor(ctx
, idmap_ldap_close_destructor
);
495 dom
->private_data
= ctx
;
497 ret
= verify_idpool(dom
);
498 if (!NT_STATUS_IS_OK(ret
)) {
499 DEBUG(1, ("idmap_ldap_db_init: failed to verify ID pool (%s)\n",
504 talloc_free(config_option
);
517 /* TODO: change this: This function cannot be called to modify a mapping,
518 * only set a new one */
520 static NTSTATUS
idmap_ldap_set_mapping(struct idmap_domain
*dom
,
521 const struct id_map
*map
)
525 struct idmap_ldap_context
*ctx
;
526 LDAPMessage
*entry
= NULL
;
527 LDAPMod
**mods
= NULL
;
534 /* Only do query if we are online */
535 if (idmap_is_offline()) {
536 return NT_STATUS_FILE_IS_OFFLINE
;
539 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
541 switch(map
->xid
.type
) {
543 type
= get_attr_key2string(sidmap_attr_list
,
544 LDAP_ATTR_UIDNUMBER
);
548 type
= get_attr_key2string(sidmap_attr_list
,
549 LDAP_ATTR_GIDNUMBER
);
553 return NT_STATUS_INVALID_PARAMETER
;
556 memctx
= talloc_new(ctx
);
558 DEBUG(0, ("Out of memory!\n"));
559 return NT_STATUS_NO_MEMORY
;
562 id_str
= talloc_asprintf(memctx
, "%lu", (unsigned long)map
->xid
.id
);
563 CHECK_ALLOC_DONE(id_str
);
565 sid
= talloc_strdup(memctx
, sid_string_talloc(memctx
, map
->sid
));
566 CHECK_ALLOC_DONE(sid
);
568 dn
= talloc_asprintf(memctx
, "%s=%s,%s",
569 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
),
572 CHECK_ALLOC_DONE(dn
);
574 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
575 "objectClass", LDAP_OBJ_IDMAP_ENTRY
);
577 smbldap_make_mod(ctx
->smbldap_state
->ldap_struct
,
578 entry
, &mods
, type
, id_str
);
580 smbldap_make_mod(ctx
->smbldap_state
->ldap_struct
, entry
, &mods
,
581 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
),
585 DEBUG(2, ("ERROR: No mods?\n"));
586 ret
= NT_STATUS_UNSUCCESSFUL
;
590 /* TODO: remove conflicting mappings! */
592 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_SID_ENTRY
);
594 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn
, sid
, id_str
));
596 rc
= smbldap_add(ctx
->smbldap_state
, dn
, mods
);
597 ldap_mods_free(mods
, True
);
599 if (rc
!= LDAP_SUCCESS
) {
600 char *ld_error
= NULL
;
601 ldap_get_option(ctx
->smbldap_state
->ldap_struct
,
602 LDAP_OPT_ERROR_STRING
, &ld_error
);
603 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
604 "mapping [%s]\n", sid
,
605 (unsigned long)map
->xid
.id
, type
));
606 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
607 ld_error
? ld_error
: "(NULL)", ldap_err2string (rc
)));
609 ldap_memfree(ld_error
);
611 ret
= NT_STATUS_UNSUCCESSFUL
;
615 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
616 "%lu [%s]\n", sid
, (unsigned long)map
->xid
.id
, type
));
626 * Create a new mapping for an unmapped SID, also allocating a new ID.
627 * If possible, this should be run inside a transaction to make the
630 static NTSTATUS
idmap_ldap_new_mapping(struct idmap_domain
*dom
, struct id_map
*map
)
633 struct idmap_ldap_context
*ctx
;
635 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
637 ret
= idmap_rw_new_mapping(dom
, ctx
->rw_ops
, map
);
642 /**********************************
643 lookup a set of unix ids.
644 **********************************/
646 static NTSTATUS
idmap_ldap_unixids_to_sids(struct idmap_domain
*dom
,
651 struct idmap_ldap_context
*ctx
;
652 LDAPMessage
*result
= NULL
;
653 LDAPMessage
*entry
= NULL
;
654 const char *uidNumber
;
655 const char *gidNumber
;
656 const char **attr_list
;
665 /* Only do query if we are online */
666 if (idmap_is_offline()) {
667 return NT_STATUS_FILE_IS_OFFLINE
;
670 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
672 memctx
= talloc_new(ctx
);
674 DEBUG(0, ("Out of memory!\n"));
675 return NT_STATUS_NO_MEMORY
;
678 uidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
679 gidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
681 attr_list
= get_attr_list(memctx
, sidmap_attr_list
);
684 /* if we are requested just one mapping use the simple filter */
686 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(%s=%lu))",
687 LDAP_OBJ_IDMAP_ENTRY
,
688 (ids
[0]->xid
.type
==ID_TYPE_UID
)?uidNumber
:gidNumber
,
689 (unsigned long)ids
[0]->xid
.id
);
690 CHECK_ALLOC_DONE(filter
);
691 DEBUG(10, ("Filter: [%s]\n", filter
));
693 /* multiple mappings */
697 for (i
= 0; ids
[i
]; i
++) {
698 ids
[i
]->status
= ID_UNKNOWN
;
705 filter
= talloc_asprintf(memctx
,
706 "(&(objectClass=%s)(|",
707 LDAP_OBJ_IDMAP_ENTRY
);
708 CHECK_ALLOC_DONE(filter
);
711 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
712 filter
= talloc_asprintf_append_buffer(filter
, "(%s=%lu)",
713 (ids
[idx
]->xid
.type
==ID_TYPE_UID
)?uidNumber
:gidNumber
,
714 (unsigned long)ids
[idx
]->xid
.id
);
715 CHECK_ALLOC_DONE(filter
);
717 filter
= talloc_asprintf_append_buffer(filter
, "))");
718 CHECK_ALLOC_DONE(filter
);
719 DEBUG(10, ("Filter: [%s]\n", filter
));
725 rc
= smbldap_search(ctx
->smbldap_state
, ctx
->suffix
, LDAP_SCOPE_SUBTREE
,
726 filter
, attr_list
, 0, &result
);
728 if (rc
!= LDAP_SUCCESS
) {
729 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc
)));
730 ret
= NT_STATUS_UNSUCCESSFUL
;
734 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
737 DEBUG(10, ("NO SIDs found\n"));
740 for (i
= 0; i
< count
; i
++) {
747 if (i
== 0) { /* first entry */
748 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
,
750 } else { /* following ones */
751 entry
= ldap_next_entry(ctx
->smbldap_state
->ldap_struct
,
755 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
760 /* first check if the SID is present */
761 sidstr
= smbldap_talloc_single_attribute(
762 ctx
->smbldap_state
->ldap_struct
,
763 entry
, LDAP_ATTRIBUTE_SID
, memctx
);
764 if ( ! sidstr
) { /* no sid, skip entry */
765 DEBUG(2, ("WARNING SID not found on entry\n"));
769 /* now try to see if it is a uid, if not try with a gid
770 * (gid is more common, but in case both uidNumber and
771 * gidNumber are returned the SID is mapped to the uid
774 tmp
= smbldap_talloc_single_attribute(
775 ctx
->smbldap_state
->ldap_struct
,
776 entry
, uidNumber
, memctx
);
779 tmp
= smbldap_talloc_single_attribute(
780 ctx
->smbldap_state
->ldap_struct
,
781 entry
, gidNumber
, memctx
);
783 if ( ! tmp
) { /* wow very strange entry, how did it match ? */
784 DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
785 "nor gidNumber returned\n", sidstr
));
790 id
= strtoul(tmp
, NULL
, 10);
791 if (!idmap_unix_id_is_in_range(id
, dom
)) {
792 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
794 dom
->low_id
, dom
->high_id
));
801 map
= idmap_find_map_by_id(&ids
[bidx
], type
, id
);
803 DEBUG(2, ("WARNING: couldn't match sid (%s) "
804 "with requested ids\n", sidstr
));
809 if ( ! string_to_sid(map
->sid
, sidstr
)) {
810 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
815 if (map
->status
== ID_MAPPED
) {
816 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
817 "overwriting mapping %u -> %s with %u -> %s\n",
818 (type
== ID_TYPE_UID
) ? "UID" : "GID",
819 id
, sid_string_dbg(map
->sid
), id
, sidstr
));
825 map
->status
= ID_MAPPED
;
827 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map
->sid
),
828 (unsigned long)map
->xid
.id
, map
->xid
.type
));
831 /* free the ldap results */
833 ldap_msgfree(result
);
837 if (multi
&& ids
[idx
]) { /* still some values to map */
843 /* mark all unknwon/expired ones as unmapped */
844 for (i
= 0; ids
[i
]; i
++) {
845 if (ids
[i
]->status
!= ID_MAPPED
)
846 ids
[i
]->status
= ID_UNMAPPED
;
854 /**********************************
855 lookup a set of sids.
856 **********************************/
858 static NTSTATUS
idmap_ldap_sids_to_unixids(struct idmap_domain
*dom
,
861 LDAPMessage
*entry
= NULL
;
864 struct idmap_ldap_context
*ctx
;
865 LDAPMessage
*result
= NULL
;
866 const char *uidNumber
;
867 const char *gidNumber
;
868 const char **attr_list
;
877 /* Only do query if we are online */
878 if (idmap_is_offline()) {
879 return NT_STATUS_FILE_IS_OFFLINE
;
882 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
884 memctx
= talloc_new(ctx
);
886 DEBUG(0, ("Out of memory!\n"));
887 return NT_STATUS_NO_MEMORY
;
890 uidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
891 gidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
893 attr_list
= get_attr_list(memctx
, sidmap_attr_list
);
896 /* if we are requested just one mapping use the simple filter */
898 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(%s=%s))",
899 LDAP_OBJ_IDMAP_ENTRY
,
901 sid_string_talloc(memctx
, ids
[0]->sid
));
902 CHECK_ALLOC_DONE(filter
);
903 DEBUG(10, ("Filter: [%s]\n", filter
));
905 /* multiple mappings */
909 for (i
= 0; ids
[i
]; i
++) {
910 ids
[i
]->status
= ID_UNKNOWN
;
917 filter
= talloc_asprintf(memctx
,
918 "(&(objectClass=%s)(|",
919 LDAP_OBJ_IDMAP_ENTRY
);
920 CHECK_ALLOC_DONE(filter
);
923 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
924 filter
= talloc_asprintf_append_buffer(filter
, "(%s=%s)",
926 sid_string_talloc(memctx
,
928 CHECK_ALLOC_DONE(filter
);
930 filter
= talloc_asprintf_append_buffer(filter
, "))");
931 CHECK_ALLOC_DONE(filter
);
932 DEBUG(10, ("Filter: [%s]", filter
));
938 rc
= smbldap_search(ctx
->smbldap_state
, ctx
->suffix
, LDAP_SCOPE_SUBTREE
,
939 filter
, attr_list
, 0, &result
);
941 if (rc
!= LDAP_SUCCESS
) {
942 DEBUG(3,("Failure looking up sids (%s)\n",
943 ldap_err2string(rc
)));
944 ret
= NT_STATUS_UNSUCCESSFUL
;
948 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
951 DEBUG(10, ("NO SIDs found\n"));
954 for (i
= 0; i
< count
; i
++) {
962 if (i
== 0) { /* first entry */
963 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
,
965 } else { /* following ones */
966 entry
= ldap_next_entry(ctx
->smbldap_state
->ldap_struct
,
970 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
975 /* first check if the SID is present */
976 sidstr
= smbldap_talloc_single_attribute(
977 ctx
->smbldap_state
->ldap_struct
,
978 entry
, LDAP_ATTRIBUTE_SID
, memctx
);
979 if ( ! sidstr
) { /* no sid ??, skip entry */
980 DEBUG(2, ("WARNING SID not found on entry\n"));
984 if ( ! string_to_sid(&sid
, sidstr
)) {
985 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
990 map
= idmap_find_map_by_sid(&ids
[bidx
], &sid
);
992 DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
998 /* now try to see if it is a uid, if not try with a gid
999 * (gid is more common, but in case both uidNumber and
1000 * gidNumber are returned the SID is mapped to the uid
1003 tmp
= smbldap_talloc_single_attribute(
1004 ctx
->smbldap_state
->ldap_struct
,
1005 entry
, uidNumber
, memctx
);
1008 tmp
= smbldap_talloc_single_attribute(
1009 ctx
->smbldap_state
->ldap_struct
,
1010 entry
, gidNumber
, memctx
);
1012 if ( ! tmp
) { /* no ids ?? */
1013 DEBUG(5, ("no uidNumber, "
1014 "nor gidNumber attributes found\n"));
1015 TALLOC_FREE(sidstr
);
1019 id
= strtoul(tmp
, NULL
, 10);
1020 if (!idmap_unix_id_is_in_range(id
, dom
)) {
1021 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1023 dom
->low_id
, dom
->high_id
));
1024 TALLOC_FREE(sidstr
);
1030 if (map
->status
== ID_MAPPED
) {
1031 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1032 "overwriting mapping %s -> %u with %s -> %u\n",
1033 (type
== ID_TYPE_UID
) ? "UID" : "GID",
1034 sidstr
, map
->xid
.id
, sidstr
, id
));
1037 TALLOC_FREE(sidstr
);
1040 map
->xid
.type
= type
;
1042 map
->status
= ID_MAPPED
;
1044 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map
->sid
),
1045 (unsigned long)map
->xid
.id
, map
->xid
.type
));
1048 /* free the ldap results */
1050 ldap_msgfree(result
);
1054 if (multi
&& ids
[idx
]) { /* still some values to map */
1059 * try to create new mappings for unmapped sids
1061 for (i
= 0; ids
[i
]; i
++) {
1062 if (ids
[i
]->status
!= ID_MAPPED
) {
1063 ids
[i
]->status
= ID_UNMAPPED
;
1064 if (ids
[i
]->sid
!= NULL
) {
1065 ret
= idmap_ldap_new_mapping(dom
, ids
[i
]);
1066 if (!NT_STATUS_IS_OK(ret
)) {
1076 talloc_free(memctx
);
1080 /**********************************
1081 Close the idmap ldap instance
1082 **********************************/
1084 static struct idmap_methods idmap_ldap_methods
= {
1086 .init
= idmap_ldap_db_init
,
1087 .unixids_to_sids
= idmap_ldap_unixids_to_sids
,
1088 .sids_to_unixids
= idmap_ldap_sids_to_unixids
,
1089 .allocate_id
= idmap_ldap_allocate_id
,
1092 NTSTATUS
idmap_ldap_init(void);
1093 NTSTATUS
idmap_ldap_init(void)
1095 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
, "ldap",
1096 &idmap_ldap_methods
);