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 static char *idmap_fetch_secret(const char *backend
,
43 const char *domain
, const char *identity
)
48 r
= asprintf(&tmp
, "IDMAP_%s_%s", backend
, domain
);
53 /* make sure the key is case insensitive */
54 if (!strupper_m(tmp
)) {
59 ret
= secrets_fetch_generic(tmp
, identity
);
66 struct idmap_ldap_context
{
67 struct smbldap_state
*smbldap_state
;
72 struct idmap_rw_ops
*rw_ops
;
75 #define CHECK_ALLOC_DONE(mem) do { \
77 DEBUG(0, ("Out of memory!\n")); \
78 ret = NT_STATUS_NO_MEMORY; \
82 /**********************************************************************
83 IDMAP ALLOC TDB BACKEND
84 **********************************************************************/
86 /*********************************************************************
87 ********************************************************************/
89 static NTSTATUS
get_credentials( TALLOC_CTX
*mem_ctx
,
90 struct smbldap_state
*ldap_state
,
91 const char *config_option
,
92 struct idmap_domain
*dom
,
95 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
97 const char *tmp
= NULL
;
101 /* assume anonymous if we don't have a specified user */
103 tmp
= lp_parm_const_string(-1, config_option
, "ldap_user_dn", NULL
);
107 DEBUG(0, ("get_credentials: Invalid domain 'NULL' "
108 "encountered for user DN %s\n",
110 ret
= NT_STATUS_UNSUCCESSFUL
;
113 secret
= idmap_fetch_secret("ldap", dom
->name
, tmp
);
117 DEBUG(0, ("get_credentials: Unable to fetch "
118 "auth credentials for %s in %s\n",
119 tmp
, (dom
==NULL
)?"ALLOC":dom
->name
));
120 ret
= NT_STATUS_ACCESS_DENIED
;
123 *dn
= talloc_strdup(mem_ctx
, tmp
);
124 CHECK_ALLOC_DONE(*dn
);
126 if (!fetch_ldap_pw(&user_dn
, &secret
)) {
127 DEBUG(2, ("get_credentials: Failed to lookup ldap "
128 "bind creds. Using anonymous connection.\n"));
132 *dn
= talloc_strdup(mem_ctx
, user_dn
);
133 SAFE_FREE( user_dn
);
134 CHECK_ALLOC_DONE(*dn
);
138 smbldap_set_creds(ldap_state
, anon
, *dn
, secret
);
148 /**********************************************************************
149 Verify the sambaUnixIdPool entry in the directory.
150 **********************************************************************/
152 static NTSTATUS
verify_idpool(struct idmap_domain
*dom
)
156 LDAPMessage
*result
= NULL
;
157 LDAPMod
**mods
= NULL
;
158 const char **attr_list
;
162 struct idmap_ldap_context
*ctx
;
164 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
166 mem_ctx
= talloc_new(ctx
);
167 if (mem_ctx
== NULL
) {
168 DEBUG(0, ("Out of memory!\n"));
169 return NT_STATUS_NO_MEMORY
;
172 filter
= talloc_asprintf(mem_ctx
, "(objectclass=%s)", LDAP_OBJ_IDPOOL
);
173 CHECK_ALLOC_DONE(filter
);
175 attr_list
= get_attr_list(mem_ctx
, idpool_attr_list
);
176 CHECK_ALLOC_DONE(attr_list
);
178 rc
= smbldap_search(ctx
->smbldap_state
,
186 if (rc
!= LDAP_SUCCESS
) {
187 DEBUG(1, ("Unable to verify the idpool, "
188 "cannot continue initialization!\n"));
189 return NT_STATUS_UNSUCCESSFUL
;
192 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
194 ldap_msgfree(result
);
197 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
198 filter
, ctx
->suffix
));
199 ret
= NT_STATUS_UNSUCCESSFUL
;
202 else if (count
== 0) {
203 char *uid_str
, *gid_str
;
205 uid_str
= talloc_asprintf(mem_ctx
, "%lu",
206 (unsigned long)dom
->low_id
);
207 gid_str
= talloc_asprintf(mem_ctx
, "%lu",
208 (unsigned long)dom
->low_id
);
210 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
211 "objectClass", LDAP_OBJ_IDPOOL
);
212 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
213 get_attr_key2string(idpool_attr_list
,
214 LDAP_ATTR_UIDNUMBER
),
216 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
217 get_attr_key2string(idpool_attr_list
,
218 LDAP_ATTR_GIDNUMBER
),
221 rc
= smbldap_modify(ctx
->smbldap_state
,
224 ldap_mods_free(mods
, True
);
226 ret
= NT_STATUS_UNSUCCESSFUL
;
231 ret
= (rc
== LDAP_SUCCESS
)?NT_STATUS_OK
:NT_STATUS_UNSUCCESSFUL
;
233 talloc_free(mem_ctx
);
237 /********************************
238 Allocate a new uid or gid
239 ********************************/
241 static NTSTATUS
idmap_ldap_allocate_id_internal(struct idmap_domain
*dom
,
245 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
246 int rc
= LDAP_SERVER_DOWN
;
248 LDAPMessage
*result
= NULL
;
249 LDAPMessage
*entry
= NULL
;
250 LDAPMod
**mods
= NULL
;
254 const char *dn
= NULL
;
255 const char **attr_list
;
257 struct idmap_ldap_context
*ctx
;
259 /* Only do query if we are online */
260 if (idmap_is_offline()) {
261 return NT_STATUS_FILE_IS_OFFLINE
;
264 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
266 mem_ctx
= talloc_new(ctx
);
268 DEBUG(0, ("Out of memory!\n"));
269 return NT_STATUS_NO_MEMORY
;
276 type
= get_attr_key2string(idpool_attr_list
,
277 LDAP_ATTR_UIDNUMBER
);
281 type
= get_attr_key2string(idpool_attr_list
,
282 LDAP_ATTR_GIDNUMBER
);
286 DEBUG(2, ("Invalid ID type (0x%x)\n", xid
->type
));
287 return NT_STATUS_INVALID_PARAMETER
;
290 filter
= talloc_asprintf(mem_ctx
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
291 CHECK_ALLOC_DONE(filter
);
293 attr_list
= get_attr_list(mem_ctx
, idpool_attr_list
);
294 CHECK_ALLOC_DONE(attr_list
);
296 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter
));
298 rc
= smbldap_search(ctx
->smbldap_state
,
300 LDAP_SCOPE_SUBTREE
, filter
,
301 attr_list
, 0, &result
);
303 if (rc
!= LDAP_SUCCESS
) {
304 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL
));
308 smbldap_talloc_autofree_ldapmsg(mem_ctx
, result
);
310 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
312 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL
));
316 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
, result
);
318 dn
= smbldap_talloc_dn(mem_ctx
,
319 ctx
->smbldap_state
->ldap_struct
,
325 id_str
= smbldap_talloc_single_attribute(
326 ctx
->smbldap_state
->ldap_struct
,
327 entry
, type
, mem_ctx
);
328 if (id_str
== NULL
) {
329 DEBUG(0,("%s attribute not found\n", type
));
330 ret
= NT_STATUS_UNSUCCESSFUL
;
334 xid
->id
= strtoul(id_str
, NULL
, 10);
336 /* make sure we still have room to grow */
340 if (xid
->id
> dom
->high_id
) {
341 DEBUG(0,("Cannot allocate uid above %lu!\n",
342 (unsigned long)dom
->high_id
));
348 if (xid
->id
> dom
->high_id
) {
349 DEBUG(0,("Cannot allocate gid above %lu!\n",
350 (unsigned long)dom
->high_id
));
360 new_id_str
= talloc_asprintf(mem_ctx
, "%lu", (unsigned long)xid
->id
+ 1);
362 DEBUG(0,("Out of memory\n"));
363 ret
= NT_STATUS_NO_MEMORY
;
367 smbldap_set_mod(&mods
, LDAP_MOD_DELETE
, type
, id_str
);
368 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, type
, new_id_str
);
371 DEBUG(0,("smbldap_set_mod() failed.\n"));
375 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n",
376 id_str
, new_id_str
));
378 rc
= smbldap_modify(ctx
->smbldap_state
, dn
, mods
);
380 ldap_mods_free(mods
, True
);
382 if (rc
!= LDAP_SUCCESS
) {
383 DEBUG(1,("Failed to allocate new %s. "
384 "smbldap_modify() failed.\n", type
));
391 talloc_free(mem_ctx
);
396 * Allocate a new unix-ID.
397 * For now this is for the default idmap domain only.
398 * Should be extended later on.
400 static NTSTATUS
idmap_ldap_allocate_id(struct idmap_domain
*dom
,
405 if (!strequal(dom
->name
, "*")) {
406 DEBUG(3, ("idmap_ldap_allocate_id: "
407 "Refusing allocation of a new unixid for domain'%s'. "
408 "This is only supported for the default "
411 return NT_STATUS_NOT_IMPLEMENTED
;
414 ret
= idmap_ldap_allocate_id_internal(dom
, id
);
420 /**********************************************************************
421 IDMAP MAPPING LDAP BACKEND
422 **********************************************************************/
424 static int idmap_ldap_close_destructor(struct idmap_ldap_context
*ctx
)
426 smbldap_free_struct(&ctx
->smbldap_state
);
427 DEBUG(5,("The connection to the LDAP server was closed\n"));
428 /* maybe free the results here --metze */
433 /********************************
434 Initialise idmap database.
435 ********************************/
437 static NTSTATUS
idmap_ldap_set_mapping(struct idmap_domain
*dom
,
438 const struct id_map
*map
);
440 static NTSTATUS
idmap_ldap_db_init(struct idmap_domain
*dom
)
443 struct idmap_ldap_context
*ctx
= NULL
;
444 char *config_option
= NULL
;
445 const char *tmp
= NULL
;
447 /* Only do init if we are online */
448 if (idmap_is_offline()) {
449 return NT_STATUS_FILE_IS_OFFLINE
;
452 ctx
= talloc_zero(dom
, struct idmap_ldap_context
);
454 DEBUG(0, ("Out of memory!\n"));
455 return NT_STATUS_NO_MEMORY
;
458 config_option
= talloc_asprintf(ctx
, "idmap config %s", dom
->name
);
459 if (!config_option
) {
460 DEBUG(0, ("Out of memory!\n"));
461 ret
= NT_STATUS_NO_MEMORY
;
465 tmp
= lp_parm_const_string(-1, config_option
, "ldap_url", NULL
);
468 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
469 ret
= NT_STATUS_UNSUCCESSFUL
;
473 ctx
->url
= talloc_strdup(ctx
, tmp
);
475 trim_char(ctx
->url
, '\"', '\"');
477 tmp
= lp_parm_const_string(-1, config_option
, "ldap_base_dn", NULL
);
478 if ( ! tmp
|| ! *tmp
) {
479 tmp
= lp_ldap_idmap_suffix(talloc_tos());
481 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
482 ret
= NT_STATUS_UNSUCCESSFUL
;
487 ctx
->suffix
= talloc_strdup(ctx
, tmp
);
488 CHECK_ALLOC_DONE(ctx
->suffix
);
490 ctx
->rw_ops
= talloc_zero(ctx
, struct idmap_rw_ops
);
491 CHECK_ALLOC_DONE(ctx
->rw_ops
);
493 ctx
->rw_ops
->get_new_id
= idmap_ldap_allocate_id_internal
;
494 ctx
->rw_ops
->set_mapping
= idmap_ldap_set_mapping
;
496 /* get_credentials deals with setting up creds */
498 ret
= smbldap_init(ctx
, winbind_event_context(), ctx
->url
,
499 false, NULL
, NULL
, &ctx
->smbldap_state
);
500 if (!NT_STATUS_IS_OK(ret
)) {
501 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx
->url
));
505 ret
= get_credentials( ctx
, ctx
->smbldap_state
, config_option
,
506 dom
, &ctx
->user_dn
);
507 if ( !NT_STATUS_IS_OK(ret
) ) {
508 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
509 "credentials (%s)\n", nt_errstr(ret
)));
514 * Set the destructor on the context, so that resources are
515 * properly freed when the context is released.
517 talloc_set_destructor(ctx
, idmap_ldap_close_destructor
);
519 dom
->private_data
= ctx
;
521 ret
= verify_idpool(dom
);
522 if (!NT_STATUS_IS_OK(ret
)) {
523 DEBUG(1, ("idmap_ldap_db_init: failed to verify ID pool (%s)\n",
528 talloc_free(config_option
);
541 /* TODO: change this: This function cannot be called to modify a mapping,
542 * only set a new one */
544 static NTSTATUS
idmap_ldap_set_mapping(struct idmap_domain
*dom
,
545 const struct id_map
*map
)
549 struct idmap_ldap_context
*ctx
;
550 LDAPMessage
*entry
= NULL
;
551 LDAPMod
**mods
= NULL
;
558 /* Only do query if we are online */
559 if (idmap_is_offline()) {
560 return NT_STATUS_FILE_IS_OFFLINE
;
563 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
565 switch(map
->xid
.type
) {
567 type
= get_attr_key2string(sidmap_attr_list
,
568 LDAP_ATTR_UIDNUMBER
);
572 type
= get_attr_key2string(sidmap_attr_list
,
573 LDAP_ATTR_GIDNUMBER
);
577 return NT_STATUS_INVALID_PARAMETER
;
580 memctx
= talloc_new(ctx
);
582 DEBUG(0, ("Out of memory!\n"));
583 return NT_STATUS_NO_MEMORY
;
586 id_str
= talloc_asprintf(memctx
, "%lu", (unsigned long)map
->xid
.id
);
587 CHECK_ALLOC_DONE(id_str
);
589 sid
= talloc_strdup(memctx
, sid_string_talloc(memctx
, map
->sid
));
590 CHECK_ALLOC_DONE(sid
);
592 dn
= talloc_asprintf(memctx
, "%s=%s,%s",
593 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
),
596 CHECK_ALLOC_DONE(dn
);
598 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
599 "objectClass", LDAP_OBJ_IDMAP_ENTRY
);
601 smbldap_make_mod(ctx
->smbldap_state
->ldap_struct
,
602 entry
, &mods
, type
, id_str
);
604 smbldap_make_mod(ctx
->smbldap_state
->ldap_struct
, entry
, &mods
,
605 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
),
609 DEBUG(2, ("ERROR: No mods?\n"));
610 ret
= NT_STATUS_UNSUCCESSFUL
;
614 /* TODO: remove conflicting mappings! */
616 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_SID_ENTRY
);
618 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn
, sid
, id_str
));
620 rc
= smbldap_add(ctx
->smbldap_state
, dn
, mods
);
621 ldap_mods_free(mods
, True
);
623 if (rc
!= LDAP_SUCCESS
) {
624 char *ld_error
= NULL
;
625 ldap_get_option(ctx
->smbldap_state
->ldap_struct
,
626 LDAP_OPT_ERROR_STRING
, &ld_error
);
627 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu "
628 "mapping [%s]\n", sid
,
629 (unsigned long)map
->xid
.id
, type
));
630 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
631 ld_error
? ld_error
: "(NULL)", ldap_err2string (rc
)));
633 ldap_memfree(ld_error
);
635 ret
= NT_STATUS_UNSUCCESSFUL
;
639 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to "
640 "%lu [%s]\n", sid
, (unsigned long)map
->xid
.id
, type
));
650 * Create a new mapping for an unmapped SID, also allocating a new ID.
651 * If possible, this should be run inside a transaction to make the
654 static NTSTATUS
idmap_ldap_new_mapping(struct idmap_domain
*dom
, struct id_map
*map
)
657 struct idmap_ldap_context
*ctx
;
659 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
661 ret
= idmap_rw_new_mapping(dom
, ctx
->rw_ops
, map
);
667 /* max number of ids requested per batch query */
668 #define IDMAP_LDAP_MAX_IDS 30
670 /**********************************
671 lookup a set of unix ids.
672 **********************************/
674 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
675 * in maps for a match */
676 static struct id_map
*find_map_by_id(struct id_map
**maps
,
682 for (i
= 0; i
< IDMAP_LDAP_MAX_IDS
; i
++) {
683 if (maps
[i
] == NULL
) { /* end of the run */
686 if ((maps
[i
]->xid
.type
== type
) && (maps
[i
]->xid
.id
== id
)) {
694 static NTSTATUS
idmap_ldap_unixids_to_sids(struct idmap_domain
*dom
,
699 struct idmap_ldap_context
*ctx
;
700 LDAPMessage
*result
= NULL
;
701 LDAPMessage
*entry
= NULL
;
702 const char *uidNumber
;
703 const char *gidNumber
;
704 const char **attr_list
;
713 /* Only do query if we are online */
714 if (idmap_is_offline()) {
715 return NT_STATUS_FILE_IS_OFFLINE
;
718 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
720 memctx
= talloc_new(ctx
);
722 DEBUG(0, ("Out of memory!\n"));
723 return NT_STATUS_NO_MEMORY
;
726 uidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
727 gidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
729 attr_list
= get_attr_list(memctx
, sidmap_attr_list
);
732 /* if we are requested just one mapping use the simple filter */
734 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(%s=%lu))",
735 LDAP_OBJ_IDMAP_ENTRY
,
736 (ids
[0]->xid
.type
==ID_TYPE_UID
)?uidNumber
:gidNumber
,
737 (unsigned long)ids
[0]->xid
.id
);
738 CHECK_ALLOC_DONE(filter
);
739 DEBUG(10, ("Filter: [%s]\n", filter
));
741 /* multiple mappings */
745 for (i
= 0; ids
[i
]; i
++) {
746 ids
[i
]->status
= ID_UNKNOWN
;
753 filter
= talloc_asprintf(memctx
,
754 "(&(objectClass=%s)(|",
755 LDAP_OBJ_IDMAP_ENTRY
);
756 CHECK_ALLOC_DONE(filter
);
759 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
760 filter
= talloc_asprintf_append_buffer(filter
, "(%s=%lu)",
761 (ids
[idx
]->xid
.type
==ID_TYPE_UID
)?uidNumber
:gidNumber
,
762 (unsigned long)ids
[idx
]->xid
.id
);
763 CHECK_ALLOC_DONE(filter
);
765 filter
= talloc_asprintf_append_buffer(filter
, "))");
766 CHECK_ALLOC_DONE(filter
);
767 DEBUG(10, ("Filter: [%s]\n", filter
));
773 rc
= smbldap_search(ctx
->smbldap_state
, ctx
->suffix
, LDAP_SCOPE_SUBTREE
,
774 filter
, attr_list
, 0, &result
);
776 if (rc
!= LDAP_SUCCESS
) {
777 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc
)));
778 ret
= NT_STATUS_UNSUCCESSFUL
;
782 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
785 DEBUG(10, ("NO SIDs found\n"));
788 for (i
= 0; i
< count
; i
++) {
795 if (i
== 0) { /* first entry */
796 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
,
798 } else { /* following ones */
799 entry
= ldap_next_entry(ctx
->smbldap_state
->ldap_struct
,
803 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
808 /* first check if the SID is present */
809 sidstr
= smbldap_talloc_single_attribute(
810 ctx
->smbldap_state
->ldap_struct
,
811 entry
, LDAP_ATTRIBUTE_SID
, memctx
);
812 if ( ! sidstr
) { /* no sid, skip entry */
813 DEBUG(2, ("WARNING SID not found on entry\n"));
817 /* now try to see if it is a uid, if not try with a gid
818 * (gid is more common, but in case both uidNumber and
819 * gidNumber are returned the SID is mapped to the uid
822 tmp
= smbldap_talloc_single_attribute(
823 ctx
->smbldap_state
->ldap_struct
,
824 entry
, uidNumber
, memctx
);
827 tmp
= smbldap_talloc_single_attribute(
828 ctx
->smbldap_state
->ldap_struct
,
829 entry
, gidNumber
, memctx
);
831 if ( ! tmp
) { /* wow very strange entry, how did it match ? */
832 DEBUG(5, ("Unprobable match on (%s), no uidNumber, "
833 "nor gidNumber returned\n", sidstr
));
838 id
= strtoul(tmp
, NULL
, 10);
839 if (!idmap_unix_id_is_in_range(id
, dom
)) {
840 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
842 dom
->low_id
, dom
->high_id
));
849 map
= find_map_by_id(&ids
[bidx
], type
, id
);
851 DEBUG(2, ("WARNING: couldn't match sid (%s) "
852 "with requested ids\n", sidstr
));
857 if ( ! string_to_sid(map
->sid
, sidstr
)) {
858 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
863 if (map
->status
== ID_MAPPED
) {
864 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
865 "overwriting mapping %u -> %s with %u -> %s\n",
866 (type
== ID_TYPE_UID
) ? "UID" : "GID",
867 id
, sid_string_dbg(map
->sid
), id
, sidstr
));
873 map
->status
= ID_MAPPED
;
875 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map
->sid
),
876 (unsigned long)map
->xid
.id
, map
->xid
.type
));
879 /* free the ldap results */
881 ldap_msgfree(result
);
885 if (multi
&& ids
[idx
]) { /* still some values to map */
891 /* mark all unknwon/expired ones as unmapped */
892 for (i
= 0; ids
[i
]; i
++) {
893 if (ids
[i
]->status
!= ID_MAPPED
)
894 ids
[i
]->status
= ID_UNMAPPED
;
902 /**********************************
903 lookup a set of sids.
904 **********************************/
906 /* this function searches up to IDMAP_LDAP_MAX_IDS entries
907 * in maps for a match */
908 static struct id_map
*find_map_by_sid(struct id_map
**maps
, struct dom_sid
*sid
)
912 for (i
= 0; i
< IDMAP_LDAP_MAX_IDS
; i
++) {
913 if (maps
[i
] == NULL
) { /* end of the run */
916 if (dom_sid_equal(maps
[i
]->sid
, sid
)) {
924 static NTSTATUS
idmap_ldap_sids_to_unixids(struct idmap_domain
*dom
,
927 LDAPMessage
*entry
= NULL
;
930 struct idmap_ldap_context
*ctx
;
931 LDAPMessage
*result
= NULL
;
932 const char *uidNumber
;
933 const char *gidNumber
;
934 const char **attr_list
;
943 /* Only do query if we are online */
944 if (idmap_is_offline()) {
945 return NT_STATUS_FILE_IS_OFFLINE
;
948 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
950 memctx
= talloc_new(ctx
);
952 DEBUG(0, ("Out of memory!\n"));
953 return NT_STATUS_NO_MEMORY
;
956 uidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
957 gidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
959 attr_list
= get_attr_list(memctx
, sidmap_attr_list
);
962 /* if we are requested just one mapping use the simple filter */
964 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(%s=%s))",
965 LDAP_OBJ_IDMAP_ENTRY
,
967 sid_string_talloc(memctx
, ids
[0]->sid
));
968 CHECK_ALLOC_DONE(filter
);
969 DEBUG(10, ("Filter: [%s]\n", filter
));
971 /* multiple mappings */
975 for (i
= 0; ids
[i
]; i
++) {
976 ids
[i
]->status
= ID_UNKNOWN
;
983 filter
= talloc_asprintf(memctx
,
984 "(&(objectClass=%s)(|",
985 LDAP_OBJ_IDMAP_ENTRY
);
986 CHECK_ALLOC_DONE(filter
);
989 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
990 filter
= talloc_asprintf_append_buffer(filter
, "(%s=%s)",
992 sid_string_talloc(memctx
,
994 CHECK_ALLOC_DONE(filter
);
996 filter
= talloc_asprintf_append_buffer(filter
, "))");
997 CHECK_ALLOC_DONE(filter
);
998 DEBUG(10, ("Filter: [%s]", filter
));
1004 rc
= smbldap_search(ctx
->smbldap_state
, ctx
->suffix
, LDAP_SCOPE_SUBTREE
,
1005 filter
, attr_list
, 0, &result
);
1007 if (rc
!= LDAP_SUCCESS
) {
1008 DEBUG(3,("Failure looking up sids (%s)\n",
1009 ldap_err2string(rc
)));
1010 ret
= NT_STATUS_UNSUCCESSFUL
;
1014 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
1017 DEBUG(10, ("NO SIDs found\n"));
1020 for (i
= 0; i
< count
; i
++) {
1021 char *sidstr
= NULL
;
1028 if (i
== 0) { /* first entry */
1029 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
,
1031 } else { /* following ones */
1032 entry
= ldap_next_entry(ctx
->smbldap_state
->ldap_struct
,
1036 DEBUG(2, ("ERROR: Unable to fetch ldap entries "
1041 /* first check if the SID is present */
1042 sidstr
= smbldap_talloc_single_attribute(
1043 ctx
->smbldap_state
->ldap_struct
,
1044 entry
, LDAP_ATTRIBUTE_SID
, memctx
);
1045 if ( ! sidstr
) { /* no sid ??, skip entry */
1046 DEBUG(2, ("WARNING SID not found on entry\n"));
1050 if ( ! string_to_sid(&sid
, sidstr
)) {
1051 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1052 TALLOC_FREE(sidstr
);
1056 map
= find_map_by_sid(&ids
[bidx
], &sid
);
1058 DEBUG(2, ("WARNING: couldn't find entry sid (%s) "
1060 TALLOC_FREE(sidstr
);
1064 /* now try to see if it is a uid, if not try with a gid
1065 * (gid is more common, but in case both uidNumber and
1066 * gidNumber are returned the SID is mapped to the uid
1069 tmp
= smbldap_talloc_single_attribute(
1070 ctx
->smbldap_state
->ldap_struct
,
1071 entry
, uidNumber
, memctx
);
1074 tmp
= smbldap_talloc_single_attribute(
1075 ctx
->smbldap_state
->ldap_struct
,
1076 entry
, gidNumber
, memctx
);
1078 if ( ! tmp
) { /* no ids ?? */
1079 DEBUG(5, ("no uidNumber, "
1080 "nor gidNumber attributes found\n"));
1081 TALLOC_FREE(sidstr
);
1085 id
= strtoul(tmp
, NULL
, 10);
1086 if (!idmap_unix_id_is_in_range(id
, dom
)) {
1087 DEBUG(5, ("Requested id (%u) out of range (%u - %u). "
1089 dom
->low_id
, dom
->high_id
));
1090 TALLOC_FREE(sidstr
);
1096 if (map
->status
== ID_MAPPED
) {
1097 DEBUG(1, ("WARNING: duplicate %s mapping in LDAP. "
1098 "overwriting mapping %s -> %u with %s -> %u\n",
1099 (type
== ID_TYPE_UID
) ? "UID" : "GID",
1100 sidstr
, map
->xid
.id
, sidstr
, id
));
1103 TALLOC_FREE(sidstr
);
1106 map
->xid
.type
= type
;
1108 map
->status
= ID_MAPPED
;
1110 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map
->sid
),
1111 (unsigned long)map
->xid
.id
, map
->xid
.type
));
1114 /* free the ldap results */
1116 ldap_msgfree(result
);
1120 if (multi
&& ids
[idx
]) { /* still some values to map */
1125 * try to create new mappings for unmapped sids
1127 for (i
= 0; ids
[i
]; i
++) {
1128 if (ids
[i
]->status
!= ID_MAPPED
) {
1129 ids
[i
]->status
= ID_UNMAPPED
;
1130 if (ids
[i
]->sid
!= NULL
) {
1131 ret
= idmap_ldap_new_mapping(dom
, ids
[i
]);
1132 if (!NT_STATUS_IS_OK(ret
)) {
1142 talloc_free(memctx
);
1146 /**********************************
1147 Close the idmap ldap instance
1148 **********************************/
1150 static struct idmap_methods idmap_ldap_methods
= {
1152 .init
= idmap_ldap_db_init
,
1153 .unixids_to_sids
= idmap_ldap_unixids_to_sids
,
1154 .sids_to_unixids
= idmap_ldap_sids_to_unixids
,
1155 .allocate_id
= idmap_ldap_allocate_id
,
1158 NTSTATUS
idmap_ldap_init(void);
1159 NTSTATUS
idmap_ldap_init(void)
1161 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
, "ldap",
1162 &idmap_ldap_methods
);