1/* 2 Unix SMB/CIFS implementation. 3 4 idmap LDAP backend 5 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 10 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. 15 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. 20 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. 24*/ 25 26#include "includes.h" 27 28#undef DBGC_CLASS 29#define DBGC_CLASS DBGC_IDMAP 30 31 32#include <lber.h> 33#include <ldap.h> 34 35#include "smbldap.h" 36 37struct ldap_idmap_state { 38 struct smbldap_state *smbldap_state; 39 TALLOC_CTX *mem_ctx; 40}; 41 42static struct ldap_idmap_state ldap_state; 43 44/* number tries while allocating new id */ 45#define LDAP_MAX_ALLOC_ID 128 46 47 48/*********************************************************************** 49 This function cannot be called to modify a mapping, only set a new one 50***********************************************************************/ 51 52static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) 53{ 54 pstring dn; 55 pstring id_str; 56 fstring type; 57 LDAPMod **mods = NULL; 58 int rc = -1; 59 int ldap_op; 60 fstring sid_string; 61 LDAPMessage *entry = NULL; 62 63 sid_to_string( sid_string, sid ); 64 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()); 68 69 if ( id_type & ID_USERID ) 70 fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) ); 71 else 72 fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) ); 73 74 pstr_sprintf(id_str, "%d", ((id_type & ID_USERID) ? id.uid : id.gid)); 75 76 smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY ); 77 78 smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, 79 entry, &mods, type, id_str ); 80 81 smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, 82 entry, &mods, 83 get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), 84 sid_string ); 85 86 /* There may well be nothing at all to do */ 87 88 if (mods) { 89 smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SID_ENTRY ); 90 rc = smbldap_add(ldap_state.smbldap_state, dn, mods); 91 ldap_mods_free( mods, True ); 92 } else { 93 rc = LDAP_SUCCESS; 94 } 95 96 if (rc != LDAP_SUCCESS) { 97 char *ld_error = NULL; 98 ldap_get_option(ldap_state.smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, 99 &ld_error); 100 DEBUG(0,("ldap_set_mapping_internals: Failed to %s mapping from %s to %lu [%s]\n", 101 (ldap_op == LDAP_MOD_ADD) ? "add" : "replace", 102 sid_string, (unsigned long)((id_type & ID_USERID) ? id.uid : id.gid), type)); 103 DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", 104 ld_error ? ld_error : "(NULL)", ldap_err2string (rc))); 105 return NT_STATUS_UNSUCCESSFUL; 106 } 107 108 DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n", 109 sid_string, ((id_type & ID_USERID) ? (unsigned long)id.uid : 110 (unsigned long)id.gid), type)); 111 112 return NT_STATUS_OK; 113} 114 115/********************************************************************** 116 Even if the sambaDomain attribute in LDAP tells us that this RID is 117 safe to use, always check before use. 118*********************************************************************/ 119 120static BOOL sid_in_use(struct ldap_idmap_state *state, 121 const DOM_SID *sid, int *error) 122{ 123 fstring filter; 124 fstring sid_string; 125 LDAPMessage *result = NULL; 126 int rc; 127 const char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL}; 128 129 slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid)); 130 131 rc = smbldap_search_suffix(state->smbldap_state, 132 filter, sid_attr, &result); 133 134 if (rc != LDAP_SUCCESS) { 135 char *ld_error = NULL; 136 ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); 137 DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n", 138 sid_string, ld_error)); 139 SAFE_FREE(ld_error); 140 141 *error = rc; 142 return True; 143 } 144 145 if ((ldap_count_entries(state->smbldap_state->ldap_struct, result)) > 0) { 146 DEBUG(3, ("Sid %s already in use - trying next RID\n", 147 sid_string)); 148 ldap_msgfree(result); 149 return True; 150 } 151 152 ldap_msgfree(result); 153 154 /* good, sid is not in use */ 155 return False; 156} 157 158/********************************************************************** 159 Set the new nextRid attribute, and return one we can use. 160 161 This also checks that this RID is actually free - in case the admin 162 manually stole it :-). 163*********************************************************************/ 164 165static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, 166 int rid_type) 167{ 168 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; 169 LDAPMessage *domain_result = NULL; 170 LDAPMessage *entry = NULL; 171 char *dn; 172 LDAPMod **mods = NULL; 173 fstring old_rid_string; 174 fstring next_rid_string; 175 fstring algorithmic_rid_base_string; 176 uint32 next_rid; 177 uint32 alg_rid_base; 178 int attempts = 0; 179 char *ld_error = NULL; 180 181 while (attempts < 10) { 182 if (!NT_STATUS_IS_OK(ret = smbldap_search_domain_info(state->smbldap_state, 183 &domain_result, get_global_sam_name(), True))) { 184 return ret; 185 } 186 187 entry = ldap_first_entry(state->smbldap_state->ldap_struct, domain_result); 188 if (!entry) { 189 DEBUG(0, ("Could not get domain info entry\n")); 190 ldap_msgfree(domain_result); 191 return ret; 192 } 193 194 if ((dn = smbldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) { 195 DEBUG(0, ("Could not get domain info DN\n")); 196 ldap_msgfree(domain_result); 197 return ret; 198 } 199 200 /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and 201 algorithmic_rid_base. The other two are to avoid stomping on the 202 different sets of algorithmic RIDs */ 203 204 if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry, 205 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), 206 algorithmic_rid_base_string)) { 207 208 alg_rid_base = (uint32)atol(algorithmic_rid_base_string); 209 } else { 210 alg_rid_base = algorithmic_rid_base(); 211 /* Try to make the modification atomically by enforcing the 212 old value in the delete mod. */ 213 slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string)-1, "%d", alg_rid_base); 214 smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, 215 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), 216 algorithmic_rid_base_string); 217 } 218 219 next_rid = 0; 220 221 if (alg_rid_base > BASE_RID) { 222 /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we 223 can allocate to new users */ 224 if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry, 225 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), 226 old_rid_string)) { 227 *rid = (uint32)atol(old_rid_string); 228 } else { 229 *rid = BASE_RID; 230 } 231 232 next_rid = *rid+1; 233 if (next_rid >= alg_rid_base) { 234 ldap_msgfree(domain_result); 235 return NT_STATUS_UNSUCCESSFUL; 236 } 237 238 slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); 239 240 /* Try to make the modification atomically by enforcing the 241 old value in the delete mod. */ 242 smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, 243 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), 244 next_rid_string); 245 } 246 247 if (!next_rid) { /* not got one already */ 248 switch (rid_type) { 249 case USER_RID_TYPE: 250 if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry, 251 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), 252 old_rid_string)) { 253 *rid = (uint32)atol(old_rid_string); 254 } 255 break; 256 case GROUP_RID_TYPE: 257 if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry, 258 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), 259 old_rid_string)) { 260 *rid = (uint32)atol(old_rid_string); 261 } 262 break; 263 } 264 265 /* This is the core of the whole routine. If we had 266 scheme-style closures, there would be a *lot* less code 267 duplication... */ 268 269 next_rid = *rid+RID_MULTIPLIER; 270 slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); 271 272 switch (rid_type) { 273 case USER_RID_TYPE: 274 /* Try to make the modification atomically by enforcing the 275 old value in the delete mod. */ 276 smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, 277 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), 278 next_rid_string); 279 break; 280 281 case GROUP_RID_TYPE: 282 /* Try to make the modification atomically by enforcing the 283 old value in the delete mod. */ 284 smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, 285 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), 286 next_rid_string); 287 break; 288 } 289 } 290 291 if ((smbldap_modify(state->smbldap_state, dn, mods)) == LDAP_SUCCESS) { 292 DOM_SID dom_sid; 293 DOM_SID sid; 294 pstring domain_sid_string; 295 int error = 0; 296 297 if (!smbldap_get_single_pstring(state->smbldap_state->ldap_struct, domain_result, 298 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), 299 domain_sid_string)) { 300 ldap_mods_free(mods, True); 301 SAFE_FREE(dn); 302 ldap_msgfree(domain_result); 303 return ret; 304 } 305 306 if (!string_to_sid(&dom_sid, domain_sid_string)) { 307 ldap_mods_free(mods, True); 308 SAFE_FREE(dn); 309 ldap_msgfree(domain_result); 310 return ret; 311 } 312 313 ldap_mods_free(mods, True); 314 mods = NULL; 315 SAFE_FREE(dn); 316 ldap_msgfree(domain_result); 317 318 sid_copy(&sid, &dom_sid); 319 sid_append_rid(&sid, *rid); 320 321 /* check RID is not in use */ 322 if (sid_in_use(state, &sid, &error)) { 323 if (error) { 324 return ret; 325 } 326 continue; 327 } 328 329 return NT_STATUS_OK; 330 } 331 332 ld_error = NULL; 333 ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); 334 DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL")); 335 SAFE_FREE(ld_error); 336 337 ldap_mods_free(mods, True); 338 mods = NULL; 339 340 SAFE_FREE(dn); 341 342 ldap_msgfree(domain_result); 343 domain_result = NULL; 344 345 { 346 /* Sleep for a random timeout */ 347 unsigned sleeptime = (sys_random()*sys_getpid()*attempts); 348 attempts += 1; 349 350 sleeptime %= 100; 351 smb_msleep(sleeptime); 352 } 353 } 354 355 DEBUG(0, ("Failed to set new RID\n")); 356 return ret; 357} 358 359 360/***************************************************************************** 361 Allocate a new RID 362*****************************************************************************/ 363 364static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type) 365{ 366 return ldap_next_rid( &ldap_state, rid, rid_type ); 367} 368 369/***************************************************************************** 370 Allocate a new uid or gid 371*****************************************************************************/ 372 373static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) 374{ 375 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; 376 int rc = LDAP_SERVER_DOWN; 377 int count = 0; 378 LDAPMessage *result = NULL; 379 LDAPMessage *entry = NULL; 380 pstring id_str, new_id_str; 381 LDAPMod **mods = NULL; 382 const char *type; 383 char *dn = NULL; 384 const char **attr_list; 385 pstring filter; 386 uid_t luid, huid; 387 gid_t lgid, hgid; 388 389 390 type = (id_type & ID_USERID) ? 391 get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) : 392 get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); 393 394 pstr_sprintf(filter, "(objectClass=%s)", LDAP_OBJ_IDPOOL); 395 396 attr_list = get_attr_list( idpool_attr_list ); 397 398 rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), 399 LDAP_SCOPE_SUBTREE, filter, 400 attr_list, 0, &result); 401 free_attr_list( attr_list ); 402 403 if (rc != LDAP_SUCCESS) { 404 DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL)); 405 goto out; 406 } 407 408 count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); 409 if (count != 1) { 410 DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL)); 411 goto out; 412 } 413 414 dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); 415 if (!dn) { 416 goto out; 417 } 418 entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); 419 420 if (!smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str)) { 421 DEBUG(0,("ldap_allocate_id: %s attribute not found\n", 422 type)); 423 goto out; 424 } 425 426 /* this must succeed or else we wouldn't have initialized */ 427 428 lp_idmap_uid( &luid, &huid); 429 lp_idmap_gid( &lgid, &hgid); 430 431 /* make sure we still have room to grow */ 432 433 if (id_type & ID_USERID) { 434 id->uid = strtoul(id_str, NULL, 10); 435 if (id->uid > huid ) { 436 DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n", 437 (unsigned long)huid)); 438 goto out; 439 } 440 } 441 else { 442 id->gid = strtoul(id_str, NULL, 10); 443 if (id->gid > hgid ) { 444 DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n", 445 (unsigned long)hgid)); 446 goto out; 447 } 448 } 449 450 pstr_sprintf(new_id_str, "%lu", 451 ((id_type & ID_USERID) ? (unsigned long)id->uid : 452 (unsigned long)id->gid) + 1); 453 454 smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str ); 455 smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str ); 456 457 if (mods == NULL) { 458 DEBUG(0,("ldap_allocate_id: smbldap_set_mod() failed.\n")); 459 goto out; 460 } 461 462 rc = smbldap_modify(ldap_state.smbldap_state, dn, mods); 463 464 ldap_mods_free( mods, True ); 465 if (rc != LDAP_SUCCESS) { 466 DEBUG(1,("ldap_allocate_id: Failed to allocate new %s. ldap_modify() failed.\n", 467 type)); 468 goto out; 469 } 470 471 ret = NT_STATUS_OK; 472out: 473 SAFE_FREE(dn); 474 if (result != NULL) 475 ldap_msgfree(result); 476 477 return ret; 478} 479 480/***************************************************************************** 481 get a sid from an id 482*****************************************************************************/ 483 484static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) 485{ 486 LDAPMessage *result = NULL; 487 LDAPMessage *entry = NULL; 488 pstring sid_str; 489 pstring filter; 490 pstring suffix; 491 const char *type; 492 int rc; 493 int count; 494 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; 495 const char **attr_list; 496 497 if ( id_type & ID_USERID ) 498 type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); 499 else 500 type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); 501 502 pstrcpy( suffix, lp_ldap_idmap_suffix() ); 503 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))", 504 LDAP_OBJ_IDMAP_ENTRY, type, 505 ((id_type & ID_USERID) ? id.uid : id.gid)); 506 507 attr_list = get_attr_list( sidmap_attr_list ); 508 rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 509 filter, attr_list, 0, &result); 510 511 if (rc != LDAP_SUCCESS) { 512 DEBUG(3,("ldap_get_isd_from_id: Failure looking up entry (%s)\n", 513 ldap_err2string(rc) )); 514 goto out; 515 } 516 517 count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); 518 519 if (count != 1) { 520 DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %lu\n", 521 type, ((id_type & ID_USERID) ? (unsigned long)id.uid : 522 (unsigned long)id.gid))); 523 goto out; 524 } 525 526 entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); 527 528 if ( !smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, sid_str) ) 529 goto out; 530 531 if (!string_to_sid(sid, sid_str)) 532 goto out; 533 534 ret = NT_STATUS_OK; 535out: 536 free_attr_list( attr_list ); 537 538 if (result) 539 ldap_msgfree(result); 540 541 return ret; 542} 543 544/*********************************************************************** 545 Get an id from a sid 546***********************************************************************/ 547 548static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) 549{ 550 LDAPMessage *result = NULL; 551 LDAPMessage *entry = NULL; 552 pstring sid_str; 553 pstring filter; 554 pstring id_str; 555 const char *suffix; 556 const char *type; 557 int rc; 558 int count; 559 const char **attr_list; 560 char *dn = NULL; 561 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; 562 563 sid_to_string(sid_str, sid); 564 565 DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_str, 566 (*id_type & ID_GROUPID ? "group" : "user") )); 567 568 suffix = lp_ldap_idmap_suffix(); 569 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", 570 LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str); 571 572 if ( *id_type & ID_GROUPID ) 573 type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ); 574 else 575 type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ); 576 577 /* do the search and check for errors */ 578 579 attr_list = get_attr_list( sidmap_attr_list ); 580 rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 581 filter, attr_list, 0, &result); 582 583 if (rc != LDAP_SUCCESS) { 584 DEBUG(3,("ldap_get_id_from_sid: Failure looking up idmap entry (%s)\n", 585 ldap_err2string(rc) )); 586 goto out; 587 } 588 589 /* check for the number of entries returned */ 590 591 count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); 592 593 if ( count > 1 ) { 594 DEBUG(0, ("ldap_get_id_from_sid: (2nd) search %s returned [%d] entries!\n", 595 filter, count)); 596 goto out; 597 } 598 599 /* try to allocate a new id if we still haven't found one */ 600 601 if ( !count ) { 602 int i; 603 604 if (*id_type & ID_QUERY_ONLY) { 605 DEBUG(5,("ldap_get_id_from_sid: No matching entry found and QUERY_ONLY flag set\n")); 606 goto out; 607 } 608 609 DEBUG(8,("ldap_get_id_from_sid: Allocating new id\n")); 610 611 for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) { 612 ret = ldap_allocate_id(id, *id_type); 613 if ( NT_STATUS_IS_OK(ret) ) 614 break; 615 } 616 617 if ( !NT_STATUS_IS_OK(ret) ) { 618 DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n")); 619 goto out; 620 } 621 622 DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n", 623 (*id_type & ID_GROUPID ? 'g' : 'u'), (uint32)id->uid )); 624 625 ret = ldap_set_mapping(sid, *id, *id_type); 626 627 /* all done */ 628 629 goto out; 630 } 631 632 DEBUG(10,("ldap_get_id_from_sid: success\n")); 633 634 entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); 635 636 dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); 637 if (!dn) 638 goto out; 639 640 DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type)); 641 642 if ( smbldap_get_single_pstring(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) { 643 if ( (*id_type & ID_USERID) ) 644 id->uid = strtoul(id_str, NULL, 10); 645 else 646 id->gid = strtoul(id_str, NULL, 10); 647 648 ret = NT_STATUS_OK; 649 goto out; 650 } 651 652out: 653 free_attr_list( attr_list ); 654 if (result) 655 ldap_msgfree(result); 656 SAFE_FREE(dn); 657 658 return ret; 659} 660 661/********************************************************************** 662 Verify the sambaUnixIdPool entry in the directiry. 663**********************************************************************/ 664 665static NTSTATUS verify_idpool( void ) 666{ 667 fstring filter; 668 int rc; 669 const char **attr_list; 670 LDAPMessage *result = NULL; 671 LDAPMod **mods = NULL; 672 int count; 673 674 fstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_IDPOOL ); 675 676 attr_list = get_attr_list( idpool_attr_list ); 677 rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), 678 LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); 679 free_attr_list ( attr_list ); 680 681 if (rc != LDAP_SUCCESS) 682 return NT_STATUS_UNSUCCESSFUL; 683 684 count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); 685 686 ldap_msgfree(result); 687 688 if ( count > 1 ) { 689 DEBUG(0,("ldap_idmap_init: multiple entries returned from %s (base == %s)\n", 690 filter, lp_ldap_idmap_suffix() )); 691 return NT_STATUS_UNSUCCESSFUL; 692 } 693 else if (count == 0) { 694 uid_t luid, huid; 695 gid_t lgid, hgid; 696 fstring uid_str, gid_str; 697 698 if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) { 699 DEBUG(0,("ldap_idmap_init: idmap uid/gid parameters not specified\n")); 700 return NT_STATUS_UNSUCCESSFUL; 701 } 702 703 fstr_sprintf( uid_str, "%d", luid ); 704 fstr_sprintf( gid_str, "%d", lgid ); 705 706 smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDPOOL ); 707 smbldap_set_mod( &mods, LDAP_MOD_ADD, 708 get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER), uid_str ); 709 smbldap_set_mod( &mods, LDAP_MOD_ADD, 710 get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER), gid_str ); 711 if (mods) { 712 rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods); 713 ldap_mods_free( mods, True ); 714 } else { 715 return NT_STATUS_UNSUCCESSFUL; 716 } 717 } 718 719 return ( rc==LDAP_SUCCESS ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); 720} 721 722/***************************************************************************** 723 Initialise idmap database. 724*****************************************************************************/ 725 726static NTSTATUS ldap_idmap_init( char *params ) 727{ 728 NTSTATUS nt_status; 729 730 ldap_state.mem_ctx = talloc_init("idmap_ldap"); 731 if (!ldap_state.mem_ctx) { 732 return NT_STATUS_NO_MEMORY; 733 } 734 735 /* assume location is the only parameter */ 736 if (!NT_STATUS_IS_OK(nt_status = 737 smbldap_init(ldap_state.mem_ctx, params, 738 &ldap_state.smbldap_state))) { 739 talloc_destroy(ldap_state.mem_ctx); 740 return nt_status; 741 } 742 743 /* see if the idmap suffix and sub entries exists */ 744 745 nt_status = verify_idpool(); 746 if ( !NT_STATUS_IS_OK(nt_status) ) 747 return nt_status; 748 749 return NT_STATUS_OK; 750} 751 752/***************************************************************************** 753 End the LDAP session 754*****************************************************************************/ 755 756static NTSTATUS ldap_idmap_close(void) 757{ 758 759 smbldap_free_struct(&(ldap_state).smbldap_state); 760 talloc_destroy(ldap_state.mem_ctx); 761 762 DEBUG(5,("The connection to the LDAP server was closed\n")); 763 /* maybe free the results here --metze */ 764 765 return NT_STATUS_OK; 766} 767 768 769/* This function doesn't make as much sense in an LDAP world since the calling 770 node doesn't really control the ID ranges */ 771static void ldap_idmap_status(void) 772{ 773 DEBUG(0, ("LDAP IDMAP Status not available\n")); 774} 775 776static struct idmap_methods ldap_methods = { 777 ldap_idmap_init, 778 ldap_allocate_rid, 779 ldap_allocate_id, 780 ldap_get_sid_from_id, 781 ldap_get_id_from_sid, 782 ldap_set_mapping, 783 ldap_idmap_close, 784 ldap_idmap_status 785 786}; 787 788NTSTATUS idmap_ldap_init(void) 789{ 790 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", &ldap_methods); 791} 792