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.
30 #define DBGC_CLASS DBGC_IDMAP
37 struct idmap_ldap_context
{
38 struct smbldap_state
*smbldap_state
;
42 uint32_t filter_low_id
, filter_high_id
; /* Filter range */
46 struct idmap_ldap_alloc_context
{
47 struct smbldap_state
*smbldap_state
;
51 uid_t low_uid
, high_uid
; /* Range of uids */
52 gid_t low_gid
, high_gid
; /* Range of gids */
56 #define CHECK_ALLOC_DONE(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while (0)
58 /**********************************************************************
59 IDMAP ALLOC TDB BACKEND
60 **********************************************************************/
62 static struct idmap_ldap_alloc_context
*idmap_alloc_ldap
;
64 /*********************************************************************
65 ********************************************************************/
67 static NTSTATUS
get_credentials( TALLOC_CTX
*mem_ctx
,
68 struct smbldap_state
*ldap_state
,
69 const char *config_option
,
70 struct idmap_domain
*dom
,
73 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
76 const char *tmp
= NULL
;
78 /* assume anonymous if we don't have a specified user */
80 tmp
= lp_parm_const_string(-1, config_option
, "ldap_user_dn", NULL
);
84 /* only the alloc backend is allowed to pass in a NULL dom */
85 secret
= idmap_fetch_secret("ldap", true, NULL
, tmp
);
87 secret
= idmap_fetch_secret("ldap", false, dom
->name
, tmp
);
91 DEBUG(0, ("get_credentials: Unable to fetch "
92 "auth credentials for %s in %s\n",
93 tmp
, (dom
==NULL
)?"ALLOC":dom
->name
));
94 ret
= NT_STATUS_ACCESS_DENIED
;
97 *dn
= talloc_strdup(mem_ctx
, tmp
);
98 CHECK_ALLOC_DONE(*dn
);
100 if ( !fetch_ldap_pw( &user_dn
, &secret
) ) {
101 DEBUG(2, ("get_credentials: Failed to lookup ldap "
102 "bind creds. Using anonymous connection.\n"));
103 *dn
= talloc_strdup( mem_ctx
, "" );
105 *dn
= talloc_strdup(mem_ctx
, user_dn
);
106 SAFE_FREE( user_dn
);
107 CHECK_ALLOC_DONE(*dn
);
111 smbldap_set_creds(ldap_state
, false, *dn
, secret
);
121 /**********************************************************************
122 Verify the sambaUnixIdPool entry in the directory.
123 **********************************************************************/
125 static NTSTATUS
verify_idpool(void)
129 LDAPMessage
*result
= NULL
;
130 LDAPMod
**mods
= NULL
;
131 const char **attr_list
;
136 if ( ! idmap_alloc_ldap
) {
137 return NT_STATUS_UNSUCCESSFUL
;
140 ctx
= talloc_new(idmap_alloc_ldap
);
142 DEBUG(0, ("Out of memory!\n"));
143 return NT_STATUS_NO_MEMORY
;
146 filter
= talloc_asprintf(ctx
, "(objectclass=%s)", LDAP_OBJ_IDPOOL
);
147 CHECK_ALLOC_DONE(filter
);
149 attr_list
= get_attr_list(ctx
, idpool_attr_list
);
150 CHECK_ALLOC_DONE(attr_list
);
152 rc
= smbldap_search(idmap_alloc_ldap
->smbldap_state
,
153 idmap_alloc_ldap
->suffix
,
160 if (rc
!= LDAP_SUCCESS
) {
161 DEBUG(1, ("Unable to verify the idpool, cannot continue initialization!\n"));
162 return NT_STATUS_UNSUCCESSFUL
;
165 count
= ldap_count_entries(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
167 ldap_msgfree(result
);
170 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
171 filter
, idmap_alloc_ldap
->suffix
));
172 ret
= NT_STATUS_UNSUCCESSFUL
;
175 else if (count
== 0) {
176 char *uid_str
, *gid_str
;
178 uid_str
= talloc_asprintf(ctx
, "%lu", (unsigned long)idmap_alloc_ldap
->low_uid
);
179 gid_str
= talloc_asprintf(ctx
, "%lu", (unsigned long)idmap_alloc_ldap
->low_gid
);
181 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
182 "objectClass", LDAP_OBJ_IDPOOL
);
183 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
184 get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
),
186 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
187 get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
),
190 rc
= smbldap_modify(idmap_alloc_ldap
->smbldap_state
,
191 idmap_alloc_ldap
->suffix
,
193 ldap_mods_free(mods
, True
);
195 ret
= NT_STATUS_UNSUCCESSFUL
;
200 ret
= (rc
== LDAP_SUCCESS
)?NT_STATUS_OK
:NT_STATUS_UNSUCCESSFUL
;
206 /*****************************************************************************
207 Initialise idmap database.
208 *****************************************************************************/
210 static NTSTATUS
idmap_ldap_alloc_init(const char *params
)
212 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
220 /* Only do init if we are online */
221 if (idmap_is_offline()) {
222 return NT_STATUS_FILE_IS_OFFLINE
;
225 idmap_alloc_ldap
= TALLOC_ZERO_P(NULL
, struct idmap_ldap_alloc_context
);
226 CHECK_ALLOC_DONE( idmap_alloc_ldap
);
230 idmap_alloc_ldap
->low_uid
= 0;
231 idmap_alloc_ldap
->high_uid
= 0;
232 idmap_alloc_ldap
->low_gid
= 0;
233 idmap_alloc_ldap
->high_gid
= 0;
235 range
= lp_parm_const_string(-1, "idmap alloc config", "range", NULL
);
236 if (range
&& range
[0]) {
237 unsigned low_id
, high_id
;
239 if (sscanf(range
, "%u - %u", &low_id
, &high_id
) == 2) {
240 if (low_id
< high_id
) {
241 idmap_alloc_ldap
->low_gid
= idmap_alloc_ldap
->low_uid
= low_id
;
242 idmap_alloc_ldap
->high_gid
= idmap_alloc_ldap
->high_uid
= high_id
;
244 DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range
));
247 DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range
));
251 if (lp_idmap_uid(&low_uid
, &high_uid
)) {
252 idmap_alloc_ldap
->low_uid
= low_uid
;
253 idmap_alloc_ldap
->high_uid
= high_uid
;
256 if (lp_idmap_gid(&low_gid
, &high_gid
)) {
257 idmap_alloc_ldap
->low_gid
= low_gid
;
258 idmap_alloc_ldap
->high_gid
= high_gid
;
261 if (idmap_alloc_ldap
->high_uid
<= idmap_alloc_ldap
->low_uid
) {
262 DEBUG(1, ("idmap uid range missing or invalid\n"));
263 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
264 ret
= NT_STATUS_UNSUCCESSFUL
;
268 if (idmap_alloc_ldap
->high_gid
<= idmap_alloc_ldap
->low_gid
) {
269 DEBUG(1, ("idmap gid range missing or invalid\n"));
270 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
271 ret
= NT_STATUS_UNSUCCESSFUL
;
275 if (params
&& *params
) {
276 /* assume location is the only parameter */
277 idmap_alloc_ldap
->url
= talloc_strdup(idmap_alloc_ldap
, params
);
279 tmp
= lp_parm_const_string(-1, "idmap alloc config", "ldap_url", NULL
);
282 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
283 ret
= NT_STATUS_UNSUCCESSFUL
;
287 idmap_alloc_ldap
->url
= talloc_strdup(idmap_alloc_ldap
, tmp
);
289 CHECK_ALLOC_DONE( idmap_alloc_ldap
->url
);
291 tmp
= lp_ldap_idmap_suffix();
292 if ( ! tmp
|| ! *tmp
) {
293 tmp
= lp_parm_const_string(-1, "idmap alloc config", "ldap_base_dn", NULL
);
296 tmp
= lp_ldap_suffix();
298 DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp
));
299 DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
302 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
303 ret
= NT_STATUS_UNSUCCESSFUL
;
308 idmap_alloc_ldap
->suffix
= talloc_strdup(idmap_alloc_ldap
, tmp
);
309 CHECK_ALLOC_DONE( idmap_alloc_ldap
->suffix
);
311 ret
= smbldap_init(idmap_alloc_ldap
, winbind_event_context(),
312 idmap_alloc_ldap
->url
,
313 &idmap_alloc_ldap
->smbldap_state
);
314 if (!NT_STATUS_IS_OK(ret
)) {
315 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
316 idmap_alloc_ldap
->url
));
320 ret
= get_credentials( idmap_alloc_ldap
,
321 idmap_alloc_ldap
->smbldap_state
,
322 "idmap alloc config", NULL
,
323 &idmap_alloc_ldap
->user_dn
);
324 if ( !NT_STATUS_IS_OK(ret
) ) {
325 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
326 "credentials (%s)\n", nt_errstr(ret
)));
330 /* see if the idmap suffix and sub entries exists */
332 ret
= verify_idpool();
335 if ( !NT_STATUS_IS_OK( ret
) )
336 TALLOC_FREE( idmap_alloc_ldap
);
341 /********************************
342 Allocate a new uid or gid
343 ********************************/
345 static NTSTATUS
idmap_ldap_allocate_id(struct unixid
*xid
)
348 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
349 int rc
= LDAP_SERVER_DOWN
;
351 LDAPMessage
*result
= NULL
;
352 LDAPMessage
*entry
= NULL
;
353 LDAPMod
**mods
= NULL
;
357 const char *dn
= NULL
;
358 const char **attr_list
;
361 /* Only do query if we are online */
362 if (idmap_is_offline()) {
363 return NT_STATUS_FILE_IS_OFFLINE
;
366 if ( ! idmap_alloc_ldap
) {
367 return NT_STATUS_UNSUCCESSFUL
;
370 ctx
= talloc_new(idmap_alloc_ldap
);
372 DEBUG(0, ("Out of memory!\n"));
373 return NT_STATUS_NO_MEMORY
;
380 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
384 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
388 DEBUG(2, ("Invalid ID type (0x%x)\n", xid
->type
));
389 return NT_STATUS_INVALID_PARAMETER
;
392 filter
= talloc_asprintf(ctx
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
393 CHECK_ALLOC_DONE(filter
);
395 attr_list
= get_attr_list(ctx
, idpool_attr_list
);
396 CHECK_ALLOC_DONE(attr_list
);
398 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter
));
400 rc
= smbldap_search(idmap_alloc_ldap
->smbldap_state
,
401 idmap_alloc_ldap
->suffix
,
402 LDAP_SCOPE_SUBTREE
, filter
,
403 attr_list
, 0, &result
);
405 if (rc
!= LDAP_SUCCESS
) {
406 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL
));
410 talloc_autofree_ldapmsg(ctx
, result
);
412 count
= ldap_count_entries(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
414 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL
));
418 entry
= ldap_first_entry(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
420 dn
= smbldap_talloc_dn(ctx
, idmap_alloc_ldap
->smbldap_state
->ldap_struct
, entry
);
425 if ( ! (id_str
= smbldap_talloc_single_attribute(idmap_alloc_ldap
->smbldap_state
->ldap_struct
,
426 entry
, type
, ctx
))) {
427 DEBUG(0,("%s attribute not found\n", type
));
431 DEBUG(0,("Out of memory\n"));
432 ret
= NT_STATUS_NO_MEMORY
;
436 xid
->id
= strtoul(id_str
, NULL
, 10);
438 /* make sure we still have room to grow */
442 if (xid
->id
> idmap_alloc_ldap
->high_uid
) {
443 DEBUG(0,("Cannot allocate uid above %lu!\n",
444 (unsigned long)idmap_alloc_ldap
->high_uid
));
450 if (xid
->id
> idmap_alloc_ldap
->high_gid
) {
451 DEBUG(0,("Cannot allocate gid above %lu!\n",
452 (unsigned long)idmap_alloc_ldap
->high_uid
));
462 new_id_str
= talloc_asprintf(ctx
, "%lu", (unsigned long)xid
->id
+ 1);
464 DEBUG(0,("Out of memory\n"));
465 ret
= NT_STATUS_NO_MEMORY
;
469 smbldap_set_mod(&mods
, LDAP_MOD_DELETE
, type
, id_str
);
470 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, type
, new_id_str
);
473 DEBUG(0,("smbldap_set_mod() failed.\n"));
477 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n", id_str
, new_id_str
));
479 rc
= smbldap_modify(idmap_alloc_ldap
->smbldap_state
, dn
, mods
);
481 ldap_mods_free(mods
, True
);
483 if (rc
!= LDAP_SUCCESS
) {
484 DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type
));
495 /**********************************
496 Get current highest id.
497 **********************************/
499 static NTSTATUS
idmap_ldap_get_hwm(struct unixid
*xid
)
502 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
503 int rc
= LDAP_SERVER_DOWN
;
505 LDAPMessage
*result
= NULL
;
506 LDAPMessage
*entry
= NULL
;
509 const char **attr_list
;
512 /* Only do query if we are online */
513 if (idmap_is_offline()) {
514 return NT_STATUS_FILE_IS_OFFLINE
;
517 if ( ! idmap_alloc_ldap
) {
518 return NT_STATUS_UNSUCCESSFUL
;
521 memctx
= talloc_new(idmap_alloc_ldap
);
523 DEBUG(0, ("Out of memory!\n"));
524 return NT_STATUS_NO_MEMORY
;
531 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
535 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
539 DEBUG(2, ("Invalid ID type (0x%x)\n", xid
->type
));
540 return NT_STATUS_INVALID_PARAMETER
;
543 filter
= talloc_asprintf(memctx
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
544 CHECK_ALLOC_DONE(filter
);
546 attr_list
= get_attr_list(memctx
, idpool_attr_list
);
547 CHECK_ALLOC_DONE(attr_list
);
549 rc
= smbldap_search(idmap_alloc_ldap
->smbldap_state
,
550 idmap_alloc_ldap
->suffix
,
551 LDAP_SCOPE_SUBTREE
, filter
,
552 attr_list
, 0, &result
);
554 if (rc
!= LDAP_SUCCESS
) {
555 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL
));
559 talloc_autofree_ldapmsg(memctx
, result
);
561 count
= ldap_count_entries(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
563 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL
));
567 entry
= ldap_first_entry(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
569 id_str
= smbldap_talloc_single_attribute(idmap_alloc_ldap
->smbldap_state
->ldap_struct
,
570 entry
, type
, memctx
);
572 DEBUG(0,("%s attribute not found\n", type
));
576 DEBUG(0,("Out of memory\n"));
577 ret
= NT_STATUS_NO_MEMORY
;
581 xid
->id
= strtoul(id_str
, NULL
, 10);
588 /**********************************
590 **********************************/
592 static NTSTATUS
idmap_ldap_set_hwm(struct unixid
*xid
)
595 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
596 int rc
= LDAP_SERVER_DOWN
;
598 LDAPMessage
*result
= NULL
;
599 LDAPMessage
*entry
= NULL
;
600 LDAPMod
**mods
= NULL
;
603 const char *dn
= NULL
;
604 const char **attr_list
;
607 /* Only do query if we are online */
608 if (idmap_is_offline()) {
609 return NT_STATUS_FILE_IS_OFFLINE
;
612 if ( ! idmap_alloc_ldap
) {
613 return NT_STATUS_UNSUCCESSFUL
;
616 ctx
= talloc_new(idmap_alloc_ldap
);
618 DEBUG(0, ("Out of memory!\n"));
619 return NT_STATUS_NO_MEMORY
;
626 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
630 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
634 DEBUG(2, ("Invalid ID type (0x%x)\n", xid
->type
));
635 return NT_STATUS_INVALID_PARAMETER
;
638 filter
= talloc_asprintf(ctx
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
639 CHECK_ALLOC_DONE(filter
);
641 attr_list
= get_attr_list(ctx
, idpool_attr_list
);
642 CHECK_ALLOC_DONE(attr_list
);
644 rc
= smbldap_search(idmap_alloc_ldap
->smbldap_state
,
645 idmap_alloc_ldap
->suffix
,
646 LDAP_SCOPE_SUBTREE
, filter
,
647 attr_list
, 0, &result
);
649 if (rc
!= LDAP_SUCCESS
) {
650 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL
));
654 talloc_autofree_ldapmsg(ctx
, result
);
656 count
= ldap_count_entries(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
658 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL
));
662 entry
= ldap_first_entry(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
664 dn
= smbldap_talloc_dn(ctx
, idmap_alloc_ldap
->smbldap_state
->ldap_struct
, entry
);
669 new_id_str
= talloc_asprintf(ctx
, "%lu", (unsigned long)xid
->id
);
671 DEBUG(0,("Out of memory\n"));
672 ret
= NT_STATUS_NO_MEMORY
;
676 smbldap_set_mod(&mods
, LDAP_MOD_REPLACE
, type
, new_id_str
);
679 DEBUG(0,("smbldap_set_mod() failed.\n"));
683 rc
= smbldap_modify(idmap_alloc_ldap
->smbldap_state
, dn
, mods
);
685 ldap_mods_free(mods
, True
);
687 if (rc
!= LDAP_SUCCESS
) {
688 DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type
));
699 /**********************************
700 Close idmap ldap alloc
701 **********************************/
703 static NTSTATUS
idmap_ldap_alloc_close(void)
705 if (idmap_alloc_ldap
) {
706 smbldap_free_struct(&idmap_alloc_ldap
->smbldap_state
);
707 DEBUG(5,("The connection to the LDAP server was closed\n"));
708 /* maybe free the results here --metze */
709 TALLOC_FREE(idmap_alloc_ldap
);
715 /**********************************************************************
716 IDMAP MAPPING LDAP BACKEND
717 **********************************************************************/
719 static int idmap_ldap_close_destructor(struct idmap_ldap_context
*ctx
)
721 smbldap_free_struct(&ctx
->smbldap_state
);
722 DEBUG(5,("The connection to the LDAP server was closed\n"));
723 /* maybe free the results here --metze */
728 /********************************
729 Initialise idmap database.
730 ********************************/
732 static NTSTATUS
idmap_ldap_db_init(struct idmap_domain
*dom
)
735 struct idmap_ldap_context
*ctx
= NULL
;
736 char *config_option
= NULL
;
737 const char *range
= NULL
;
738 const char *tmp
= NULL
;
740 /* Only do init if we are online */
741 if (idmap_is_offline()) {
742 return NT_STATUS_FILE_IS_OFFLINE
;
745 ctx
= TALLOC_ZERO_P(dom
, struct idmap_ldap_context
);
747 DEBUG(0, ("Out of memory!\n"));
748 return NT_STATUS_NO_MEMORY
;
751 config_option
= talloc_asprintf(ctx
, "idmap config %s", dom
->name
);
752 if ( ! config_option
) {
753 DEBUG(0, ("Out of memory!\n"));
754 ret
= NT_STATUS_NO_MEMORY
;
759 range
= lp_parm_const_string(-1, config_option
, "range", NULL
);
760 if (range
&& range
[0]) {
761 if ((sscanf(range
, "%u - %u", &ctx
->filter_low_id
, &ctx
->filter_high_id
) != 2) ||
762 (ctx
->filter_low_id
> ctx
->filter_high_id
)) {
763 DEBUG(1, ("ERROR: invalid filter range [%s]", range
));
764 ctx
->filter_low_id
= 0;
765 ctx
->filter_high_id
= 0;
769 if (dom
->params
&& *(dom
->params
)) {
770 /* assume location is the only parameter */
771 ctx
->url
= talloc_strdup(ctx
, dom
->params
);
773 tmp
= lp_parm_const_string(-1, config_option
, "ldap_url", NULL
);
776 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
777 ret
= NT_STATUS_UNSUCCESSFUL
;
781 ctx
->url
= talloc_strdup(ctx
, tmp
);
783 CHECK_ALLOC_DONE(ctx
->url
);
785 tmp
= lp_ldap_idmap_suffix();
786 if ( ! tmp
|| ! *tmp
) {
787 tmp
= lp_parm_const_string(-1, config_option
, "ldap_base_dn", NULL
);
790 tmp
= lp_ldap_suffix();
792 DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp
));
793 DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
795 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
796 ret
= NT_STATUS_UNSUCCESSFUL
;
800 ctx
->suffix
= talloc_strdup(ctx
, tmp
);
801 CHECK_ALLOC_DONE(ctx
->suffix
);
803 ret
= smbldap_init(ctx
, winbind_event_context(), ctx
->url
,
804 &ctx
->smbldap_state
);
805 if (!NT_STATUS_IS_OK(ret
)) {
806 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx
->url
));
810 ret
= get_credentials( ctx
, ctx
->smbldap_state
, config_option
,
811 dom
, &ctx
->user_dn
);
812 if ( !NT_STATUS_IS_OK(ret
) ) {
813 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
814 "credentials (%s)\n", nt_errstr(ret
)));
818 /* set the destructor on the context, so that resource are properly
819 freed if the contexts is released */
821 talloc_set_destructor(ctx
, idmap_ldap_close_destructor
);
823 dom
->private_data
= ctx
;
824 dom
->initialized
= True
;
826 talloc_free(config_option
);
835 /* max number of ids requested per batch query */
836 #define IDMAP_LDAP_MAX_IDS 30
838 /**********************************
839 lookup a set of unix ids.
840 **********************************/
842 /* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
843 static struct id_map
*find_map_by_id(struct id_map
**maps
, enum id_type type
, uint32_t id
)
847 for (i
= 0; i
< IDMAP_LDAP_MAX_IDS
; i
++) {
848 if (maps
[i
] == NULL
) { /* end of the run */
851 if ((maps
[i
]->xid
.type
== type
) && (maps
[i
]->xid
.id
== id
)) {
859 static NTSTATUS
idmap_ldap_unixids_to_sids(struct idmap_domain
*dom
, struct id_map
**ids
)
863 struct idmap_ldap_context
*ctx
;
864 LDAPMessage
*result
= NULL
;
865 const char *uidNumber
;
866 const char *gidNumber
;
867 const char **attr_list
;
876 /* Only do query if we are online */
877 if (idmap_is_offline()) {
878 return NT_STATUS_FILE_IS_OFFLINE
;
881 /* Initilization my have been deferred because we were offline */
882 if ( ! dom
->initialized
) {
883 ret
= idmap_ldap_db_init(dom
);
884 if ( ! NT_STATUS_IS_OK(ret
)) {
889 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
891 memctx
= talloc_new(ctx
);
893 DEBUG(0, ("Out of memory!\n"));
894 return NT_STATUS_NO_MEMORY
;
897 uidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
898 gidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
900 attr_list
= get_attr_list(ctx
, sidmap_attr_list
);
903 /* if we are requested just one mapping use the simple filter */
905 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(%s=%lu))",
906 LDAP_OBJ_IDMAP_ENTRY
,
907 (ids
[0]->xid
.type
==ID_TYPE_UID
)?uidNumber
:gidNumber
,
908 (unsigned long)ids
[0]->xid
.id
);
909 CHECK_ALLOC_DONE(filter
);
910 DEBUG(10, ("Filter: [%s]\n", filter
));
912 /* multiple mappings */
920 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY
);
921 CHECK_ALLOC_DONE(filter
);
924 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
925 filter
= talloc_asprintf_append(filter
, "(%s=%lu)",
926 (ids
[idx
]->xid
.type
==ID_TYPE_UID
)?uidNumber
:gidNumber
,
927 (unsigned long)ids
[idx
]->xid
.id
);
928 CHECK_ALLOC_DONE(filter
);
930 filter
= talloc_asprintf_append(filter
, "))");
931 CHECK_ALLOC_DONE(filter
);
932 DEBUG(10, ("Filter: [%s]\n", 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 ids (%s)\n", ldap_err2string(rc
)));
943 ret
= NT_STATUS_UNSUCCESSFUL
;
947 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
950 DEBUG(10, ("NO SIDs found\n"));
953 for (i
= 0; i
< count
; i
++) {
954 LDAPMessage
*entry
= NULL
;
961 if (i
== 0) { /* first entry */
962 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
, result
);
963 } else { /* following ones */
964 entry
= ldap_next_entry(ctx
->smbldap_state
->ldap_struct
, entry
);
967 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
971 /* first check if the SID is present */
972 sidstr
= smbldap_talloc_single_attribute(
973 ctx
->smbldap_state
->ldap_struct
,
974 entry
, LDAP_ATTRIBUTE_SID
, memctx
);
975 if ( ! sidstr
) { /* no sid, skip entry */
976 DEBUG(2, ("WARNING SID not found on entry\n"));
980 /* now try to see if it is a uid, if not try with a gid
981 * (gid is more common, but in case both uidNumber and
982 * gidNumber are returned the SID is mapped to the uid not the gid) */
984 tmp
= smbldap_talloc_single_attribute(
985 ctx
->smbldap_state
->ldap_struct
,
986 entry
, uidNumber
, memctx
);
989 tmp
= smbldap_talloc_single_attribute(
990 ctx
->smbldap_state
->ldap_struct
,
991 entry
, gidNumber
, memctx
);
993 if ( ! tmp
) { /* wow very strange entry, how did it match ? */
994 DEBUG(5, ("Unprobable match on (%s), no uidNumber, nor gidNumber returned\n", sidstr
));
999 id
= strtoul(tmp
, NULL
, 10);
1001 (ctx
->filter_low_id
&& (id
< ctx
->filter_low_id
)) ||
1002 (ctx
->filter_high_id
&& (id
> ctx
->filter_high_id
))) {
1003 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
1004 id
, ctx
->filter_low_id
, ctx
->filter_high_id
));
1005 TALLOC_FREE(sidstr
);
1011 map
= find_map_by_id(&ids
[bidx
], type
, id
);
1013 DEBUG(2, ("WARNING: couldn't match sid (%s) with requested ids\n", sidstr
));
1014 TALLOC_FREE(sidstr
);
1018 if ( ! string_to_sid(map
->sid
, sidstr
)) {
1019 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1020 TALLOC_FREE(sidstr
);
1023 TALLOC_FREE(sidstr
);
1026 map
->status
= ID_MAPPED
;
1028 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map
->sid
), (unsigned long)map
->xid
.id
, map
->xid
.type
));
1031 /* free the ldap results */
1033 ldap_msgfree(result
);
1037 if (multi
&& ids
[idx
]) { /* still some values to map */
1043 /* mark all unknwon/expired ones as unmapped */
1044 for (i
= 0; ids
[i
]; i
++) {
1045 if (ids
[i
]->status
!= ID_MAPPED
)
1046 ids
[i
]->status
= ID_UNMAPPED
;
1050 talloc_free(memctx
);
1054 /**********************************
1055 lookup a set of sids.
1056 **********************************/
1058 /* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
1059 static struct id_map
*find_map_by_sid(struct id_map
**maps
, DOM_SID
*sid
)
1063 for (i
= 0; i
< IDMAP_LDAP_MAX_IDS
; i
++) {
1064 if (maps
[i
] == NULL
) { /* end of the run */
1067 if (sid_equal(maps
[i
]->sid
, sid
)) {
1075 static NTSTATUS
idmap_ldap_sids_to_unixids(struct idmap_domain
*dom
, struct id_map
**ids
)
1077 LDAPMessage
*entry
= NULL
;
1080 struct idmap_ldap_context
*ctx
;
1081 LDAPMessage
*result
= NULL
;
1082 const char *uidNumber
;
1083 const char *gidNumber
;
1084 const char **attr_list
;
1085 char *filter
= NULL
;
1093 /* Only do query if we are online */
1094 if (idmap_is_offline()) {
1095 return NT_STATUS_FILE_IS_OFFLINE
;
1098 /* Initilization my have been deferred because we were offline */
1099 if ( ! dom
->initialized
) {
1100 ret
= idmap_ldap_db_init(dom
);
1101 if ( ! NT_STATUS_IS_OK(ret
)) {
1106 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
1108 memctx
= talloc_new(ctx
);
1110 DEBUG(0, ("Out of memory!\n"));
1111 return NT_STATUS_NO_MEMORY
;
1114 uidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
1115 gidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
1117 attr_list
= get_attr_list(ctx
, sidmap_attr_list
);
1120 /* if we are requested just one mapping use the simple filter */
1122 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(%s=%s))",
1123 LDAP_OBJ_IDMAP_ENTRY
,
1125 sid_string_static(ids
[0]->sid
));
1126 CHECK_ALLOC_DONE(filter
);
1127 DEBUG(10, ("Filter: [%s]\n", filter
));
1129 /* multiple mappings */
1136 TALLOC_FREE(filter
);
1137 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY
);
1138 CHECK_ALLOC_DONE(filter
);
1141 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
1142 filter
= talloc_asprintf_append(filter
, "(%s=%s)",
1144 sid_string_static(ids
[idx
]->sid
));
1145 CHECK_ALLOC_DONE(filter
);
1147 filter
= talloc_asprintf_append(filter
, "))");
1148 CHECK_ALLOC_DONE(filter
);
1149 DEBUG(10, ("Filter: [%s]", filter
));
1155 rc
= smbldap_search(ctx
->smbldap_state
, ctx
->suffix
, LDAP_SCOPE_SUBTREE
,
1156 filter
, attr_list
, 0, &result
);
1158 if (rc
!= LDAP_SUCCESS
) {
1159 DEBUG(3,("Failure looking up sids (%s)\n", ldap_err2string(rc
)));
1160 ret
= NT_STATUS_UNSUCCESSFUL
;
1164 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
1167 DEBUG(10, ("NO SIDs found\n"));
1170 for (i
= 0; i
< count
; i
++) {
1171 char *sidstr
= NULL
;
1178 if (i
== 0) { /* first entry */
1179 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
, result
);
1180 } else { /* following ones */
1181 entry
= ldap_next_entry(ctx
->smbldap_state
->ldap_struct
, entry
);
1184 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
1188 /* first check if the SID is present */
1189 sidstr
= smbldap_talloc_single_attribute(
1190 ctx
->smbldap_state
->ldap_struct
,
1191 entry
, LDAP_ATTRIBUTE_SID
, memctx
);
1192 if ( ! sidstr
) { /* no sid ??, skip entry */
1193 DEBUG(2, ("WARNING SID not found on entry\n"));
1197 if ( ! string_to_sid(&sid
, sidstr
)) {
1198 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1199 TALLOC_FREE(sidstr
);
1203 map
= find_map_by_sid(&ids
[bidx
], &sid
);
1205 DEBUG(2, ("WARNING: couldn't find entry sid (%s) in ids", sidstr
));
1206 TALLOC_FREE(sidstr
);
1210 TALLOC_FREE(sidstr
);
1212 /* now try to see if it is a uid, if not try with a gid
1213 * (gid is more common, but in case both uidNumber and
1214 * gidNumber are returned the SID is mapped to the uid not the gid) */
1216 tmp
= smbldap_talloc_single_attribute(
1217 ctx
->smbldap_state
->ldap_struct
,
1218 entry
, uidNumber
, memctx
);
1221 tmp
= smbldap_talloc_single_attribute(
1222 ctx
->smbldap_state
->ldap_struct
,
1223 entry
, gidNumber
, memctx
);
1225 if ( ! tmp
) { /* no ids ?? */
1226 DEBUG(5, ("no uidNumber, nor gidNumber attributes found\n"));
1230 id
= strtoul(tmp
, NULL
, 10);
1232 (ctx
->filter_low_id
&& (id
< ctx
->filter_low_id
)) ||
1233 (ctx
->filter_high_id
&& (id
> ctx
->filter_high_id
))) {
1234 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
1235 id
, ctx
->filter_low_id
, ctx
->filter_high_id
));
1242 map
->xid
.type
= type
;
1244 map
->status
= ID_MAPPED
;
1246 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map
->sid
), (unsigned long)map
->xid
.id
, map
->xid
.type
));
1249 /* free the ldap results */
1251 ldap_msgfree(result
);
1255 if (multi
&& ids
[idx
]) { /* still some values to map */
1261 /* mark all unknwon/expired ones as unmapped */
1262 for (i
= 0; ids
[i
]; i
++) {
1263 if (ids
[i
]->status
!= ID_MAPPED
)
1264 ids
[i
]->status
= ID_UNMAPPED
;
1268 talloc_free(memctx
);
1272 /**********************************
1274 **********************************/
1276 /* TODO: change this: This function cannot be called to modify a mapping, only set a new one */
1278 static NTSTATUS
idmap_ldap_set_mapping(struct idmap_domain
*dom
, const struct id_map
*map
)
1282 struct idmap_ldap_context
*ctx
;
1283 LDAPMessage
*entry
= NULL
;
1284 LDAPMod
**mods
= NULL
;
1291 /* Only do query if we are online */
1292 if (idmap_is_offline()) {
1293 return NT_STATUS_FILE_IS_OFFLINE
;
1296 /* Initilization my have been deferred because we were offline */
1297 if ( ! dom
->initialized
) {
1298 ret
= idmap_ldap_db_init(dom
);
1299 if ( ! NT_STATUS_IS_OK(ret
)) {
1304 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
1306 switch(map
->xid
.type
) {
1308 type
= get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_UIDNUMBER
);
1312 type
= get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_GIDNUMBER
);
1316 return NT_STATUS_INVALID_PARAMETER
;
1319 memctx
= talloc_new(ctx
);
1321 DEBUG(0, ("Out of memory!\n"));
1322 return NT_STATUS_NO_MEMORY
;
1325 id_str
= talloc_asprintf(memctx
, "%lu", (unsigned long)map
->xid
.id
);
1326 CHECK_ALLOC_DONE(id_str
);
1328 sid
= talloc_strdup(memctx
, sid_string_static(map
->sid
));
1329 CHECK_ALLOC_DONE(sid
);
1331 dn
= talloc_asprintf(memctx
, "%s=%s,%s",
1332 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
),
1335 CHECK_ALLOC_DONE(dn
);
1337 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_IDMAP_ENTRY
);
1339 smbldap_make_mod(ctx
->smbldap_state
->ldap_struct
, entry
, &mods
, type
, id_str
);
1341 smbldap_make_mod(ctx
->smbldap_state
->ldap_struct
, entry
, &mods
,
1342 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
), sid
);
1345 DEBUG(2, ("ERROR: No mods?\n"));
1346 ret
= NT_STATUS_UNSUCCESSFUL
;
1350 /* TODO: remove conflicting mappings! */
1352 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_SID_ENTRY
);
1354 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn
, sid
, id_str
));
1356 rc
= smbldap_add(ctx
->smbldap_state
, dn
, mods
);
1357 ldap_mods_free(mods
, True
);
1359 if (rc
!= LDAP_SUCCESS
) {
1360 char *ld_error
= NULL
;
1361 ldap_get_option(ctx
->smbldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1362 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu mapping [%s]\n",
1363 sid
, (unsigned long)map
->xid
.id
, type
));
1364 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1365 ld_error
? ld_error
: "(NULL)", ldap_err2string (rc
)));
1367 ldap_memfree(ld_error
);
1369 ret
= NT_STATUS_UNSUCCESSFUL
;
1373 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
1374 sid
, (unsigned long)map
->xid
.id
, type
));
1379 talloc_free(memctx
);
1383 /**********************************
1384 Close the idmap ldap instance
1385 **********************************/
1387 static NTSTATUS
idmap_ldap_close(struct idmap_domain
*dom
)
1389 struct idmap_ldap_context
*ctx
;
1391 if (dom
->private_data
) {
1392 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
1395 dom
->private_data
= NULL
;
1398 return NT_STATUS_OK
;
1401 static struct idmap_methods idmap_ldap_methods
= {
1403 .init
= idmap_ldap_db_init
,
1404 .unixids_to_sids
= idmap_ldap_unixids_to_sids
,
1405 .sids_to_unixids
= idmap_ldap_sids_to_unixids
,
1406 .set_mapping
= idmap_ldap_set_mapping
,
1407 .close_fn
= idmap_ldap_close
1410 static struct idmap_alloc_methods idmap_ldap_alloc_methods
= {
1412 .init
= idmap_ldap_alloc_init
,
1413 .allocate_id
= idmap_ldap_allocate_id
,
1414 .get_id_hwm
= idmap_ldap_get_hwm
,
1415 .set_id_hwm
= idmap_ldap_set_hwm
,
1416 .close_fn
= idmap_ldap_alloc_close
,
1417 /* .dump_data = TODO */
1420 NTSTATUS
idmap_alloc_ldap_init(void)
1422 return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION
, "ldap", &idmap_ldap_alloc_methods
);
1425 NTSTATUS
idmap_ldap_init(void)
1429 /* FIXME: bad hack to actually register also the alloc_ldap module without changining configure.in */
1430 ret
= idmap_alloc_ldap_init();
1431 if (! NT_STATUS_IS_OK(ret
)) {
1434 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
, "ldap", &idmap_ldap_methods
);