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_context
{
37 struct smbldap_state
*smbldap_state
;
41 uint32_t filter_low_id
, filter_high_id
; /* Filter range */
45 struct idmap_ldap_alloc_context
{
46 struct smbldap_state
*smbldap_state
;
50 uid_t low_uid
, high_uid
; /* Range of uids */
51 gid_t low_gid
, high_gid
; /* Range of gids */
55 #define CHECK_ALLOC_DONE(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while (0)
57 /**********************************************************************
58 IDMAP ALLOC TDB BACKEND
59 **********************************************************************/
61 static struct idmap_ldap_alloc_context
*idmap_alloc_ldap
;
63 /*********************************************************************
64 ********************************************************************/
66 static NTSTATUS
get_credentials( TALLOC_CTX
*mem_ctx
,
67 struct smbldap_state
*ldap_state
,
68 const char *config_option
,
69 struct idmap_domain
*dom
,
72 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
75 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 /* only the alloc backend is allowed to pass in a NULL dom */
84 secret
= idmap_fetch_secret("ldap", true, NULL
, tmp
);
86 secret
= idmap_fetch_secret("ldap", false, dom
->name
, tmp
);
90 DEBUG(0, ("get_credentials: Unable to fetch "
91 "auth credentials for %s in %s\n",
92 tmp
, (dom
==NULL
)?"ALLOC":dom
->name
));
93 ret
= NT_STATUS_ACCESS_DENIED
;
96 *dn
= talloc_strdup(mem_ctx
, tmp
);
97 CHECK_ALLOC_DONE(*dn
);
99 if ( !fetch_ldap_pw( &user_dn
, &secret
) ) {
100 DEBUG(2, ("get_credentials: Failed to lookup ldap "
101 "bind creds. Using anonymous connection.\n"));
102 *dn
= talloc_strdup( mem_ctx
, "" );
104 *dn
= talloc_strdup(mem_ctx
, user_dn
);
105 SAFE_FREE( user_dn
);
106 CHECK_ALLOC_DONE(*dn
);
110 smbldap_set_creds(ldap_state
, false, *dn
, secret
);
120 /**********************************************************************
121 Verify the sambaUnixIdPool entry in the directory.
122 **********************************************************************/
124 static NTSTATUS
verify_idpool(void)
128 LDAPMessage
*result
= NULL
;
129 LDAPMod
**mods
= NULL
;
130 const char **attr_list
;
135 if ( ! idmap_alloc_ldap
) {
136 return NT_STATUS_UNSUCCESSFUL
;
139 ctx
= talloc_new(idmap_alloc_ldap
);
141 DEBUG(0, ("Out of memory!\n"));
142 return NT_STATUS_NO_MEMORY
;
145 filter
= talloc_asprintf(ctx
, "(objectclass=%s)", LDAP_OBJ_IDPOOL
);
146 CHECK_ALLOC_DONE(filter
);
148 attr_list
= get_attr_list(ctx
, idpool_attr_list
);
149 CHECK_ALLOC_DONE(attr_list
);
151 rc
= smbldap_search(idmap_alloc_ldap
->smbldap_state
,
152 idmap_alloc_ldap
->suffix
,
159 if (rc
!= LDAP_SUCCESS
) {
160 DEBUG(1, ("Unable to verify the idpool, cannot continue initialization!\n"));
161 return NT_STATUS_UNSUCCESSFUL
;
164 count
= ldap_count_entries(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
166 ldap_msgfree(result
);
169 DEBUG(0,("Multiple entries returned from %s (base == %s)\n",
170 filter
, idmap_alloc_ldap
->suffix
));
171 ret
= NT_STATUS_UNSUCCESSFUL
;
174 else if (count
== 0) {
175 char *uid_str
, *gid_str
;
177 uid_str
= talloc_asprintf(ctx
, "%lu", (unsigned long)idmap_alloc_ldap
->low_uid
);
178 gid_str
= talloc_asprintf(ctx
, "%lu", (unsigned long)idmap_alloc_ldap
->low_gid
);
180 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
181 "objectClass", LDAP_OBJ_IDPOOL
);
182 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
183 get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
),
185 smbldap_set_mod(&mods
, LDAP_MOD_ADD
,
186 get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
),
189 rc
= smbldap_modify(idmap_alloc_ldap
->smbldap_state
,
190 idmap_alloc_ldap
->suffix
,
192 ldap_mods_free(mods
, True
);
194 ret
= NT_STATUS_UNSUCCESSFUL
;
199 ret
= (rc
== LDAP_SUCCESS
)?NT_STATUS_OK
:NT_STATUS_UNSUCCESSFUL
;
205 /*****************************************************************************
206 Initialise idmap database.
207 *****************************************************************************/
209 static NTSTATUS
idmap_ldap_alloc_init(const char *params
)
211 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
219 /* Only do init if we are online */
220 if (idmap_is_offline()) {
221 return NT_STATUS_FILE_IS_OFFLINE
;
224 idmap_alloc_ldap
= TALLOC_ZERO_P(NULL
, struct idmap_ldap_alloc_context
);
225 CHECK_ALLOC_DONE( idmap_alloc_ldap
);
229 idmap_alloc_ldap
->low_uid
= 0;
230 idmap_alloc_ldap
->high_uid
= 0;
231 idmap_alloc_ldap
->low_gid
= 0;
232 idmap_alloc_ldap
->high_gid
= 0;
234 range
= lp_parm_const_string(-1, "idmap alloc config", "range", NULL
);
235 if (range
&& range
[0]) {
236 unsigned low_id
, high_id
;
238 if (sscanf(range
, "%u - %u", &low_id
, &high_id
) == 2) {
239 if (low_id
< high_id
) {
240 idmap_alloc_ldap
->low_gid
= idmap_alloc_ldap
->low_uid
= low_id
;
241 idmap_alloc_ldap
->high_gid
= idmap_alloc_ldap
->high_uid
= high_id
;
243 DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range
));
246 DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range
));
250 if (lp_idmap_uid(&low_uid
, &high_uid
)) {
251 idmap_alloc_ldap
->low_uid
= low_uid
;
252 idmap_alloc_ldap
->high_uid
= high_uid
;
255 if (lp_idmap_gid(&low_gid
, &high_gid
)) {
256 idmap_alloc_ldap
->low_gid
= low_gid
;
257 idmap_alloc_ldap
->high_gid
= high_gid
;
260 if (idmap_alloc_ldap
->high_uid
<= idmap_alloc_ldap
->low_uid
) {
261 DEBUG(1, ("idmap uid range missing or invalid\n"));
262 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
263 ret
= NT_STATUS_UNSUCCESSFUL
;
267 if (idmap_alloc_ldap
->high_gid
<= idmap_alloc_ldap
->low_gid
) {
268 DEBUG(1, ("idmap gid range missing or invalid\n"));
269 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
270 ret
= NT_STATUS_UNSUCCESSFUL
;
274 if (params
&& *params
) {
275 /* assume location is the only parameter */
276 idmap_alloc_ldap
->url
= talloc_strdup(idmap_alloc_ldap
, params
);
278 tmp
= lp_parm_const_string(-1, "idmap alloc config", "ldap_url", NULL
);
281 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
282 ret
= NT_STATUS_UNSUCCESSFUL
;
286 idmap_alloc_ldap
->url
= talloc_strdup(idmap_alloc_ldap
, tmp
);
288 CHECK_ALLOC_DONE( idmap_alloc_ldap
->url
);
290 tmp
= lp_ldap_idmap_suffix();
291 if ( ! tmp
|| ! *tmp
) {
292 tmp
= lp_parm_const_string(-1, "idmap alloc config", "ldap_base_dn", NULL
);
295 tmp
= lp_ldap_suffix();
297 DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp
));
298 DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
301 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
302 ret
= NT_STATUS_UNSUCCESSFUL
;
307 idmap_alloc_ldap
->suffix
= talloc_strdup(idmap_alloc_ldap
, tmp
);
308 CHECK_ALLOC_DONE( idmap_alloc_ldap
->suffix
);
310 ret
= smbldap_init(idmap_alloc_ldap
, idmap_alloc_ldap
->url
,
311 &idmap_alloc_ldap
->smbldap_state
);
312 if (!NT_STATUS_IS_OK(ret
)) {
313 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n",
314 idmap_alloc_ldap
->url
));
318 ret
= get_credentials( idmap_alloc_ldap
,
319 idmap_alloc_ldap
->smbldap_state
,
320 "idmap alloc config", NULL
,
321 &idmap_alloc_ldap
->user_dn
);
322 if ( !NT_STATUS_IS_OK(ret
) ) {
323 DEBUG(1,("idmap_ldap_alloc_init: Failed to get connection "
324 "credentials (%s)\n", nt_errstr(ret
)));
328 /* see if the idmap suffix and sub entries exists */
330 ret
= verify_idpool();
333 if ( !NT_STATUS_IS_OK( ret
) )
334 TALLOC_FREE( idmap_alloc_ldap
);
339 /********************************
340 Allocate a new uid or gid
341 ********************************/
343 static NTSTATUS
idmap_ldap_allocate_id(struct unixid
*xid
)
346 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
347 int rc
= LDAP_SERVER_DOWN
;
349 LDAPMessage
*result
= NULL
;
350 LDAPMessage
*entry
= NULL
;
351 LDAPMod
**mods
= NULL
;
355 const char *dn
= NULL
;
356 const char **attr_list
;
359 /* Only do query if we are online */
360 if (idmap_is_offline()) {
361 return NT_STATUS_FILE_IS_OFFLINE
;
364 if ( ! idmap_alloc_ldap
) {
365 return NT_STATUS_UNSUCCESSFUL
;
368 ctx
= talloc_new(idmap_alloc_ldap
);
370 DEBUG(0, ("Out of memory!\n"));
371 return NT_STATUS_NO_MEMORY
;
378 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
382 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
386 DEBUG(2, ("Invalid ID type (0x%x)\n", xid
->type
));
387 return NT_STATUS_INVALID_PARAMETER
;
390 filter
= talloc_asprintf(ctx
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
391 CHECK_ALLOC_DONE(filter
);
393 attr_list
= get_attr_list(ctx
, idpool_attr_list
);
394 CHECK_ALLOC_DONE(attr_list
);
396 DEBUG(10, ("Search of the id pool (filter: %s)\n", filter
));
398 rc
= smbldap_search(idmap_alloc_ldap
->smbldap_state
,
399 idmap_alloc_ldap
->suffix
,
400 LDAP_SCOPE_SUBTREE
, filter
,
401 attr_list
, 0, &result
);
403 if (rc
!= LDAP_SUCCESS
) {
404 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL
));
408 talloc_autofree_ldapmsg(ctx
, result
);
410 count
= ldap_count_entries(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
412 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL
));
416 entry
= ldap_first_entry(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
418 dn
= smbldap_talloc_dn(ctx
, idmap_alloc_ldap
->smbldap_state
->ldap_struct
, entry
);
423 if ( ! (id_str
= smbldap_talloc_single_attribute(idmap_alloc_ldap
->smbldap_state
->ldap_struct
,
424 entry
, type
, ctx
))) {
425 DEBUG(0,("%s attribute not found\n", type
));
429 DEBUG(0,("Out of memory\n"));
430 ret
= NT_STATUS_NO_MEMORY
;
434 xid
->id
= strtoul(id_str
, NULL
, 10);
436 /* make sure we still have room to grow */
440 if (xid
->id
> idmap_alloc_ldap
->high_uid
) {
441 DEBUG(0,("Cannot allocate uid above %lu!\n",
442 (unsigned long)idmap_alloc_ldap
->high_uid
));
448 if (xid
->id
> idmap_alloc_ldap
->high_gid
) {
449 DEBUG(0,("Cannot allocate gid above %lu!\n",
450 (unsigned long)idmap_alloc_ldap
->high_uid
));
460 new_id_str
= talloc_asprintf(ctx
, "%lu", (unsigned long)xid
->id
+ 1);
462 DEBUG(0,("Out of memory\n"));
463 ret
= NT_STATUS_NO_MEMORY
;
467 smbldap_set_mod(&mods
, LDAP_MOD_DELETE
, type
, id_str
);
468 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, type
, new_id_str
);
471 DEBUG(0,("smbldap_set_mod() failed.\n"));
475 DEBUG(10, ("Try to atomically increment the id (%s -> %s)\n", id_str
, new_id_str
));
477 rc
= smbldap_modify(idmap_alloc_ldap
->smbldap_state
, dn
, mods
);
479 ldap_mods_free(mods
, True
);
481 if (rc
!= LDAP_SUCCESS
) {
482 DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type
));
493 /**********************************
494 Get current highest id.
495 **********************************/
497 static NTSTATUS
idmap_ldap_get_hwm(struct unixid
*xid
)
500 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
501 int rc
= LDAP_SERVER_DOWN
;
503 LDAPMessage
*result
= NULL
;
504 LDAPMessage
*entry
= NULL
;
507 const char **attr_list
;
510 /* Only do query if we are online */
511 if (idmap_is_offline()) {
512 return NT_STATUS_FILE_IS_OFFLINE
;
515 if ( ! idmap_alloc_ldap
) {
516 return NT_STATUS_UNSUCCESSFUL
;
519 memctx
= talloc_new(idmap_alloc_ldap
);
521 DEBUG(0, ("Out of memory!\n"));
522 return NT_STATUS_NO_MEMORY
;
529 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
533 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
537 DEBUG(2, ("Invalid ID type (0x%x)\n", xid
->type
));
538 return NT_STATUS_INVALID_PARAMETER
;
541 filter
= talloc_asprintf(memctx
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
542 CHECK_ALLOC_DONE(filter
);
544 attr_list
= get_attr_list(memctx
, idpool_attr_list
);
545 CHECK_ALLOC_DONE(attr_list
);
547 rc
= smbldap_search(idmap_alloc_ldap
->smbldap_state
,
548 idmap_alloc_ldap
->suffix
,
549 LDAP_SCOPE_SUBTREE
, filter
,
550 attr_list
, 0, &result
);
552 if (rc
!= LDAP_SUCCESS
) {
553 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL
));
557 talloc_autofree_ldapmsg(memctx
, result
);
559 count
= ldap_count_entries(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
561 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL
));
565 entry
= ldap_first_entry(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
567 id_str
= smbldap_talloc_single_attribute(idmap_alloc_ldap
->smbldap_state
->ldap_struct
,
568 entry
, type
, memctx
);
570 DEBUG(0,("%s attribute not found\n", type
));
574 DEBUG(0,("Out of memory\n"));
575 ret
= NT_STATUS_NO_MEMORY
;
579 xid
->id
= strtoul(id_str
, NULL
, 10);
586 /**********************************
588 **********************************/
590 static NTSTATUS
idmap_ldap_set_hwm(struct unixid
*xid
)
593 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
594 int rc
= LDAP_SERVER_DOWN
;
596 LDAPMessage
*result
= NULL
;
597 LDAPMessage
*entry
= NULL
;
598 LDAPMod
**mods
= NULL
;
601 const char *dn
= NULL
;
602 const char **attr_list
;
605 /* Only do query if we are online */
606 if (idmap_is_offline()) {
607 return NT_STATUS_FILE_IS_OFFLINE
;
610 if ( ! idmap_alloc_ldap
) {
611 return NT_STATUS_UNSUCCESSFUL
;
614 ctx
= talloc_new(idmap_alloc_ldap
);
616 DEBUG(0, ("Out of memory!\n"));
617 return NT_STATUS_NO_MEMORY
;
624 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
628 type
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
632 DEBUG(2, ("Invalid ID type (0x%x)\n", xid
->type
));
633 return NT_STATUS_INVALID_PARAMETER
;
636 filter
= talloc_asprintf(ctx
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
637 CHECK_ALLOC_DONE(filter
);
639 attr_list
= get_attr_list(ctx
, idpool_attr_list
);
640 CHECK_ALLOC_DONE(attr_list
);
642 rc
= smbldap_search(idmap_alloc_ldap
->smbldap_state
,
643 idmap_alloc_ldap
->suffix
,
644 LDAP_SCOPE_SUBTREE
, filter
,
645 attr_list
, 0, &result
);
647 if (rc
!= LDAP_SUCCESS
) {
648 DEBUG(0,("%s object not found\n", LDAP_OBJ_IDPOOL
));
652 talloc_autofree_ldapmsg(ctx
, result
);
654 count
= ldap_count_entries(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
656 DEBUG(0,("Single %s object not found\n", LDAP_OBJ_IDPOOL
));
660 entry
= ldap_first_entry(idmap_alloc_ldap
->smbldap_state
->ldap_struct
, result
);
662 dn
= smbldap_talloc_dn(ctx
, idmap_alloc_ldap
->smbldap_state
->ldap_struct
, entry
);
667 new_id_str
= talloc_asprintf(ctx
, "%lu", (unsigned long)xid
->id
);
669 DEBUG(0,("Out of memory\n"));
670 ret
= NT_STATUS_NO_MEMORY
;
674 smbldap_set_mod(&mods
, LDAP_MOD_REPLACE
, type
, new_id_str
);
677 DEBUG(0,("smbldap_set_mod() failed.\n"));
681 rc
= smbldap_modify(idmap_alloc_ldap
->smbldap_state
, dn
, mods
);
683 ldap_mods_free(mods
, True
);
685 if (rc
!= LDAP_SUCCESS
) {
686 DEBUG(1,("Failed to allocate new %s. smbldap_modify() failed.\n", type
));
697 /**********************************
698 Close idmap ldap alloc
699 **********************************/
701 static NTSTATUS
idmap_ldap_alloc_close(void)
703 if (idmap_alloc_ldap
) {
704 smbldap_free_struct(&idmap_alloc_ldap
->smbldap_state
);
705 DEBUG(5,("The connection to the LDAP server was closed\n"));
706 /* maybe free the results here --metze */
707 TALLOC_FREE(idmap_alloc_ldap
);
713 /**********************************************************************
714 IDMAP MAPPING LDAP BACKEND
715 **********************************************************************/
717 static int idmap_ldap_close_destructor(struct idmap_ldap_context
*ctx
)
719 smbldap_free_struct(&ctx
->smbldap_state
);
720 DEBUG(5,("The connection to the LDAP server was closed\n"));
721 /* maybe free the results here --metze */
726 /********************************
727 Initialise idmap database.
728 ********************************/
730 static NTSTATUS
idmap_ldap_db_init(struct idmap_domain
*dom
)
733 struct idmap_ldap_context
*ctx
= NULL
;
734 char *config_option
= NULL
;
735 const char *range
= NULL
;
736 const char *tmp
= NULL
;
738 /* Only do init if we are online */
739 if (idmap_is_offline()) {
740 return NT_STATUS_FILE_IS_OFFLINE
;
743 ctx
= TALLOC_ZERO_P(dom
, struct idmap_ldap_context
);
745 DEBUG(0, ("Out of memory!\n"));
746 return NT_STATUS_NO_MEMORY
;
749 config_option
= talloc_asprintf(ctx
, "idmap config %s", dom
->name
);
750 if ( ! config_option
) {
751 DEBUG(0, ("Out of memory!\n"));
752 ret
= NT_STATUS_NO_MEMORY
;
757 range
= lp_parm_const_string(-1, config_option
, "range", NULL
);
758 if (range
&& range
[0]) {
759 if ((sscanf(range
, "%u - %u", &ctx
->filter_low_id
, &ctx
->filter_high_id
) != 2) ||
760 (ctx
->filter_low_id
> ctx
->filter_high_id
)) {
761 DEBUG(1, ("ERROR: invalid filter range [%s]", range
));
762 ctx
->filter_low_id
= 0;
763 ctx
->filter_high_id
= 0;
767 if (dom
->params
&& *(dom
->params
)) {
768 /* assume location is the only parameter */
769 ctx
->url
= talloc_strdup(ctx
, dom
->params
);
771 tmp
= lp_parm_const_string(-1, config_option
, "ldap_url", NULL
);
774 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
775 ret
= NT_STATUS_UNSUCCESSFUL
;
779 ctx
->url
= talloc_strdup(ctx
, tmp
);
781 CHECK_ALLOC_DONE(ctx
->url
);
783 tmp
= lp_ldap_idmap_suffix();
784 if ( ! tmp
|| ! *tmp
) {
785 tmp
= lp_parm_const_string(-1, config_option
, "ldap_base_dn", NULL
);
788 tmp
= lp_ldap_suffix();
790 DEBUG(1, ("WARNING: Trying to use the global ldap suffix(%s)\n", tmp
));
791 DEBUGADD(1, ("as suffix. This may not be what you want!\n"));
793 DEBUG(1, ("ERROR: missing idmap ldap suffix\n"));
794 ret
= NT_STATUS_UNSUCCESSFUL
;
798 ctx
->suffix
= talloc_strdup(ctx
, tmp
);
799 CHECK_ALLOC_DONE(ctx
->suffix
);
801 ret
= smbldap_init(ctx
, ctx
->url
, &ctx
->smbldap_state
);
802 if (!NT_STATUS_IS_OK(ret
)) {
803 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", ctx
->url
));
807 ret
= get_credentials( ctx
, ctx
->smbldap_state
, config_option
,
808 dom
, &ctx
->user_dn
);
809 if ( !NT_STATUS_IS_OK(ret
) ) {
810 DEBUG(1,("idmap_ldap_db_init: Failed to get connection "
811 "credentials (%s)\n", nt_errstr(ret
)));
815 /* set the destructor on the context, so that resource are properly
816 freed if the contexts is released */
818 talloc_set_destructor(ctx
, idmap_ldap_close_destructor
);
820 dom
->private_data
= ctx
;
821 dom
->initialized
= True
;
823 talloc_free(config_option
);
832 /* max number of ids requested per batch query */
833 #define IDMAP_LDAP_MAX_IDS 30
835 /**********************************
836 lookup a set of unix ids.
837 **********************************/
839 /* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
840 static struct id_map
*find_map_by_id(struct id_map
**maps
, enum id_type type
, uint32_t id
)
844 for (i
= 0; i
< IDMAP_LDAP_MAX_IDS
; i
++) {
845 if (maps
[i
] == NULL
) { /* end of the run */
848 if ((maps
[i
]->xid
.type
== type
) && (maps
[i
]->xid
.id
== id
)) {
856 static NTSTATUS
idmap_ldap_unixids_to_sids(struct idmap_domain
*dom
, struct id_map
**ids
)
860 struct idmap_ldap_context
*ctx
;
861 LDAPMessage
*result
= NULL
;
862 const char *uidNumber
;
863 const char *gidNumber
;
864 const char **attr_list
;
873 /* Only do query if we are online */
874 if (idmap_is_offline()) {
875 return NT_STATUS_FILE_IS_OFFLINE
;
878 /* Initilization my have been deferred because we were offline */
879 if ( ! dom
->initialized
) {
880 ret
= idmap_ldap_db_init(dom
);
881 if ( ! NT_STATUS_IS_OK(ret
)) {
886 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
888 memctx
= talloc_new(ctx
);
890 DEBUG(0, ("Out of memory!\n"));
891 return NT_STATUS_NO_MEMORY
;
894 uidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
895 gidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
897 attr_list
= get_attr_list(ctx
, sidmap_attr_list
);
900 /* if we are requested just one mapping use the simple filter */
902 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(%s=%lu))",
903 LDAP_OBJ_IDMAP_ENTRY
,
904 (ids
[0]->xid
.type
==ID_TYPE_UID
)?uidNumber
:gidNumber
,
905 (unsigned long)ids
[0]->xid
.id
);
906 CHECK_ALLOC_DONE(filter
);
907 DEBUG(10, ("Filter: [%s]\n", filter
));
909 /* multiple mappings */
917 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY
);
918 CHECK_ALLOC_DONE(filter
);
921 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
922 filter
= talloc_asprintf_append(filter
, "(%s=%lu)",
923 (ids
[idx
]->xid
.type
==ID_TYPE_UID
)?uidNumber
:gidNumber
,
924 (unsigned long)ids
[idx
]->xid
.id
);
925 CHECK_ALLOC_DONE(filter
);
927 filter
= talloc_asprintf_append(filter
, "))");
928 CHECK_ALLOC_DONE(filter
);
929 DEBUG(10, ("Filter: [%s]\n", filter
));
935 rc
= smbldap_search(ctx
->smbldap_state
, ctx
->suffix
, LDAP_SCOPE_SUBTREE
,
936 filter
, attr_list
, 0, &result
);
938 if (rc
!= LDAP_SUCCESS
) {
939 DEBUG(3,("Failure looking up ids (%s)\n", ldap_err2string(rc
)));
940 ret
= NT_STATUS_UNSUCCESSFUL
;
944 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
947 DEBUG(10, ("NO SIDs found\n"));
950 for (i
= 0; i
< count
; i
++) {
951 LDAPMessage
*entry
= NULL
;
958 if (i
== 0) { /* first entry */
959 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
, result
);
960 } else { /* following ones */
961 entry
= ldap_next_entry(ctx
->smbldap_state
->ldap_struct
, entry
);
964 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
968 /* first check if the SID is present */
969 sidstr
= smbldap_talloc_single_attribute(
970 ctx
->smbldap_state
->ldap_struct
,
971 entry
, LDAP_ATTRIBUTE_SID
, memctx
);
972 if ( ! sidstr
) { /* no sid, skip entry */
973 DEBUG(2, ("WARNING SID not found on entry\n"));
977 /* now try to see if it is a uid, if not try with a gid
978 * (gid is more common, but in case both uidNumber and
979 * gidNumber are returned the SID is mapped to the uid not the gid) */
981 tmp
= smbldap_talloc_single_attribute(
982 ctx
->smbldap_state
->ldap_struct
,
983 entry
, uidNumber
, memctx
);
986 tmp
= smbldap_talloc_single_attribute(
987 ctx
->smbldap_state
->ldap_struct
,
988 entry
, gidNumber
, memctx
);
990 if ( ! tmp
) { /* wow very strange entry, how did it match ? */
991 DEBUG(5, ("Unprobable match on (%s), no uidNumber, nor gidNumber returned\n", sidstr
));
996 id
= strtoul(tmp
, NULL
, 10);
998 (ctx
->filter_low_id
&& (id
< ctx
->filter_low_id
)) ||
999 (ctx
->filter_high_id
&& (id
> ctx
->filter_high_id
))) {
1000 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
1001 id
, ctx
->filter_low_id
, ctx
->filter_high_id
));
1002 TALLOC_FREE(sidstr
);
1008 map
= find_map_by_id(&ids
[bidx
], type
, id
);
1010 DEBUG(2, ("WARNING: couldn't match sid (%s) with requested ids\n", sidstr
));
1011 TALLOC_FREE(sidstr
);
1015 if ( ! string_to_sid(map
->sid
, sidstr
)) {
1016 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1017 TALLOC_FREE(sidstr
);
1020 TALLOC_FREE(sidstr
);
1023 map
->status
= ID_MAPPED
;
1025 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map
->sid
), (unsigned long)map
->xid
.id
, map
->xid
.type
));
1028 /* free the ldap results */
1030 ldap_msgfree(result
);
1034 if (multi
&& ids
[idx
]) { /* still some values to map */
1040 /* mark all unknwon/expired ones as unmapped */
1041 for (i
= 0; ids
[i
]; i
++) {
1042 if (ids
[i
]->status
!= ID_MAPPED
)
1043 ids
[i
]->status
= ID_UNMAPPED
;
1047 talloc_free(memctx
);
1051 /**********************************
1052 lookup a set of sids.
1053 **********************************/
1055 /* this function searches up to IDMAP_LDAP_MAX_IDS entries in maps for a match */
1056 static struct id_map
*find_map_by_sid(struct id_map
**maps
, DOM_SID
*sid
)
1060 for (i
= 0; i
< IDMAP_LDAP_MAX_IDS
; i
++) {
1061 if (maps
[i
] == NULL
) { /* end of the run */
1064 if (sid_equal(maps
[i
]->sid
, sid
)) {
1072 static NTSTATUS
idmap_ldap_sids_to_unixids(struct idmap_domain
*dom
, struct id_map
**ids
)
1074 LDAPMessage
*entry
= NULL
;
1077 struct idmap_ldap_context
*ctx
;
1078 LDAPMessage
*result
= NULL
;
1079 const char *uidNumber
;
1080 const char *gidNumber
;
1081 const char **attr_list
;
1082 char *filter
= NULL
;
1090 /* Only do query if we are online */
1091 if (idmap_is_offline()) {
1092 return NT_STATUS_FILE_IS_OFFLINE
;
1095 /* Initilization my have been deferred because we were offline */
1096 if ( ! dom
->initialized
) {
1097 ret
= idmap_ldap_db_init(dom
);
1098 if ( ! NT_STATUS_IS_OK(ret
)) {
1103 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
1105 memctx
= talloc_new(ctx
);
1107 DEBUG(0, ("Out of memory!\n"));
1108 return NT_STATUS_NO_MEMORY
;
1111 uidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
1112 gidNumber
= get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
1114 attr_list
= get_attr_list(ctx
, sidmap_attr_list
);
1117 /* if we are requested just one mapping use the simple filter */
1119 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(%s=%s))",
1120 LDAP_OBJ_IDMAP_ENTRY
,
1122 sid_string_static(ids
[0]->sid
));
1123 CHECK_ALLOC_DONE(filter
);
1124 DEBUG(10, ("Filter: [%s]\n", filter
));
1126 /* multiple mappings */
1133 TALLOC_FREE(filter
);
1134 filter
= talloc_asprintf(memctx
, "(&(objectClass=%s)(|", LDAP_OBJ_IDMAP_ENTRY
);
1135 CHECK_ALLOC_DONE(filter
);
1138 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
1139 filter
= talloc_asprintf_append(filter
, "(%s=%s)",
1141 sid_string_static(ids
[idx
]->sid
));
1142 CHECK_ALLOC_DONE(filter
);
1144 filter
= talloc_asprintf_append(filter
, "))");
1145 CHECK_ALLOC_DONE(filter
);
1146 DEBUG(10, ("Filter: [%s]", filter
));
1152 rc
= smbldap_search(ctx
->smbldap_state
, ctx
->suffix
, LDAP_SCOPE_SUBTREE
,
1153 filter
, attr_list
, 0, &result
);
1155 if (rc
!= LDAP_SUCCESS
) {
1156 DEBUG(3,("Failure looking up sids (%s)\n", ldap_err2string(rc
)));
1157 ret
= NT_STATUS_UNSUCCESSFUL
;
1161 count
= ldap_count_entries(ctx
->smbldap_state
->ldap_struct
, result
);
1164 DEBUG(10, ("NO SIDs found\n"));
1167 for (i
= 0; i
< count
; i
++) {
1168 char *sidstr
= NULL
;
1175 if (i
== 0) { /* first entry */
1176 entry
= ldap_first_entry(ctx
->smbldap_state
->ldap_struct
, result
);
1177 } else { /* following ones */
1178 entry
= ldap_next_entry(ctx
->smbldap_state
->ldap_struct
, entry
);
1181 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
1185 /* first check if the SID is present */
1186 sidstr
= smbldap_talloc_single_attribute(
1187 ctx
->smbldap_state
->ldap_struct
,
1188 entry
, LDAP_ATTRIBUTE_SID
, memctx
);
1189 if ( ! sidstr
) { /* no sid ??, skip entry */
1190 DEBUG(2, ("WARNING SID not found on entry\n"));
1194 if ( ! string_to_sid(&sid
, sidstr
)) {
1195 DEBUG(2, ("ERROR: Invalid SID on entry\n"));
1196 TALLOC_FREE(sidstr
);
1200 map
= find_map_by_sid(&ids
[bidx
], &sid
);
1202 DEBUG(2, ("WARNING: couldn't find entry sid (%s) in ids", sidstr
));
1203 TALLOC_FREE(sidstr
);
1207 TALLOC_FREE(sidstr
);
1209 /* now try to see if it is a uid, if not try with a gid
1210 * (gid is more common, but in case both uidNumber and
1211 * gidNumber are returned the SID is mapped to the uid not the gid) */
1213 tmp
= smbldap_talloc_single_attribute(
1214 ctx
->smbldap_state
->ldap_struct
,
1215 entry
, uidNumber
, memctx
);
1218 tmp
= smbldap_talloc_single_attribute(
1219 ctx
->smbldap_state
->ldap_struct
,
1220 entry
, gidNumber
, memctx
);
1222 if ( ! tmp
) { /* no ids ?? */
1223 DEBUG(5, ("no uidNumber, nor gidNumber attributes found\n"));
1227 id
= strtoul(tmp
, NULL
, 10);
1229 (ctx
->filter_low_id
&& (id
< ctx
->filter_low_id
)) ||
1230 (ctx
->filter_high_id
&& (id
> ctx
->filter_high_id
))) {
1231 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
1232 id
, ctx
->filter_low_id
, ctx
->filter_high_id
));
1239 map
->xid
.type
= type
;
1241 map
->status
= ID_MAPPED
;
1243 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_static(map
->sid
), (unsigned long)map
->xid
.id
, map
->xid
.type
));
1246 /* free the ldap results */
1248 ldap_msgfree(result
);
1252 if (multi
&& ids
[idx
]) { /* still some values to map */
1258 /* mark all unknwon/expired ones as unmapped */
1259 for (i
= 0; ids
[i
]; i
++) {
1260 if (ids
[i
]->status
!= ID_MAPPED
)
1261 ids
[i
]->status
= ID_UNMAPPED
;
1265 talloc_free(memctx
);
1269 /**********************************
1271 **********************************/
1273 /* TODO: change this: This function cannot be called to modify a mapping, only set a new one */
1275 static NTSTATUS
idmap_ldap_set_mapping(struct idmap_domain
*dom
, const struct id_map
*map
)
1279 struct idmap_ldap_context
*ctx
;
1280 LDAPMessage
*entry
= NULL
;
1281 LDAPMod
**mods
= NULL
;
1288 /* Only do query if we are online */
1289 if (idmap_is_offline()) {
1290 return NT_STATUS_FILE_IS_OFFLINE
;
1293 /* Initilization my have been deferred because we were offline */
1294 if ( ! dom
->initialized
) {
1295 ret
= idmap_ldap_db_init(dom
);
1296 if ( ! NT_STATUS_IS_OK(ret
)) {
1301 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
1303 switch(map
->xid
.type
) {
1305 type
= get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_UIDNUMBER
);
1309 type
= get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_GIDNUMBER
);
1313 return NT_STATUS_INVALID_PARAMETER
;
1316 memctx
= talloc_new(ctx
);
1318 DEBUG(0, ("Out of memory!\n"));
1319 return NT_STATUS_NO_MEMORY
;
1322 id_str
= talloc_asprintf(memctx
, "%lu", (unsigned long)map
->xid
.id
);
1323 CHECK_ALLOC_DONE(id_str
);
1325 sid
= talloc_strdup(memctx
, sid_string_static(map
->sid
));
1326 CHECK_ALLOC_DONE(sid
);
1328 dn
= talloc_asprintf(memctx
, "%s=%s,%s",
1329 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
),
1332 CHECK_ALLOC_DONE(dn
);
1334 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_IDMAP_ENTRY
);
1336 smbldap_make_mod(ctx
->smbldap_state
->ldap_struct
, entry
, &mods
, type
, id_str
);
1338 smbldap_make_mod(ctx
->smbldap_state
->ldap_struct
, entry
, &mods
,
1339 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
), sid
);
1342 DEBUG(2, ("ERROR: No mods?\n"));
1343 ret
= NT_STATUS_UNSUCCESSFUL
;
1347 /* TODO: remove conflicting mappings! */
1349 smbldap_set_mod(&mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_SID_ENTRY
);
1351 DEBUG(10, ("Set DN %s (%s -> %s)\n", dn
, sid
, id_str
));
1353 rc
= smbldap_add(ctx
->smbldap_state
, dn
, mods
);
1354 ldap_mods_free(mods
, True
);
1356 if (rc
!= LDAP_SUCCESS
) {
1357 char *ld_error
= NULL
;
1358 ldap_get_option(ctx
->smbldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
1359 DEBUG(0,("ldap_set_mapping_internals: Failed to add %s to %lu mapping [%s]\n",
1360 sid
, (unsigned long)map
->xid
.id
, type
));
1361 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
1362 ld_error
? ld_error
: "(NULL)", ldap_err2string (rc
)));
1364 ldap_memfree(ld_error
);
1366 ret
= NT_STATUS_UNSUCCESSFUL
;
1370 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
1371 sid
, (unsigned long)map
->xid
.id
, type
));
1376 talloc_free(memctx
);
1380 /**********************************
1381 Close the idmap ldap instance
1382 **********************************/
1384 static NTSTATUS
idmap_ldap_close(struct idmap_domain
*dom
)
1386 struct idmap_ldap_context
*ctx
;
1388 if (dom
->private_data
) {
1389 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ldap_context
);
1392 dom
->private_data
= NULL
;
1395 return NT_STATUS_OK
;
1398 static struct idmap_methods idmap_ldap_methods
= {
1400 .init
= idmap_ldap_db_init
,
1401 .unixids_to_sids
= idmap_ldap_unixids_to_sids
,
1402 .sids_to_unixids
= idmap_ldap_sids_to_unixids
,
1403 .set_mapping
= idmap_ldap_set_mapping
,
1404 .close_fn
= idmap_ldap_close
1407 static struct idmap_alloc_methods idmap_ldap_alloc_methods
= {
1409 .init
= idmap_ldap_alloc_init
,
1410 .allocate_id
= idmap_ldap_allocate_id
,
1411 .get_id_hwm
= idmap_ldap_get_hwm
,
1412 .set_id_hwm
= idmap_ldap_set_hwm
,
1413 .close_fn
= idmap_ldap_alloc_close
,
1414 /* .dump_data = TODO */
1417 NTSTATUS
idmap_alloc_ldap_init(void)
1419 return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION
, "ldap", &idmap_ldap_alloc_methods
);
1422 NTSTATUS
idmap_ldap_init(void)
1426 /* FIXME: bad hack to actually register also the alloc_ldap module without changining configure.in */
1427 ret
= idmap_alloc_ldap_init();
1428 if (! NT_STATUS_IS_OK(ret
)) {
1431 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
, "ldap", &idmap_ldap_methods
);