2 Unix SMB/CIFS implementation.
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8 Copyright (C) Simo Sorce 2003
9 Copyright (C) Gerald Carter 2003
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
37 struct ldap_idmap_state
{
38 struct smbldap_state
*smbldap_state
;
42 static struct ldap_idmap_state ldap_state
;
44 /* number tries while allocating new id */
45 #define LDAP_MAX_ALLOC_ID 128
48 /***********************************************************************
49 This function cannot be called to modify a mapping, only set a new one
50 ***********************************************************************/
52 static NTSTATUS
ldap_set_mapping(const DOM_SID
*sid
, unid_t id
, int id_type
)
57 LDAPMod
**mods
= NULL
;
61 LDAPMessage
*entry
= NULL
;
63 sid_to_string( sid_string
, sid
);
65 ldap_op
= LDAP_MOD_ADD
;
66 pstr_sprintf(dn
, "%s=%s,%s", get_attr_key2string( sidmap_attr_list
, LDAP_ATTR_SID
),
67 sid_string
, lp_ldap_idmap_suffix());
69 if ( id_type
& ID_USERID
)
70 fstrcpy( type
, get_attr_key2string( sidmap_attr_list
, LDAP_ATTR_UIDNUMBER
) );
72 fstrcpy( type
, get_attr_key2string( sidmap_attr_list
, LDAP_ATTR_GIDNUMBER
) );
74 pstr_sprintf(id_str
, "%lu", ((id_type
& ID_USERID
) ? (unsigned long)id
.uid
:
75 (unsigned long)id
.gid
));
77 smbldap_set_mod( &mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_IDMAP_ENTRY
);
79 smbldap_make_mod( ldap_state
.smbldap_state
->ldap_struct
,
80 entry
, &mods
, type
, id_str
);
82 smbldap_make_mod( ldap_state
.smbldap_state
->ldap_struct
,
84 get_attr_key2string(sidmap_attr_list
, LDAP_ATTR_SID
),
87 /* There may well be nothing at all to do */
90 smbldap_set_mod( &mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_SID_ENTRY
);
91 rc
= smbldap_add(ldap_state
.smbldap_state
, dn
, mods
);
92 ldap_mods_free( mods
, True
);
97 if (rc
!= LDAP_SUCCESS
) {
98 char *ld_error
= NULL
;
99 ldap_get_option(ldap_state
.smbldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
,
101 DEBUG(0,("ldap_set_mapping_internals: Failed to %s mapping from %s to %lu [%s]\n",
102 (ldap_op
== LDAP_MOD_ADD
) ? "add" : "replace",
103 sid_string
, (unsigned long)((id_type
& ID_USERID
) ? id
.uid
: id
.gid
), type
));
104 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
105 ld_error
? ld_error
: "(NULL)", ldap_err2string (rc
)));
106 return NT_STATUS_UNSUCCESSFUL
;
109 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n",
110 sid_string
, ((id_type
& ID_USERID
) ? (unsigned long)id
.uid
:
111 (unsigned long)id
.gid
), type
));
116 /**********************************************************************
117 Even if the sambaDomain attribute in LDAP tells us that this RID is
118 safe to use, always check before use.
119 *********************************************************************/
121 static BOOL
sid_in_use(struct ldap_idmap_state
*state
,
122 const DOM_SID
*sid
, int *error
)
126 LDAPMessage
*result
= NULL
;
128 const char *sid_attr
[] = {LDAP_ATTRIBUTE_SID
, NULL
};
130 slprintf(filter
, sizeof(filter
)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID
, sid_to_string(sid_string
, sid
));
132 rc
= smbldap_search_suffix(state
->smbldap_state
,
133 filter
, sid_attr
, &result
);
135 if (rc
!= LDAP_SUCCESS
) {
136 char *ld_error
= NULL
;
137 ldap_get_option(state
->smbldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
138 DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
139 sid_string
, ld_error
));
146 if ((ldap_count_entries(state
->smbldap_state
->ldap_struct
, result
)) > 0) {
147 DEBUG(3, ("Sid %s already in use - trying next RID\n",
149 ldap_msgfree(result
);
153 ldap_msgfree(result
);
155 /* good, sid is not in use */
159 /**********************************************************************
160 Set the new nextRid attribute, and return one we can use.
162 This also checks that this RID is actually free - in case the admin
163 manually stole it :-).
164 *********************************************************************/
166 static NTSTATUS
ldap_next_rid(struct ldap_idmap_state
*state
, uint32
*rid
,
169 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
170 LDAPMessage
*domain_result
= NULL
;
171 LDAPMessage
*entry
= NULL
;
173 LDAPMod
**mods
= NULL
;
174 fstring old_rid_string
;
175 fstring next_rid_string
;
176 fstring algorithmic_rid_base_string
;
180 char *ld_error
= NULL
;
182 while (attempts
< 10) {
183 if (!NT_STATUS_IS_OK(ret
= smbldap_search_domain_info(state
->smbldap_state
,
184 &domain_result
, get_global_sam_name(), True
))) {
188 entry
= ldap_first_entry(state
->smbldap_state
->ldap_struct
, domain_result
);
190 DEBUG(0, ("Could not get domain info entry\n"));
191 ldap_msgfree(domain_result
);
195 if ((dn
= smbldap_get_dn(state
->smbldap_state
->ldap_struct
, entry
)) == NULL
) {
196 DEBUG(0, ("Could not get domain info DN\n"));
197 ldap_msgfree(domain_result
);
201 /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and
202 algorithmic_rid_base. The other two are to avoid stomping on the
203 different sets of algorithmic RIDs */
205 if (smbldap_get_single_pstring(state
->smbldap_state
->ldap_struct
, entry
,
206 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_ALGORITHMIC_RID_BASE
),
207 algorithmic_rid_base_string
)) {
209 alg_rid_base
= (uint32
)atol(algorithmic_rid_base_string
);
211 alg_rid_base
= algorithmic_rid_base();
212 /* Try to make the modification atomically by enforcing the
213 old value in the delete mod. */
214 slprintf(algorithmic_rid_base_string
, sizeof(algorithmic_rid_base_string
)-1, "%d", alg_rid_base
);
215 smbldap_make_mod(state
->smbldap_state
->ldap_struct
, entry
, &mods
,
216 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_ALGORITHMIC_RID_BASE
),
217 algorithmic_rid_base_string
);
222 if (alg_rid_base
> BASE_RID
) {
223 /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we
224 can allocate to new users */
225 if (smbldap_get_single_pstring(state
->smbldap_state
->ldap_struct
, entry
,
226 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_RID
),
228 *rid
= (uint32
)atol(old_rid_string
);
234 if (next_rid
>= alg_rid_base
) {
235 ldap_msgfree(domain_result
);
236 return NT_STATUS_UNSUCCESSFUL
;
239 slprintf(next_rid_string
, sizeof(next_rid_string
)-1, "%d", next_rid
);
241 /* Try to make the modification atomically by enforcing the
242 old value in the delete mod. */
243 smbldap_make_mod(state
->smbldap_state
->ldap_struct
, entry
, &mods
,
244 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_RID
),
248 if (!next_rid
) { /* not got one already */
251 if (smbldap_get_single_pstring(state
->smbldap_state
->ldap_struct
, entry
,
252 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_USERRID
),
254 *rid
= (uint32
)atol(old_rid_string
);
258 if (smbldap_get_single_pstring(state
->smbldap_state
->ldap_struct
, entry
,
259 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_GROUPRID
),
261 *rid
= (uint32
)atol(old_rid_string
);
266 /* This is the core of the whole routine. If we had
267 scheme-style closures, there would be a *lot* less code
270 next_rid
= *rid
+RID_MULTIPLIER
;
271 slprintf(next_rid_string
, sizeof(next_rid_string
)-1, "%d", next_rid
);
275 /* Try to make the modification atomically by enforcing the
276 old value in the delete mod. */
277 smbldap_make_mod(state
->smbldap_state
->ldap_struct
, entry
, &mods
,
278 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_USERRID
),
283 /* Try to make the modification atomically by enforcing the
284 old value in the delete mod. */
285 smbldap_make_mod(state
->smbldap_state
->ldap_struct
, entry
, &mods
,
286 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_NEXT_GROUPRID
),
292 if ((smbldap_modify(state
->smbldap_state
, dn
, mods
)) == LDAP_SUCCESS
) {
295 pstring domain_sid_string
;
298 if (!smbldap_get_single_pstring(state
->smbldap_state
->ldap_struct
, domain_result
,
299 get_attr_key2string(dominfo_attr_list
, LDAP_ATTR_DOM_SID
),
300 domain_sid_string
)) {
301 ldap_mods_free(mods
, True
);
303 ldap_msgfree(domain_result
);
307 if (!string_to_sid(&dom_sid
, domain_sid_string
)) {
308 ldap_mods_free(mods
, True
);
310 ldap_msgfree(domain_result
);
314 ldap_mods_free(mods
, True
);
317 ldap_msgfree(domain_result
);
319 sid_copy(&sid
, &dom_sid
);
320 sid_append_rid(&sid
, *rid
);
322 /* check RID is not in use */
323 if (sid_in_use(state
, &sid
, &error
)) {
334 ldap_get_option(state
->smbldap_state
->ldap_struct
, LDAP_OPT_ERROR_STRING
, &ld_error
);
335 DEBUG(2, ("Failed to modify rid: %s\n", ld_error
? ld_error
: "(NULL"));
338 ldap_mods_free(mods
, True
);
343 ldap_msgfree(domain_result
);
344 domain_result
= NULL
;
347 /* Sleep for a random timeout */
348 unsigned sleeptime
= (sys_random()*sys_getpid()*attempts
);
352 smb_msleep(sleeptime
);
356 DEBUG(0, ("Failed to set new RID\n"));
361 /*****************************************************************************
363 *****************************************************************************/
365 static NTSTATUS
ldap_allocate_rid(uint32
*rid
, int rid_type
)
367 return ldap_next_rid( &ldap_state
, rid
, rid_type
);
370 /*****************************************************************************
371 Allocate a new uid or gid
372 *****************************************************************************/
374 static NTSTATUS
ldap_allocate_id(unid_t
*id
, int id_type
)
376 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
377 int rc
= LDAP_SERVER_DOWN
;
379 LDAPMessage
*result
= NULL
;
380 LDAPMessage
*entry
= NULL
;
381 pstring id_str
, new_id_str
;
382 LDAPMod
**mods
= NULL
;
385 const char **attr_list
;
391 type
= (id_type
& ID_USERID
) ?
392 get_attr_key2string( idpool_attr_list
, LDAP_ATTR_UIDNUMBER
) :
393 get_attr_key2string( idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
395 pstr_sprintf(filter
, "(objectClass=%s)", LDAP_OBJ_IDPOOL
);
397 attr_list
= get_attr_list( idpool_attr_list
);
399 rc
= smbldap_search(ldap_state
.smbldap_state
, lp_ldap_idmap_suffix(),
400 LDAP_SCOPE_SUBTREE
, filter
,
401 attr_list
, 0, &result
);
402 free_attr_list( attr_list
);
404 if (rc
!= LDAP_SUCCESS
) {
405 DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL
));
409 count
= ldap_count_entries(ldap_state
.smbldap_state
->ldap_struct
, result
);
411 DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL
));
415 dn
= smbldap_get_dn(ldap_state
.smbldap_state
->ldap_struct
, result
);
419 entry
= ldap_first_entry(ldap_state
.smbldap_state
->ldap_struct
, result
);
421 if (!smbldap_get_single_pstring(ldap_state
.smbldap_state
->ldap_struct
, entry
, type
, id_str
)) {
422 DEBUG(0,("ldap_allocate_id: %s attribute not found\n",
427 /* this must succeed or else we wouldn't have initialized */
429 lp_idmap_uid( &luid
, &huid
);
430 lp_idmap_gid( &lgid
, &hgid
);
432 /* make sure we still have room to grow */
434 if (id_type
& ID_USERID
) {
435 id
->uid
= strtoul(id_str
, NULL
, 10);
436 if (id
->uid
> huid
) {
437 DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n",
438 (unsigned long)huid
));
443 id
->gid
= strtoul(id_str
, NULL
, 10);
444 if (id
->gid
> hgid
) {
445 DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n",
446 (unsigned long)hgid
));
451 pstr_sprintf(new_id_str
, "%lu",
452 ((id_type
& ID_USERID
) ? (unsigned long)id
->uid
:
453 (unsigned long)id
->gid
) + 1);
455 smbldap_set_mod( &mods
, LDAP_MOD_DELETE
, type
, id_str
);
456 smbldap_set_mod( &mods
, LDAP_MOD_ADD
, type
, new_id_str
);
459 DEBUG(0,("ldap_allocate_id: smbldap_set_mod() failed.\n"));
463 rc
= smbldap_modify(ldap_state
.smbldap_state
, dn
, mods
);
465 ldap_mods_free( mods
, True
);
466 if (rc
!= LDAP_SUCCESS
) {
467 DEBUG(1,("ldap_allocate_id: Failed to allocate new %s. ldap_modify() failed.\n",
476 ldap_msgfree(result
);
481 /*****************************************************************************
483 *****************************************************************************/
485 static NTSTATUS
ldap_get_sid_from_id(DOM_SID
*sid
, unid_t id
, int id_type
)
487 LDAPMessage
*result
= NULL
;
488 LDAPMessage
*entry
= NULL
;
495 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
496 const char **attr_list
;
498 if ( id_type
& ID_USERID
)
499 type
= get_attr_key2string( idpool_attr_list
, LDAP_ATTR_UIDNUMBER
);
501 type
= get_attr_key2string( idpool_attr_list
, LDAP_ATTR_GIDNUMBER
);
503 pstrcpy( suffix
, lp_ldap_idmap_suffix() );
504 pstr_sprintf(filter
, "(&(objectClass=%s)(%s=%lu))",
505 LDAP_OBJ_IDMAP_ENTRY
, type
,
506 ((id_type
& ID_USERID
) ? (unsigned long)id
.uid
: (unsigned long)id
.gid
));
508 attr_list
= get_attr_list( sidmap_attr_list
);
509 rc
= smbldap_search(ldap_state
.smbldap_state
, suffix
, LDAP_SCOPE_SUBTREE
,
510 filter
, attr_list
, 0, &result
);
512 if (rc
!= LDAP_SUCCESS
) {
513 DEBUG(3,("ldap_get_isd_from_id: Failure looking up entry (%s)\n",
514 ldap_err2string(rc
) ));
518 count
= ldap_count_entries(ldap_state
.smbldap_state
->ldap_struct
, result
);
521 DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %lu\n",
522 type
, ((id_type
& ID_USERID
) ? (unsigned long)id
.uid
:
523 (unsigned long)id
.gid
)));
527 entry
= ldap_first_entry(ldap_state
.smbldap_state
->ldap_struct
, result
);
529 if ( !smbldap_get_single_pstring(ldap_state
.smbldap_state
->ldap_struct
, entry
, LDAP_ATTRIBUTE_SID
, sid_str
) )
532 if (!string_to_sid(sid
, sid_str
))
537 free_attr_list( attr_list
);
540 ldap_msgfree(result
);
545 /***********************************************************************
547 ***********************************************************************/
549 static NTSTATUS
ldap_get_id_from_sid(unid_t
*id
, int *id_type
, const DOM_SID
*sid
)
551 LDAPMessage
*result
= NULL
;
552 LDAPMessage
*entry
= NULL
;
560 const char **attr_list
;
562 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
564 sid_to_string(sid_str
, sid
);
566 DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_str
,
567 (*id_type
& ID_GROUPID
? "group" : "user") ));
569 suffix
= lp_ldap_idmap_suffix();
570 pstr_sprintf(filter
, "(&(objectClass=%s)(%s=%s))",
571 LDAP_OBJ_IDMAP_ENTRY
, LDAP_ATTRIBUTE_SID
, sid_str
);
573 if ( *id_type
& ID_GROUPID
)
574 type
= get_attr_key2string( sidmap_attr_list
, LDAP_ATTR_GIDNUMBER
);
576 type
= get_attr_key2string( sidmap_attr_list
, LDAP_ATTR_UIDNUMBER
);
578 /* do the search and check for errors */
580 attr_list
= get_attr_list( sidmap_attr_list
);
581 rc
= smbldap_search(ldap_state
.smbldap_state
, suffix
, LDAP_SCOPE_SUBTREE
,
582 filter
, attr_list
, 0, &result
);
584 if (rc
!= LDAP_SUCCESS
) {
585 DEBUG(3,("ldap_get_id_from_sid: Failure looking up idmap entry (%s)\n",
586 ldap_err2string(rc
) ));
590 /* check for the number of entries returned */
592 count
= ldap_count_entries(ldap_state
.smbldap_state
->ldap_struct
, result
);
595 DEBUG(0, ("ldap_get_id_from_sid: (2nd) search %s returned [%d] entries!\n",
600 /* try to allocate a new id if we still haven't found one */
605 if (*id_type
& ID_QUERY_ONLY
) {
606 DEBUG(5,("ldap_get_id_from_sid: No matching entry found and QUERY_ONLY flag set\n"));
610 DEBUG(8,("ldap_get_id_from_sid: Allocating new id\n"));
612 for (i
= 0; i
< LDAP_MAX_ALLOC_ID
; i
++) {
613 ret
= ldap_allocate_id(id
, *id_type
);
614 if ( NT_STATUS_IS_OK(ret
) )
618 if ( !NT_STATUS_IS_OK(ret
) ) {
619 DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n"));
623 DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n",
624 (*id_type
& ID_GROUPID
? 'g' : 'u'), (uint32
)id
->uid
));
626 ret
= ldap_set_mapping(sid
, *id
, *id_type
);
633 DEBUG(10,("ldap_get_id_from_sid: success\n"));
635 entry
= ldap_first_entry(ldap_state
.smbldap_state
->ldap_struct
, result
);
637 dn
= smbldap_get_dn(ldap_state
.smbldap_state
->ldap_struct
, result
);
641 DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn
, type
));
643 if ( smbldap_get_single_pstring(ldap_state
.smbldap_state
->ldap_struct
, entry
, type
, id_str
) ) {
644 if ( (*id_type
& ID_USERID
) )
645 id
->uid
= strtoul(id_str
, NULL
, 10);
647 id
->gid
= strtoul(id_str
, NULL
, 10);
654 free_attr_list( attr_list
);
656 ldap_msgfree(result
);
662 /**********************************************************************
663 Verify the sambaUnixIdPool entry in the directiry.
664 **********************************************************************/
666 static NTSTATUS
verify_idpool( void )
670 const char **attr_list
;
671 LDAPMessage
*result
= NULL
;
672 LDAPMod
**mods
= NULL
;
675 fstr_sprintf( filter
, "(objectclass=%s)", LDAP_OBJ_IDPOOL
);
677 attr_list
= get_attr_list( idpool_attr_list
);
678 rc
= smbldap_search(ldap_state
.smbldap_state
, lp_ldap_idmap_suffix(),
679 LDAP_SCOPE_SUBTREE
, filter
, attr_list
, 0, &result
);
680 free_attr_list ( attr_list
);
682 if (rc
!= LDAP_SUCCESS
)
683 return NT_STATUS_UNSUCCESSFUL
;
685 count
= ldap_count_entries(ldap_state
.smbldap_state
->ldap_struct
, result
);
687 ldap_msgfree(result
);
690 DEBUG(0,("ldap_idmap_init: multiple entries returned from %s (base == %s)\n",
691 filter
, lp_ldap_idmap_suffix() ));
692 return NT_STATUS_UNSUCCESSFUL
;
694 else if (count
== 0) {
697 fstring uid_str
, gid_str
;
699 if ( !lp_idmap_uid(&luid
, &huid
) || !lp_idmap_gid( &lgid
, &hgid
) ) {
700 DEBUG(0,("ldap_idmap_init: idmap uid/gid parameters not specified\n"));
701 return NT_STATUS_UNSUCCESSFUL
;
704 fstr_sprintf( uid_str
, "%lu", (unsigned long)luid
);
705 fstr_sprintf( gid_str
, "%lu", (unsigned long)lgid
);
707 smbldap_set_mod( &mods
, LDAP_MOD_ADD
, "objectClass", LDAP_OBJ_IDPOOL
);
708 smbldap_set_mod( &mods
, LDAP_MOD_ADD
,
709 get_attr_key2string(idpool_attr_list
, LDAP_ATTR_UIDNUMBER
), uid_str
);
710 smbldap_set_mod( &mods
, LDAP_MOD_ADD
,
711 get_attr_key2string(idpool_attr_list
, LDAP_ATTR_GIDNUMBER
), gid_str
);
713 rc
= smbldap_modify(ldap_state
.smbldap_state
, lp_ldap_idmap_suffix(), mods
);
714 ldap_mods_free( mods
, True
);
716 return NT_STATUS_UNSUCCESSFUL
;
720 return ( rc
==LDAP_SUCCESS
? NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
);
723 /*****************************************************************************
724 Initialise idmap database.
725 *****************************************************************************/
727 static NTSTATUS
ldap_idmap_init( char *params
)
731 ldap_state
.mem_ctx
= talloc_init("idmap_ldap");
732 if (!ldap_state
.mem_ctx
) {
733 return NT_STATUS_NO_MEMORY
;
736 /* assume location is the only parameter */
737 if (!NT_STATUS_IS_OK(nt_status
=
738 smbldap_init(ldap_state
.mem_ctx
, params
,
739 &ldap_state
.smbldap_state
))) {
740 talloc_destroy(ldap_state
.mem_ctx
);
744 /* see if the idmap suffix and sub entries exists */
746 nt_status
= verify_idpool();
747 if ( !NT_STATUS_IS_OK(nt_status
) )
753 /*****************************************************************************
755 *****************************************************************************/
757 static NTSTATUS
ldap_idmap_close(void)
760 smbldap_free_struct(&(ldap_state
).smbldap_state
);
761 talloc_destroy(ldap_state
.mem_ctx
);
763 DEBUG(5,("The connection to the LDAP server was closed\n"));
764 /* maybe free the results here --metze */
770 /* This function doesn't make as much sense in an LDAP world since the calling
771 node doesn't really control the ID ranges */
772 static void ldap_idmap_status(void)
774 DEBUG(0, ("LDAP IDMAP Status not available\n"));
777 static struct idmap_methods ldap_methods
= {
781 ldap_get_sid_from_id
,
782 ldap_get_id_from_sid
,
789 NTSTATUS
idmap_ldap_init(void)
791 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
, "ldap", &ldap_methods
);