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 Allocate a new uid or gid
118 *****************************************************************************/
120 static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
122 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
123 int rc = LDAP_SERVER_DOWN;
125 LDAPMessage *result = NULL;
126 LDAPMessage *entry = NULL;
127 pstring id_str, new_id_str;
128 LDAPMod **mods = NULL;
131 const char **attr_list;
137 type = (id_type & ID_USERID) ?
138 get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) :
139 get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
141 pstr_sprintf(filter, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
143 attr_list = get_attr_list( NULL, idpool_attr_list );
145 rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(),
146 LDAP_SCOPE_SUBTREE, filter,
147 attr_list, 0, &result);
148 TALLOC_FREE( attr_list );
150 if (rc != LDAP_SUCCESS) {
151 DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL));
155 count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
157 DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL));
161 dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
165 entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
167 if (!smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str)) {
168 DEBUG(0,("ldap_allocate_id: %s attribute not found\n",
173 /* this must succeed or else we wouldn't have initialized */
175 lp_idmap_uid( &luid, &huid);
176 lp_idmap_gid( &lgid, &hgid);
178 /* make sure we still have room to grow */
180 if (id_type & ID_USERID) {
181 id->uid = strtoul(id_str, NULL, 10);
182 if (id->uid > huid ) {
183 DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n",
184 (unsigned long)huid));
189 id->gid = strtoul(id_str, NULL, 10);
190 if (id->gid > hgid ) {
191 DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n",
192 (unsigned long)hgid));
197 pstr_sprintf(new_id_str, "%lu",
198 ((id_type & ID_USERID) ? (unsigned long)id->uid :
199 (unsigned long)id->gid) + 1);
201 smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str );
202 smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str );
205 DEBUG(0,("ldap_allocate_id: smbldap_set_mod() failed.\n"));
209 rc = smbldap_modify(ldap_state.smbldap_state, dn, mods);
211 ldap_mods_free( mods, True );
212 if (rc != LDAP_SUCCESS) {
213 DEBUG(1,("ldap_allocate_id: Failed to allocate new %s. ldap_modify() failed.\n",
222 ldap_msgfree(result);
227 /*****************************************************************************
229 *****************************************************************************/
231 static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
233 LDAPMessage *result = NULL;
234 LDAPMessage *entry = NULL;
241 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
242 const char **attr_list;
244 if ( id_type & ID_USERID )
245 type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
247 type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
249 pstrcpy( suffix, lp_ldap_idmap_suffix() );
250 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
251 LDAP_OBJ_IDMAP_ENTRY, type,
252 ((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid));
254 attr_list = get_attr_list( NULL, sidmap_attr_list );
255 rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
256 filter, attr_list, 0, &result);
258 if (rc != LDAP_SUCCESS) {
259 DEBUG(3,("ldap_get_isd_from_id: Failure looking up entry (%s)\n",
260 ldap_err2string(rc) ));
264 count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
267 DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %lu\n",
268 type, ((id_type & ID_USERID) ? (unsigned long)id.uid :
269 (unsigned long)id.gid)));
273 entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
275 if ( !smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, sid_str) )
278 if (!string_to_sid(sid, sid_str))
283 TALLOC_FREE( attr_list );
286 ldap_msgfree(result);
291 /***********************************************************************
293 ***********************************************************************/
295 static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
297 LDAPMessage *result = NULL;
298 LDAPMessage *entry = NULL;
306 const char **attr_list;
308 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
310 sid_to_string(sid_str, sid);
312 DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_str,
313 (*id_type & ID_GROUPID ? "group" : "user") ));
315 suffix = lp_ldap_idmap_suffix();
316 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
317 LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str);
319 if ( *id_type & ID_GROUPID )
320 type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER );
322 type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER );
324 /* do the search and check for errors */
326 attr_list = get_attr_list( NULL, sidmap_attr_list );
327 rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
328 filter, attr_list, 0, &result);
330 if (rc != LDAP_SUCCESS) {
331 DEBUG(3,("ldap_get_id_from_sid: Failure looking up idmap entry (%s)\n",
332 ldap_err2string(rc) ));
336 /* check for the number of entries returned */
338 count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
341 DEBUG(0, ("ldap_get_id_from_sid: (2nd) search %s returned [%d] entries!\n",
346 /* try to allocate a new id if we still haven't found one */
351 if (*id_type & ID_QUERY_ONLY) {
352 DEBUG(5,("ldap_get_id_from_sid: No matching entry found and QUERY_ONLY flag set\n"));
356 DEBUG(8,("ldap_get_id_from_sid: Allocating new id\n"));
358 for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) {
359 ret = ldap_allocate_id(id, *id_type);
360 if ( NT_STATUS_IS_OK(ret) )
364 if ( !NT_STATUS_IS_OK(ret) ) {
365 DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n"));
369 DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n",
370 (*id_type & ID_GROUPID ? 'g' : 'u'), (uint32)id->uid ));
372 ret = ldap_set_mapping(sid, *id, *id_type);
379 DEBUG(10,("ldap_get_id_from_sid: success\n"));
381 entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
383 dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
387 DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type));
389 if ( smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) {
390 if ( (*id_type & ID_USERID) )
391 id->uid = strtoul(id_str, NULL, 10);
393 id->gid = strtoul(id_str, NULL, 10);
400 TALLOC_FREE( attr_list );
402 ldap_msgfree(result);
408 /**********************************************************************
409 Verify the sambaUnixIdPool entry in the directiry.
410 **********************************************************************/
412 static NTSTATUS verify_idpool( void )
416 const char **attr_list;
417 LDAPMessage *result = NULL;
418 LDAPMod **mods = NULL;
421 fstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_IDPOOL );
423 attr_list = get_attr_list( NULL, idpool_attr_list );
424 rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(),
425 LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result);
426 TALLOC_FREE( attr_list );
428 if (rc != LDAP_SUCCESS)
429 return NT_STATUS_UNSUCCESSFUL;
431 count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
433 ldap_msgfree(result);
436 DEBUG(0,("ldap_idmap_init: multiple entries returned from %s (base == %s)\n",
437 filter, lp_ldap_idmap_suffix() ));
438 return NT_STATUS_UNSUCCESSFUL;
440 else if (count == 0) {
443 fstring uid_str, gid_str;
445 if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) {
446 DEBUG(0,("ldap_idmap_init: idmap uid/gid parameters not specified\n"));
447 return NT_STATUS_UNSUCCESSFUL;
450 fstr_sprintf( uid_str, "%lu", (unsigned long)luid );
451 fstr_sprintf( gid_str, "%lu", (unsigned long)lgid );
453 smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDPOOL );
454 smbldap_set_mod( &mods, LDAP_MOD_ADD,
455 get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER), uid_str );
456 smbldap_set_mod( &mods, LDAP_MOD_ADD,
457 get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER), gid_str );
459 rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods);
460 ldap_mods_free( mods, True );
462 return NT_STATUS_UNSUCCESSFUL;
466 return ( rc==LDAP_SUCCESS ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
469 /*****************************************************************************
470 Initialise idmap database.
471 *****************************************************************************/
473 static NTSTATUS ldap_idmap_init( char *params )
477 ldap_state.mem_ctx = talloc_init("idmap_ldap");
478 if (!ldap_state.mem_ctx) {
479 return NT_STATUS_NO_MEMORY;
482 /* assume location is the only parameter */
483 if (!NT_STATUS_IS_OK(nt_status =
484 smbldap_init(ldap_state.mem_ctx, params,
485 &ldap_state.smbldap_state))) {
486 talloc_destroy(ldap_state.mem_ctx);
490 /* see if the idmap suffix and sub entries exists */
492 nt_status = verify_idpool();
493 if ( !NT_STATUS_IS_OK(nt_status) )
499 /*****************************************************************************
501 *****************************************************************************/
503 static NTSTATUS ldap_idmap_close(void)
506 smbldap_free_struct(&(ldap_state).smbldap_state);
507 talloc_destroy(ldap_state.mem_ctx);
509 DEBUG(5,("The connection to the LDAP server was closed\n"));
510 /* maybe free the results here --metze */
516 /* This function doesn't make as much sense in an LDAP world since the calling
517 node doesn't really control the ID ranges */
518 static void ldap_idmap_status(void)
520 DEBUG(0, ("LDAP IDMAP Status not available\n"));
523 static struct idmap_methods ldap_methods = {
526 ldap_get_sid_from_id,
527 ldap_get_id_from_sid,
534 NTSTATUS idmap_ldap_init(void)
536 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", &ldap_methods);