1/* 2 Unix SMB/CIFS implementation. 3 4 Winbind daemon for ntdom nss module 5 6 Copyright (C) Tim Potter 2000-2001 7 Copyright (C) 2001 by Martin Pool <mbp@samba.org> 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22*/ 23 24#include "includes.h" 25#include "winbindd.h" 26 27#undef DBGC_CLASS 28#define DBGC_CLASS DBGC_WINBIND 29 30/** 31 * @file winbindd_util.c 32 * 33 * Winbind daemon for NT domain authentication nss module. 34 **/ 35 36 37/** 38 * Used to clobber name fields that have an undefined value. 39 * 40 * Correct code should never look at a field that has this value. 41 **/ 42 43static const fstring name_deadbeef = "<deadbeef>"; 44 45/* The list of trusted domains. Note that the list can be deleted and 46 recreated using the init_domain_list() function so pointers to 47 individual winbindd_domain structures cannot be made. Keep a copy of 48 the domain name instead. */ 49 50static struct winbindd_domain *_domain_list; 51 52/** 53 When was the last scan of trusted domains done? 54 55 0 == not ever 56*/ 57 58static time_t last_trustdom_scan; 59 60struct winbindd_domain *domain_list(void) 61{ 62 /* Initialise list */ 63 64 if (!_domain_list) 65 if (!init_domain_list()) 66 return NULL; 67 68 return _domain_list; 69} 70 71/* Free all entries in the trusted domain list */ 72 73void free_domain_list(void) 74{ 75 struct winbindd_domain *domain = _domain_list; 76 77 while(domain) { 78 struct winbindd_domain *next = domain->next; 79 80 DLIST_REMOVE(_domain_list, domain); 81 SAFE_FREE(domain); 82 domain = next; 83 } 84} 85 86static BOOL is_internal_domain(const DOM_SID *sid) 87{ 88 extern DOM_SID global_sid_Builtin; 89 90 if (sid == NULL) 91 return False; 92 93 if (sid_compare_domain(sid, get_global_sam_sid()) == 0) 94 return True; 95 96 if (sid_compare_domain(sid, &global_sid_Builtin) == 0) 97 return True; 98 99 return False; 100} 101 102 103/* Add a trusted domain to our list of domains */ 104static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name, 105 struct winbindd_methods *methods, 106 DOM_SID *sid) 107{ 108 struct winbindd_domain *domain; 109 const char *alternative_name = NULL; 110 static const DOM_SID null_sid; 111 112 /* ignore alt_name if we are not in an AD domain */ 113 114 if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) { 115 alternative_name = alt_name; 116 } 117 118 /* We can't call domain_list() as this function is called from 119 init_domain_list() and we'll get stuck in a loop. */ 120 for (domain = _domain_list; domain; domain = domain->next) { 121 if (strequal(domain_name, domain->name) || 122 strequal(domain_name, domain->alt_name)) { 123 return domain; 124 } 125 if (alternative_name && *alternative_name) { 126 if (strequal(alternative_name, domain->name) || 127 strequal(alternative_name, domain->alt_name)) { 128 return domain; 129 } 130 } 131 if (sid) { 132 if (sid_equal(sid, &null_sid) ) { 133 134 } else if (sid_equal(sid, &domain->sid)) { 135 return domain; 136 } 137 } 138 } 139 140 /* Create new domain entry */ 141 142 if ((domain = SMB_MALLOC_P(struct winbindd_domain)) == NULL) 143 return NULL; 144 145 /* Fill in fields */ 146 147 ZERO_STRUCTP(domain); 148 149 /* prioritise the short name */ 150 if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) { 151 fstrcpy(domain->name, alternative_name); 152 fstrcpy(domain->alt_name, domain_name); 153 } else { 154 fstrcpy(domain->name, domain_name); 155 if (alternative_name) { 156 fstrcpy(domain->alt_name, alternative_name); 157 } 158 } 159 160 domain->methods = methods; 161 domain->backend = NULL; 162 domain->internal = is_internal_domain(sid); 163 domain->sequence_number = DOM_SEQUENCE_NONE; 164 domain->last_seq_check = 0; 165 domain->initialized = False; 166 if (sid) { 167 sid_copy(&domain->sid, sid); 168 } 169 170 /* Link to domain list */ 171 DLIST_ADD(_domain_list, domain); 172 173 DEBUG(2,("Added domain %s %s %s\n", 174 domain->name, domain->alt_name, 175 &domain->sid?sid_string_static(&domain->sid):"")); 176 177 return domain; 178} 179 180/******************************************************************** 181 rescan our domains looking for new trusted domains 182********************************************************************/ 183 184static void add_trusted_domains( struct winbindd_domain *domain ) 185{ 186 extern struct winbindd_methods cache_methods; 187 TALLOC_CTX *mem_ctx; 188 NTSTATUS result; 189 time_t t; 190 char **names; 191 char **alt_names; 192 int num_domains = 0; 193 DOM_SID *dom_sids, null_sid; 194 int i; 195 struct winbindd_domain *new_domain; 196 197 /* trusted domains might be disabled */ 198 if (!lp_allow_trusted_domains()) { 199 return; 200 } 201 202 DEBUG(5, ("scanning trusted domain list\n")); 203 204 if (!(mem_ctx = talloc_init("init_domain_list"))) 205 return; 206 207 ZERO_STRUCTP(&null_sid); 208 209 t = time(NULL); 210 211 /* ask the DC what domains it trusts */ 212 213 result = domain->methods->trusted_domains(domain, mem_ctx, (unsigned int *)&num_domains, 214 &names, &alt_names, &dom_sids); 215 216 if ( NT_STATUS_IS_OK(result) ) { 217 218 /* Add each domain to the trusted domain list */ 219 220 for(i = 0; i < num_domains; i++) { 221 DEBUG(10,("Found domain %s\n", names[i])); 222 add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, 223 &cache_methods, &dom_sids[i]); 224 225 /* if the SID was empty, we better set it now */ 226 227 if ( sid_equal(&dom_sids[i], &null_sid) ) { 228 229 new_domain = find_domain_from_name(names[i]); 230 231 /* this should never happen */ 232 if ( !new_domain ) { 233 DEBUG(0,("rescan_trust_domains: can't find the domain I just added! [%s]\n", 234 names[i])); 235 break; 236 } 237 238 /* call the cache method; which will operate on the winbindd_domain \ 239 passed in and choose either rpc or ads as appropriate */ 240 241 result = domain->methods->domain_sid( new_domain, &new_domain->sid ); 242 243 if ( NT_STATUS_IS_OK(result) ) 244 sid_copy( &dom_sids[i], &new_domain->sid ); 245 } 246 247 /* store trusted domain in the cache */ 248 trustdom_cache_store(names[i], alt_names ? alt_names[i] : NULL, 249 &dom_sids[i], t + WINBINDD_RESCAN_FREQ); 250 } 251 } 252 253 talloc_destroy(mem_ctx); 254} 255 256/******************************************************************** 257 Periodically we need to refresh the trusted domain cache for smbd 258********************************************************************/ 259 260void rescan_trusted_domains( void ) 261{ 262 time_t now = time(NULL); 263 struct winbindd_domain *mydomain = NULL; 264 265 /* see if the time has come... */ 266 267 if ( (now > last_trustdom_scan) && ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) ) 268 return; 269 270 if ( (mydomain = find_our_domain()) == NULL ) { 271 DEBUG(0,("rescan_trusted_domains: Can't find my own domain!\n")); 272 return; 273 } 274 275 /* this will only add new domains we didn't already know about */ 276 277 add_trusted_domains( mydomain ); 278 279 last_trustdom_scan = now; 280 281 return; 282} 283 284/* Look up global info for the winbind daemon */ 285BOOL init_domain_list(void) 286{ 287 extern DOM_SID global_sid_Builtin; 288 extern struct winbindd_methods cache_methods; 289 extern struct winbindd_methods passdb_methods; 290 struct winbindd_domain *domain; 291 292 /* Free existing list */ 293 free_domain_list(); 294 295 /* Add ourselves as the first entry. */ 296 297 if (IS_DC) { 298 domain = add_trusted_domain(get_global_sam_name(), NULL, 299 &passdb_methods, get_global_sam_sid()); 300 } else { 301 302 domain = add_trusted_domain( lp_workgroup(), lp_realm(), 303 &cache_methods, NULL); 304 305 /* set flags about native_mode, active_directory */ 306 set_dc_type_and_flags(domain); 307 } 308 309 domain->primary = True; 310 311 /* get any alternate name for the primary domain */ 312 313 cache_methods.alternate_name(domain); 314 315 /* now we have the correct netbios (short) domain name */ 316 317 if ( *domain->name ) 318 set_global_myworkgroup( domain->name ); 319 320 if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) { 321 DEBUG(1, ("Could not fetch sid for our domain %s\n", 322 domain->name)); 323 return False; 324 } 325 326 /* do an initial scan for trusted domains */ 327 add_trusted_domains(domain); 328 329 330 /* Add our local SAM domains */ 331 332 add_trusted_domain("BUILTIN", NULL, &passdb_methods, 333 &global_sid_Builtin); 334 335 if (!IS_DC) { 336 add_trusted_domain(get_global_sam_name(), NULL, 337 &passdb_methods, get_global_sam_sid()); 338 } 339 340 /* avoid rescanning this right away */ 341 last_trustdom_scan = time(NULL); 342 return True; 343} 344 345/** 346 * Given a domain name, return the struct winbindd domain info for it 347 * 348 * @note Do *not* pass lp_workgroup() to this function. domain_list 349 * may modify it's value, and free that pointer. Instead, our local 350 * domain may be found by calling find_our_domain(). 351 * directly. 352 * 353 * 354 * @return The domain structure for the named domain, if it is working. 355 */ 356 357struct winbindd_domain *find_domain_from_name(const char *domain_name) 358{ 359 struct winbindd_domain *domain; 360 361 /* Search through list */ 362 363 for (domain = domain_list(); domain != NULL; domain = domain->next) { 364 if (strequal(domain_name, domain->name) || 365 (domain->alt_name[0] && strequal(domain_name, domain->alt_name))) { 366 if (!domain->initialized) 367 set_dc_type_and_flags(domain); 368 369 return domain; 370 } 371 } 372 373 /* Not found */ 374 375 return NULL; 376} 377 378/* Given a domain sid, return the struct winbindd domain info for it */ 379 380struct winbindd_domain *find_domain_from_sid(const DOM_SID *sid) 381{ 382 struct winbindd_domain *domain; 383 384 /* Search through list */ 385 386 for (domain = domain_list(); domain != NULL; domain = domain->next) { 387 if (sid_compare_domain(sid, &domain->sid) == 0) { 388 if (!domain->initialized) 389 set_dc_type_and_flags(domain); 390 return domain; 391 } 392 } 393 394 /* Not found */ 395 396 return NULL; 397} 398 399/* Given a domain sid, return the struct winbindd domain info for it */ 400 401struct winbindd_domain *find_our_domain(void) 402{ 403 struct winbindd_domain *domain; 404 405 /* Search through list */ 406 407 for (domain = domain_list(); domain != NULL; domain = domain->next) { 408 if (domain->primary) 409 return domain; 410 } 411 412 /* Not found */ 413 414 return NULL; 415} 416 417/* Find the appropriate domain to lookup a name or SID */ 418 419struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid) 420{ 421 /* A DC can't ask the local smbd for remote SIDs, here winbindd is the 422 * one to contact the external DC's. On member servers the internal 423 * domains are different: These are part of the local SAM. */ 424 425 if (IS_DC || is_internal_domain(sid)) 426 return find_domain_from_sid(sid); 427 428 /* On a member server a query for SID or name can always go to our 429 * primary DC. */ 430 431 return find_our_domain(); 432} 433 434struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name) 435{ 436 if (IS_DC || strequal(domain_name, "BUILTIN") || 437 strequal(domain_name, get_global_sam_name())) 438 return find_domain_from_name(domain_name); 439 440 return find_our_domain(); 441} 442 443/* Lookup a sid in a domain from a name */ 444 445BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, 446 const char *domain_name, 447 const char *name, DOM_SID *sid, 448 enum SID_NAME_USE *type) 449{ 450 NTSTATUS result; 451 TALLOC_CTX *mem_ctx; 452 453 mem_ctx = talloc_init("lookup_sid_by_name for %s\\%s\n", 454 domain_name, name); 455 if (!mem_ctx) 456 return False; 457 458 /* Lookup name */ 459 result = domain->methods->name_to_sid(domain, mem_ctx, domain_name, name, sid, type); 460 461 talloc_destroy(mem_ctx); 462 463 /* Return rid and type if lookup successful */ 464 if (!NT_STATUS_IS_OK(result)) { 465 *type = SID_NAME_UNKNOWN; 466 } 467 468 return NT_STATUS_IS_OK(result); 469} 470 471/** 472 * @brief Lookup a name in a domain from a sid. 473 * 474 * @param sid Security ID you want to look up. 475 * @param name On success, set to the name corresponding to @p sid. 476 * @param dom_name On success, set to the 'domain name' corresponding to @p sid. 477 * @param type On success, contains the type of name: alias, group or 478 * user. 479 * @retval True if the name exists, in which case @p name and @p type 480 * are set, otherwise False. 481 **/ 482BOOL winbindd_lookup_name_by_sid(DOM_SID *sid, 483 fstring dom_name, 484 fstring name, 485 enum SID_NAME_USE *type) 486{ 487 char *names; 488 char *dom_names; 489 NTSTATUS result; 490 TALLOC_CTX *mem_ctx; 491 BOOL rv = False; 492 struct winbindd_domain *domain; 493 494 domain = find_lookup_domain_from_sid(sid); 495 496 if (!domain) { 497 DEBUG(1,("Can't find domain from sid\n")); 498 return False; 499 } 500 501 /* Lookup name */ 502 503 if (!(mem_ctx = talloc_init("winbindd_lookup_name_by_sid"))) 504 return False; 505 506 result = domain->methods->sid_to_name(domain, mem_ctx, sid, &dom_names, &names, type); 507 508 /* Return name and type if successful */ 509 510 if ((rv = NT_STATUS_IS_OK(result))) { 511 fstrcpy(dom_name, dom_names); 512 fstrcpy(name, names); 513 } else { 514 *type = SID_NAME_UNKNOWN; 515 fstrcpy(name, name_deadbeef); 516 } 517 518 talloc_destroy(mem_ctx); 519 520 return rv; 521} 522 523 524/* Free state information held for {set,get,end}{pw,gr}ent() functions */ 525 526void free_getent_state(struct getent_state *state) 527{ 528 struct getent_state *temp; 529 530 /* Iterate over state list */ 531 532 temp = state; 533 534 while(temp != NULL) { 535 struct getent_state *next; 536 537 /* Free sam entries then list entry */ 538 539 SAFE_FREE(state->sam_entries); 540 DLIST_REMOVE(state, state); 541 next = temp->next; 542 543 SAFE_FREE(temp); 544 temp = next; 545 } 546} 547 548/* Parse winbindd related parameters */ 549 550BOOL winbindd_param_init(void) 551{ 552 /* Parse winbind uid and winbind_gid parameters */ 553 554 if (!lp_idmap_uid(&server_state.uid_low, &server_state.uid_high)) { 555 DEBUG(0, ("winbindd: idmap uid range missing or invalid\n")); 556 DEBUG(0, ("winbindd: cannot continue, exiting.\n")); 557 return False; 558 } 559 560 if (!lp_idmap_gid(&server_state.gid_low, &server_state.gid_high)) { 561 DEBUG(0, ("winbindd: idmap gid range missing or invalid\n")); 562 DEBUG(0, ("winbindd: cannot continue, exiting.\n")); 563 return False; 564 } 565 566 return True; 567} 568 569/* Check if a domain is present in a comma-separated list of domains */ 570 571BOOL check_domain_env(char *domain_env, char *domain) 572{ 573 fstring name; 574 const char *tmp = domain_env; 575 576 while(next_token(&tmp, name, ",", sizeof(fstring))) { 577 if (strequal(name, domain)) 578 return True; 579 } 580 581 return False; 582} 583 584/* Is this a domain which we may assume no DOMAIN\ prefix? */ 585 586static BOOL assume_domain(const char *domain) { 587 if ((lp_winbind_use_default_domain() 588 || lp_winbind_trusted_domains_only()) && 589 strequal(lp_workgroup(), domain)) 590 return True; 591 592 if (strequal(get_global_sam_name(), domain)) 593 return True; 594 595 return False; 596} 597 598/* Parse a string of the form DOMAIN/user into a domain and a user */ 599 600BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) 601{ 602 char *p = strchr(domuser,*lp_winbind_separator()); 603 604 if ( !p ) { 605 fstrcpy(user, domuser); 606 607 if ( assume_domain(lp_workgroup())) { 608 fstrcpy(domain, lp_workgroup()); 609 } else { 610 fstrcpy( domain, get_global_sam_name() ); 611 } 612 } 613 else { 614 fstrcpy(user, p+1); 615 fstrcpy(domain, domuser); 616 domain[PTR_DIFF(p, domuser)] = 0; 617 } 618 619 strupper_m(domain); 620 621 return True; 622} 623 624/* 625 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and 626 'winbind separator' options. 627 This means: 628 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is 629 lp_workgroup() 630 631 If we are a PDC or BDC, and this is for our domain, do likewise. 632 633 Also, if omit DOMAIN if 'winbind trusted domains only = true', as the 634 username is then unqualified in unix 635 636*/ 637void fill_domain_username(fstring name, const char *domain, const char *user) 638{ 639 strlower_m( user ); 640 641 if (assume_domain(domain)) { 642 strlcpy(name, user, sizeof(fstring)); 643 } else { 644 slprintf(name, sizeof(fstring) - 1, "%s%c%s", 645 domain, *lp_winbind_separator(), 646 user); 647 } 648} 649 650/* 651 * Winbindd socket accessor functions 652 */ 653 654char *get_winbind_priv_pipe_dir(void) 655{ 656 return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR); 657} 658 659/* Open the winbindd socket */ 660 661static int _winbindd_socket = -1; 662static int _winbindd_priv_socket = -1; 663 664int open_winbindd_socket(void) 665{ 666 if (_winbindd_socket == -1) { 667 _winbindd_socket = create_pipe_sock( 668 WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755); 669 DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n", 670 _winbindd_socket)); 671 } 672 673 return _winbindd_socket; 674} 675 676int open_winbindd_priv_socket(void) 677{ 678 if (_winbindd_priv_socket == -1) { 679 _winbindd_priv_socket = create_pipe_sock( 680 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750); 681 DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n", 682 _winbindd_priv_socket)); 683 } 684 685 return _winbindd_priv_socket; 686} 687 688/* Close the winbindd socket */ 689 690void close_winbindd_socket(void) 691{ 692 if (_winbindd_socket != -1) { 693 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", 694 _winbindd_socket)); 695 close(_winbindd_socket); 696 _winbindd_socket = -1; 697 } 698 if (_winbindd_priv_socket != -1) { 699 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", 700 _winbindd_priv_socket)); 701 close(_winbindd_priv_socket); 702 _winbindd_priv_socket = -1; 703 } 704} 705 706/* 707 * Client list accessor functions 708 */ 709 710static struct winbindd_cli_state *_client_list; 711static int _num_clients; 712 713/* Return list of all connected clients */ 714 715struct winbindd_cli_state *winbindd_client_list(void) 716{ 717 return _client_list; 718} 719 720/* Add a connection to the list */ 721 722void winbindd_add_client(struct winbindd_cli_state *cli) 723{ 724 DLIST_ADD(_client_list, cli); 725 _num_clients++; 726} 727 728/* Remove a client from the list */ 729 730void winbindd_remove_client(struct winbindd_cli_state *cli) 731{ 732 DLIST_REMOVE(_client_list, cli); 733 _num_clients--; 734} 735 736/* Demote a client to be the last in the list */ 737 738void winbindd_demote_client(struct winbindd_cli_state *cli) 739{ 740 struct winbindd_cli_state *tmp; 741 DLIST_DEMOTE(_client_list, cli, tmp); 742} 743 744/* Close all open clients */ 745 746void winbindd_kill_all_clients(void) 747{ 748 struct winbindd_cli_state *cl = winbindd_client_list(); 749 750 DEBUG(10, ("winbindd_kill_all_clients: going postal\n")); 751 752 while (cl) { 753 struct winbindd_cli_state *next; 754 755 next = cl->next; 756 winbindd_remove_client(cl); 757 cl = next; 758 } 759} 760 761/* Return number of open clients */ 762 763int winbindd_num_clients(void) 764{ 765 return _num_clients; 766} 767 768/* Help with RID -> SID conversion */ 769 770DOM_SID *rid_to_talloced_sid(struct winbindd_domain *domain, 771 TALLOC_CTX *mem_ctx, 772 uint32 rid) 773{ 774 DOM_SID *sid; 775 sid = TALLOC_P(mem_ctx, DOM_SID); 776 if (!sid) { 777 smb_panic("rid_to_to_talloced_sid: talloc for DOM_SID failed!\n"); 778 } 779 sid_copy(sid, &domain->sid); 780 sid_append_rid(sid, rid); 781 return sid; 782} 783 784/***************************************************************************** 785 For idmap conversion: convert one record to new format 786 Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid 787 instead of the SID. 788*****************************************************************************/ 789static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state) 790{ 791 struct winbindd_domain *domain; 792 char *p; 793 DOM_SID sid; 794 uint32 rid; 795 fstring keystr; 796 fstring dom_name; 797 TDB_DATA key2; 798 BOOL *failed = (BOOL *)state; 799 800 DEBUG(10,("Converting %s\n", key.dptr)); 801 802 p = strchr(key.dptr, '/'); 803 if (!p) 804 return 0; 805 806 *p = 0; 807 fstrcpy(dom_name, key.dptr); 808 *p++ = '/'; 809 810 domain = find_domain_from_name(dom_name); 811 if (domain == NULL) { 812 /* We must delete the old record. */ 813 DEBUG(0,("Unable to find domain %s\n", dom_name )); 814 DEBUG(0,("deleting record %s\n", key.dptr )); 815 816 if (tdb_delete(tdb, key) != 0) { 817 DEBUG(0, ("Unable to delete record %s\n", key.dptr)); 818 *failed = True; 819 return -1; 820 } 821 822 return 0; 823 } 824 825 rid = atoi(p); 826 827 sid_copy(&sid, &domain->sid); 828 sid_append_rid(&sid, rid); 829 830 sid_to_string(keystr, &sid); 831 key2.dptr = keystr; 832 key2.dsize = strlen(keystr) + 1; 833 834 if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) { 835 DEBUG(0,("Unable to add record %s\n", key2.dptr )); 836 *failed = True; 837 return -1; 838 } 839 840 if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) { 841 DEBUG(0,("Unable to update record %s\n", data.dptr )); 842 *failed = True; 843 return -1; 844 } 845 846 if (tdb_delete(tdb, key) != 0) { 847 DEBUG(0,("Unable to delete record %s\n", key.dptr )); 848 *failed = True; 849 return -1; 850 } 851 852 return 0; 853} 854 855/* These definitions are from sam/idmap_tdb.c. Replicated here just 856 out of laziness.... :-( */ 857 858/* High water mark keys */ 859#define HWM_GROUP "GROUP HWM" 860#define HWM_USER "USER HWM" 861 862/* idmap version determines auto-conversion */ 863#define IDMAP_VERSION 2 864 865 866/***************************************************************************** 867 Convert the idmap database from an older version. 868*****************************************************************************/ 869 870static BOOL idmap_convert(const char *idmap_name) 871{ 872 int32 vers; 873 BOOL bigendianheader; 874 BOOL failed = False; 875 TDB_CONTEXT *idmap_tdb; 876 877 if (!(idmap_tdb = tdb_open_log(idmap_name, 0, 878 TDB_DEFAULT, O_RDWR, 879 0600))) { 880 DEBUG(0, ("idmap_convert: Unable to open idmap database\n")); 881 return False; 882 } 883 884 bigendianheader = (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False; 885 886 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); 887 888 if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) { 889 /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */ 890 /* 891 * high and low records were created on a 892 * big endian machine and will need byte-reversing. 893 */ 894 895 int32 wm; 896 897 wm = tdb_fetch_int32(idmap_tdb, HWM_USER); 898 899 if (wm != -1) { 900 wm = IREV(wm); 901 } else { 902 wm = server_state.uid_low; 903 } 904 905 if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) { 906 DEBUG(0, ("idmap_convert: Unable to byteswap user hwm in idmap database\n")); 907 tdb_close(idmap_tdb); 908 return False; 909 } 910 911 wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP); 912 if (wm != -1) { 913 wm = IREV(wm); 914 } else { 915 wm = server_state.gid_low; 916 } 917 918 if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) { 919 DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n")); 920 tdb_close(idmap_tdb); 921 return False; 922 } 923 } 924 925 /* the old format stored as DOMAIN/rid - now we store the SID direct */ 926 tdb_traverse(idmap_tdb, convert_fn, &failed); 927 928 if (failed) { 929 DEBUG(0, ("Problem during conversion\n")); 930 tdb_close(idmap_tdb); 931 return False; 932 } 933 934 if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) { 935 DEBUG(0, ("idmap_convert: Unable to dtore idmap version in databse\n")); 936 tdb_close(idmap_tdb); 937 return False; 938 } 939 940 tdb_close(idmap_tdb); 941 return True; 942} 943 944/***************************************************************************** 945 Convert the idmap database from an older version if necessary 946*****************************************************************************/ 947 948BOOL winbindd_upgrade_idmap(void) 949{ 950 pstring idmap_name; 951 pstring backup_name; 952 SMB_STRUCT_STAT stbuf; 953 TDB_CONTEXT *idmap_tdb; 954 955 pstrcpy(idmap_name, lock_path("winbindd_idmap.tdb")); 956 957 if (!file_exist(idmap_name, &stbuf)) { 958 /* nothing to convert return */ 959 return True; 960 } 961 962 if (!(idmap_tdb = tdb_open_log(idmap_name, 0, 963 TDB_DEFAULT, O_RDWR, 964 0600))) { 965 DEBUG(0, ("idmap_convert: Unable to open idmap database\n")); 966 return False; 967 } 968 969 if (tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION") == IDMAP_VERSION) { 970 /* nothing to convert return */ 971 tdb_close(idmap_tdb); 972 return True; 973 } 974 975 /* backup_tdb expects the tdb not to be open */ 976 tdb_close(idmap_tdb); 977 978 DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n")); 979 980 pstrcpy(backup_name, idmap_name); 981 pstrcat(backup_name, ".bak"); 982 983 if (backup_tdb(idmap_name, backup_name) != 0) { 984 DEBUG(0, ("Could not backup idmap database\n")); 985 return False; 986 } 987 988 return idmap_convert(idmap_name); 989} 990 991/******************************************************************* 992 wrapper around retrieving the trust account password 993*******************************************************************/ 994 995BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], 996 time_t *pass_last_set_time, uint32 *channel) 997{ 998 DOM_SID sid; 999 char *pwd; 1000 1001 /* if we are a DC and this is not our domain, then lookup an account 1002 for the domain trust */ 1003 1004 if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) 1005 { 1006 if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, 1007 pass_last_set_time) ) 1008 { 1009 DEBUG(0, ("get_trust_pw: could not fetch trust account " 1010 "password for trusted domain %s\n", domain)); 1011 return False; 1012 } 1013 1014 *channel = SEC_CHAN_DOMAIN; 1015 E_md4hash(pwd, ret_pwd); 1016 SAFE_FREE(pwd); 1017 1018 return True; 1019 } 1020 else /* just get the account for our domain (covers 1021 ROLE_DOMAIN_MEMBER as well */ 1022 { 1023 /* get the machine trust account for our domain */ 1024 1025 if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd, 1026 pass_last_set_time, channel) ) 1027 { 1028 DEBUG(0, ("get_trust_pw: could not fetch trust account " 1029 "password for my domain %s\n", domain)); 1030 return False; 1031 } 1032 1033 return True; 1034 } 1035 1036 /* Failure */ 1037} 1038 1039