1/* 2 Unix SMB/CIFS implementation. 3 dump the remote SAM using rpc samsync operations 4 5 Copyright (C) Andrew Tridgell 2002 6 Copyright (C) Tim Potter 2001,2002 7 Modified by Volker Lendecke 2002 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 "utils/net.h" 26 27extern DOM_SID global_sid_Builtin; 28 29static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g) 30{ 31 int i; 32 d_printf("Group mem %u: ", rid); 33 for (i=0;i<g->num_members;i++) { 34 d_printf("%u ", g->rids[i]); 35 } 36 d_printf("\n"); 37} 38 39 40static const char *display_time(NTTIME *nttime) 41{ 42 static fstring string; 43 44 float high; 45 float low; 46 int sec; 47 int days, hours, mins, secs; 48 int offset = 1; 49 50 if (nttime->high==0 && nttime->low==0) 51 return "Now"; 52 53 if (nttime->high==0x80000000 && nttime->low==0) 54 return "Never"; 55 56 high = 65536; 57 high = high/10000; 58 high = high*65536; 59 high = high/1000; 60 high = high * (~nttime->high); 61 62 low = ~nttime->low; 63 low = low/(1000*1000*10); 64 65 sec=high+low; 66 sec+=offset; 67 68 days=sec/(60*60*24); 69 hours=(sec - (days*60*60*24)) / (60*60); 70 mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60; 71 secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60); 72 73 fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs); 74 return (string); 75} 76 77 78static void display_alias_info(uint32 rid, SAM_ALIAS_INFO *a) 79{ 80 d_printf("Alias '%s' ", unistr2_static(&a->uni_als_name)); 81 d_printf("desc='%s' rid=%u\n", unistr2_static(&a->uni_als_desc), a->als_rid); 82} 83 84static void display_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *a) 85{ 86 int i; 87 d_printf("Alias rid %u: ", rid); 88 for (i=0;i<a->num_members;i++) { 89 d_printf("%s ", sid_string_static(&a->sids[i].sid)); 90 } 91 d_printf("\n"); 92} 93 94static void display_account_info(uint32 rid, SAM_ACCOUNT_INFO *a) 95{ 96 fstring hex_nt_passwd, hex_lm_passwd; 97 uchar lm_passwd[16], nt_passwd[16]; 98 static uchar zero_buf[16]; 99 100 /* Decode hashes from password hash (if they are not NULL) */ 101 102 if (memcmp(a->pass.buf_lm_pwd, zero_buf, 16) != 0) { 103 sam_pwd_hash(a->user_rid, a->pass.buf_lm_pwd, lm_passwd, 0); 104 pdb_sethexpwd(hex_lm_passwd, lm_passwd, a->acb_info); 105 } else { 106 pdb_sethexpwd(hex_lm_passwd, NULL, 0); 107 } 108 109 if (memcmp(a->pass.buf_nt_pwd, zero_buf, 16) != 0) { 110 sam_pwd_hash(a->user_rid, a->pass.buf_nt_pwd, nt_passwd, 0); 111 pdb_sethexpwd(hex_nt_passwd, nt_passwd, a->acb_info); 112 } else { 113 pdb_sethexpwd(hex_nt_passwd, NULL, 0); 114 } 115 116 printf("%s:%d:%s:%s:%s:LCT-0\n", unistr2_static(&a->uni_acct_name), 117 a->user_rid, hex_lm_passwd, hex_nt_passwd, 118 pdb_encode_acct_ctrl(a->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN)); 119} 120 121static void display_domain_info(SAM_DOMAIN_INFO *a) 122{ 123 time_t u_logout; 124 125 u_logout = nt_time_to_unix_abs((NTTIME *)&a->force_logoff); 126 127 d_printf("Domain name: %s\n", unistr2_static(&a->uni_dom_name)); 128 129 d_printf("Minimal Password Length: %d\n", a->min_pwd_len); 130 d_printf("Password History Length: %d\n", a->pwd_history_len); 131 132 d_printf("Force Logoff: %d\n", (int)u_logout); 133 134 d_printf("Max Password Age: %s\n", display_time((NTTIME *)&a->max_pwd_age)); 135 d_printf("Min Password Age: %s\n", display_time((NTTIME *)&a->min_pwd_age)); 136 137 d_printf("Lockout Time: %s\n", display_time((NTTIME *)&a->account_lockout.lockout_duration)); 138 d_printf("Lockout Reset Time: %s\n", display_time((NTTIME *)&a->account_lockout.reset_count)); 139 140 d_printf("Bad Attempt Lockout: %d\n", a->account_lockout.bad_attempt_lockout); 141 d_printf("User must logon to change password: %d\n", a->logon_chgpass); 142} 143 144static void display_group_info(uint32 rid, SAM_GROUP_INFO *a) 145{ 146 d_printf("Group '%s' ", unistr2_static(&a->uni_grp_name)); 147 d_printf("desc='%s', rid=%u\n", unistr2_static(&a->uni_grp_desc), rid); 148} 149 150static void display_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta) 151{ 152 switch (hdr_delta->type) { 153 case SAM_DELTA_ACCOUNT_INFO: 154 display_account_info(hdr_delta->target_rid, &delta->account_info); 155 break; 156 case SAM_DELTA_GROUP_MEM: 157 display_group_mem_info(hdr_delta->target_rid, &delta->grp_mem_info); 158 break; 159 case SAM_DELTA_ALIAS_INFO: 160 display_alias_info(hdr_delta->target_rid, &delta->alias_info); 161 break; 162 case SAM_DELTA_ALIAS_MEM: 163 display_alias_mem(hdr_delta->target_rid, &delta->als_mem_info); 164 break; 165 case SAM_DELTA_DOMAIN_INFO: 166 display_domain_info(&delta->domain_info); 167 break; 168 case SAM_DELTA_GROUP_INFO: 169 display_group_info(hdr_delta->target_rid, &delta->group_info); 170 break; 171 /* The following types are recognised but not handled */ 172 case SAM_DELTA_RENAME_GROUP: 173 d_printf("SAM_DELTA_RENAME_GROUP not handled\n"); 174 break; 175 case SAM_DELTA_RENAME_USER: 176 d_printf("SAM_DELTA_RENAME_USER not handled\n"); 177 break; 178 case SAM_DELTA_RENAME_ALIAS: 179 d_printf("SAM_DELTA_RENAME_ALIAS not handled\n"); 180 break; 181 case SAM_DELTA_POLICY_INFO: 182 d_printf("SAM_DELTA_POLICY_INFO not handled\n"); 183 break; 184 case SAM_DELTA_TRUST_DOMS: 185 d_printf("SAM_DELTA_TRUST_DOMS not handled\n"); 186 break; 187 case SAM_DELTA_PRIVS_INFO: 188 d_printf("SAM_DELTA_PRIVS_INFO not handled\n"); 189 break; 190 case SAM_DELTA_SECRET_INFO: 191 d_printf("SAM_DELTA_SECRET_INFO not handled\n"); 192 break; 193 case SAM_DELTA_DELETE_GROUP: 194 d_printf("SAM_DELTA_DELETE_GROUP not handled\n"); 195 break; 196 case SAM_DELTA_DELETE_USER: 197 d_printf("SAM_DELTA_DELETE_USER not handled\n"); 198 break; 199 case SAM_DELTA_MODIFIED_COUNT: 200 d_printf("SAM_DELTA_MODIFIED_COUNT not handled\n"); 201 break; 202 default: 203 d_printf("Unknown delta record type %d\n", hdr_delta->type); 204 break; 205 } 206} 207 208 209static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds) 210{ 211 unsigned sync_context = 0; 212 NTSTATUS result; 213 int i; 214 TALLOC_CTX *mem_ctx; 215 SAM_DELTA_HDR *hdr_deltas; 216 SAM_DELTA_CTR *deltas; 217 uint32 num_deltas; 218 219 if (!(mem_ctx = talloc_init("dump_database"))) { 220 return; 221 } 222 223 switch( db_type ) { 224 case SAM_DATABASE_DOMAIN: 225 d_printf("Dumping DOMAIN database\n"); 226 break; 227 case SAM_DATABASE_BUILTIN: 228 d_printf("Dumping BUILTIN database\n"); 229 break; 230 case SAM_DATABASE_PRIVS: 231 d_printf("Dumping PRIVS databases\n"); 232 break; 233 default: 234 d_printf("Dumping unknown database type %u\n", db_type ); 235 break; 236 } 237 238 do { 239 result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, db_type, 240 sync_context, 241 &num_deltas, &hdr_deltas, &deltas); 242 if (NT_STATUS_IS_ERR(result)) 243 break; 244 245 clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), ret_creds); 246 for (i = 0; i < num_deltas; i++) { 247 display_sam_entry(&hdr_deltas[i], &deltas[i]); 248 } 249 sync_context += 1; 250 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); 251 252 talloc_destroy(mem_ctx); 253} 254 255/* dump sam database via samsync rpc calls */ 256NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid, 257 const char *domain_name, 258 struct cli_state *cli, TALLOC_CTX *mem_ctx, 259 int argc, const char **argv) 260{ 261 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; 262 uchar trust_password[16]; 263 DOM_CRED ret_creds; 264 uint32 sec_channel; 265 266 ZERO_STRUCT(ret_creds); 267 268 fstrcpy(cli->domain, domain_name); 269 270 if (!secrets_fetch_trust_account_password(domain_name, 271 trust_password, 272 NULL, &sec_channel)) { 273 DEBUG(0,("Could not fetch trust account password\n")); 274 goto fail; 275 } 276 277 if (!NT_STATUS_IS_OK(nt_status = cli_nt_establish_netlogon(cli, sec_channel, 278 trust_password))) { 279 DEBUG(0,("Error connecting to NETLOGON pipe\n")); 280 goto fail; 281 } 282 283 dump_database(cli, SAM_DATABASE_DOMAIN, &ret_creds); 284 dump_database(cli, SAM_DATABASE_BUILTIN, &ret_creds); 285 dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); 286 287 nt_status = NT_STATUS_OK; 288 289fail: 290 cli_nt_session_close(cli); 291 return nt_status; 292} 293 294/* Convert a SAM_ACCOUNT_DELTA to a SAM_ACCOUNT. */ 295#define STRING_CHANGED (old_string && !new_string) ||\ 296 (!old_string && new_string) ||\ 297 (old_string && new_string && (strcmp(old_string, new_string) != 0)) 298 299static NTSTATUS 300sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta) 301{ 302 const char *old_string, *new_string; 303 time_t unix_time, stored_time; 304 uchar lm_passwd[16], nt_passwd[16]; 305 static uchar zero_buf[16]; 306 307 /* Username, fullname, home dir, dir drive, logon script, acct 308 desc, workstations, profile. */ 309 310 if (delta->hdr_acct_name.buffer) { 311 old_string = pdb_get_nt_username(account); 312 new_string = unistr2_static(&delta->uni_acct_name); 313 314 if (STRING_CHANGED) { 315 pdb_set_nt_username(account, new_string, PDB_CHANGED); 316 317 } 318 319 /* Unix username is the same - for sanity */ 320 old_string = pdb_get_username( account ); 321 if (STRING_CHANGED) { 322 pdb_set_username(account, new_string, PDB_CHANGED); 323 } 324 } 325 326 if (delta->hdr_full_name.buffer) { 327 old_string = pdb_get_fullname(account); 328 new_string = unistr2_static(&delta->uni_full_name); 329 330 if (STRING_CHANGED) 331 pdb_set_fullname(account, new_string, PDB_CHANGED); 332 } 333 334 if (delta->hdr_home_dir.buffer) { 335 old_string = pdb_get_homedir(account); 336 new_string = unistr2_static(&delta->uni_home_dir); 337 338 if (STRING_CHANGED) 339 pdb_set_homedir(account, new_string, PDB_CHANGED); 340 } 341 342 if (delta->hdr_dir_drive.buffer) { 343 old_string = pdb_get_dir_drive(account); 344 new_string = unistr2_static(&delta->uni_dir_drive); 345 346 if (STRING_CHANGED) 347 pdb_set_dir_drive(account, new_string, PDB_CHANGED); 348 } 349 350 if (delta->hdr_logon_script.buffer) { 351 old_string = pdb_get_logon_script(account); 352 new_string = unistr2_static(&delta->uni_logon_script); 353 354 if (STRING_CHANGED) 355 pdb_set_logon_script(account, new_string, PDB_CHANGED); 356 } 357 358 if (delta->hdr_acct_desc.buffer) { 359 old_string = pdb_get_acct_desc(account); 360 new_string = unistr2_static(&delta->uni_acct_desc); 361 362 if (STRING_CHANGED) 363 pdb_set_acct_desc(account, new_string, PDB_CHANGED); 364 } 365 366 if (delta->hdr_workstations.buffer) { 367 old_string = pdb_get_workstations(account); 368 new_string = unistr2_static(&delta->uni_workstations); 369 370 if (STRING_CHANGED) 371 pdb_set_workstations(account, new_string, PDB_CHANGED); 372 } 373 374 if (delta->hdr_profile.buffer) { 375 old_string = pdb_get_profile_path(account); 376 new_string = unistr2_static(&delta->uni_profile); 377 378 if (STRING_CHANGED) 379 pdb_set_profile_path(account, new_string, PDB_CHANGED); 380 } 381 382 if (delta->hdr_parameters.buffer) { 383 DATA_BLOB mung; 384 old_string = pdb_get_munged_dial(account); 385 mung.length = delta->hdr_parameters.uni_str_len; 386 mung.data = (uint8 *) delta->uni_parameters.buffer; 387 new_string = (mung.length == 0) ? NULL : base64_encode_data_blob(mung); 388 389 if (STRING_CHANGED) 390 pdb_set_munged_dial(account, new_string, PDB_CHANGED); 391 } 392 393 /* User and group sid */ 394 if (pdb_get_user_rid(account) != delta->user_rid) 395 pdb_set_user_sid_from_rid(account, delta->user_rid, PDB_CHANGED); 396 if (pdb_get_group_rid(account) != delta->group_rid) 397 pdb_set_group_sid_from_rid(account, delta->group_rid, PDB_CHANGED); 398 399 /* Logon and password information */ 400 if (!nt_time_is_zero(&delta->logon_time)) { 401 unix_time = nt_time_to_unix(&delta->logon_time); 402 stored_time = pdb_get_logon_time(account); 403 if (stored_time != unix_time) 404 pdb_set_logon_time(account, unix_time, PDB_CHANGED); 405 } 406 407 if (!nt_time_is_zero(&delta->logoff_time)) { 408 unix_time = nt_time_to_unix(&delta->logoff_time); 409 stored_time = pdb_get_logoff_time(account); 410 if (stored_time != unix_time) 411 pdb_set_logoff_time(account, unix_time,PDB_CHANGED); 412 } 413 414 /* Logon Divs */ 415 if (pdb_get_logon_divs(account) != delta->logon_divs) 416 pdb_set_logon_divs(account, delta->logon_divs, PDB_CHANGED); 417 418 /* Max Logon Hours */ 419 if (delta->unknown1 != pdb_get_unknown_6(account)) { 420 pdb_set_unknown_6(account, delta->unknown1, PDB_CHANGED); 421 } 422 423 /* Logon Hours Len */ 424 if (delta->buf_logon_hrs.buf_len != pdb_get_hours_len(account)) { 425 pdb_set_hours_len(account, delta->buf_logon_hrs.buf_len, PDB_CHANGED); 426 } 427 428 /* Logon Hours */ 429 if (delta->buf_logon_hrs.buffer) { 430 pstring old, new; 431 pdb_sethexhours(old, pdb_get_hours(account)); 432 pdb_sethexhours(new, (const char *)delta->buf_logon_hrs.buffer); 433 if (!strequal(old, new)) 434 pdb_set_hours(account, (const char *)delta->buf_logon_hrs.buffer, PDB_CHANGED); 435 } 436 437 if (pdb_get_bad_password_count(account) != delta->bad_pwd_count) 438 pdb_set_bad_password_count(account, delta->bad_pwd_count, PDB_CHANGED); 439 440 if (pdb_get_logon_count(account) != delta->logon_count) 441 pdb_set_logon_count(account, delta->logon_count, PDB_CHANGED); 442 443 if (!nt_time_is_zero(&delta->pwd_last_set_time)) { 444 unix_time = nt_time_to_unix(&delta->pwd_last_set_time); 445 stored_time = pdb_get_pass_last_set_time(account); 446 if (stored_time != unix_time) 447 pdb_set_pass_last_set_time(account, unix_time, PDB_CHANGED); 448 } else { 449 /* no last set time, make it now */ 450 pdb_set_pass_last_set_time(account, time(NULL), PDB_CHANGED); 451 } 452 453#if 0 454/* No kickoff time in the delta? */ 455 if (!nt_time_is_zero(&delta->kickoff_time)) { 456 unix_time = nt_time_to_unix(&delta->kickoff_time); 457 stored_time = pdb_get_kickoff_time(account); 458 if (stored_time != unix_time) 459 pdb_set_kickoff_time(account, unix_time, PDB_CHANGED); 460 } 461#endif 462 463 /* Decode hashes from password hash 464 Note that win2000 may send us all zeros for the hashes if it doesn't 465 think this channel is secure enough - don't set the passwords at all 466 in that case 467 */ 468 if (memcmp(delta->pass.buf_lm_pwd, zero_buf, 16) != 0) { 469 sam_pwd_hash(delta->user_rid, delta->pass.buf_lm_pwd, lm_passwd, 0); 470 pdb_set_lanman_passwd(account, lm_passwd, PDB_CHANGED); 471 } 472 473 if (memcmp(delta->pass.buf_nt_pwd, zero_buf, 16) != 0) { 474 sam_pwd_hash(delta->user_rid, delta->pass.buf_nt_pwd, nt_passwd, 0); 475 pdb_set_nt_passwd(account, nt_passwd, PDB_CHANGED); 476 } 477 478 /* TODO: account expiry time */ 479 480 if (pdb_get_acct_ctrl(account) != delta->acb_info) 481 pdb_set_acct_ctrl(account, delta->acb_info, PDB_CHANGED); 482 483 pdb_set_domain(account, lp_workgroup(), PDB_CHANGED); 484 485 return NT_STATUS_OK; 486} 487 488static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) 489{ 490 NTSTATUS nt_ret; 491 fstring account; 492 pstring add_script; 493 SAM_ACCOUNT *sam_account=NULL; 494 GROUP_MAP map; 495 struct group *grp; 496 DOM_SID user_sid; 497 DOM_SID group_sid; 498 struct passwd *passwd; 499 fstring sid_string; 500 501 fstrcpy(account, unistr2_static(&delta->uni_acct_name)); 502 d_printf("Creating account: %s\n", account); 503 504 if (!NT_STATUS_IS_OK(nt_ret = pdb_init_sam(&sam_account))) 505 return nt_ret; 506 507 if (!(passwd = Get_Pwnam(account))) { 508 /* Create appropriate user */ 509 if (delta->acb_info & ACB_NORMAL) { 510 pstrcpy(add_script, lp_adduser_script()); 511 } else if ( (delta->acb_info & ACB_WSTRUST) || 512 (delta->acb_info & ACB_SVRTRUST) || 513 (delta->acb_info & ACB_DOMTRUST) ) { 514 pstrcpy(add_script, lp_addmachine_script()); 515 } else { 516 DEBUG(1, ("Unknown user type: %s\n", 517 pdb_encode_acct_ctrl(delta->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN))); 518 nt_ret = NT_STATUS_UNSUCCESSFUL; 519 goto done; 520 } 521 if (*add_script) { 522 int add_ret; 523 all_string_sub(add_script, "%u", account, 524 sizeof(account)); 525 add_ret = smbrun(add_script,NULL); 526 DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' " 527 "gave %d\n", add_script, add_ret)); 528 } else { 529 DEBUG(8,("fetch_account_info: no add user/machine script. Asking winbindd\n")); 530 531 /* don't need a RID allocated since the user already has a SID */ 532 if ( !winbind_create_user( account, NULL ) ) 533 DEBUG(4,("fetch_account_info: winbind_create_user() failed\n")); 534 } 535 536 /* try and find the possible unix account again */ 537 if ( !(passwd = Get_Pwnam(account)) ) { 538 d_printf("Could not create posix account info for '%s'\n", account); 539 nt_ret = NT_STATUS_NO_SUCH_USER; 540 goto done; 541 } 542 } 543 544 sid_copy(&user_sid, get_global_sam_sid()); 545 sid_append_rid(&user_sid, delta->user_rid); 546 547 DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n", sid_to_string(sid_string, &user_sid), account)); 548 if (!pdb_getsampwsid(sam_account, &user_sid)) { 549 sam_account_from_delta(sam_account, delta); 550 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n", 551 sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account))); 552 if (!pdb_add_sam_account(sam_account)) { 553 DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n", 554 account)); 555 return NT_STATUS_ACCESS_DENIED; 556 } 557 } else { 558 sam_account_from_delta(sam_account, delta); 559 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n", 560 sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account))); 561 if (!pdb_update_sam_account(sam_account)) { 562 DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n", 563 account)); 564 pdb_free_sam(&sam_account); 565 return NT_STATUS_ACCESS_DENIED; 566 } 567 } 568 569 group_sid = *pdb_get_group_sid(sam_account); 570 571 if (!pdb_getgrsid(&map, group_sid)) { 572 DEBUG(0, ("Primary group of %s has no mapping!\n", 573 pdb_get_username(sam_account))); 574 } else { 575 if (map.gid != passwd->pw_gid) { 576 if (!(grp = getgrgid(map.gid))) { 577 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n", 578 (unsigned long)map.gid, pdb_get_username(sam_account), sid_string_static(&group_sid))); 579 } else { 580 smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account)); 581 } 582 } 583 } 584 585 if ( !passwd ) { 586 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n", 587 pdb_get_username(sam_account))); 588 } 589 590 done: 591 pdb_free_sam(&sam_account); 592 return nt_ret; 593} 594 595static NTSTATUS 596fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta) 597{ 598 fstring name; 599 fstring comment; 600 struct group *grp = NULL; 601 DOM_SID group_sid; 602 fstring sid_string; 603 GROUP_MAP map; 604 BOOL insert = True; 605 606 unistr2_to_ascii(name, &delta->uni_grp_name, sizeof(name)-1); 607 unistr2_to_ascii(comment, &delta->uni_grp_desc, sizeof(comment)-1); 608 609 /* add the group to the mapping table */ 610 sid_copy(&group_sid, get_global_sam_sid()); 611 sid_append_rid(&group_sid, rid); 612 sid_to_string(sid_string, &group_sid); 613 614 if (pdb_getgrsid(&map, group_sid)) { 615 if ( map.gid != -1 ) 616 grp = getgrgid(map.gid); 617 insert = False; 618 } 619 620 if (grp == NULL) { 621 gid_t gid; 622 623 /* No group found from mapping, find it from its name. */ 624 if ((grp = getgrnam(name)) == NULL) { 625 626 /* No appropriate group found, create one */ 627 628 d_printf("Creating unix group: '%s'\n", name); 629 630 if (smb_create_group(name, &gid) != 0) 631 return NT_STATUS_ACCESS_DENIED; 632 633 if ((grp = getgrnam(name)) == NULL) 634 return NT_STATUS_ACCESS_DENIED; 635 } 636 } 637 638 map.gid = grp->gr_gid; 639 map.sid = group_sid; 640 map.sid_name_use = SID_NAME_DOM_GRP; 641 fstrcpy(map.nt_name, name); 642 if (delta->hdr_grp_desc.buffer) { 643 fstrcpy(map.comment, comment); 644 } else { 645 fstrcpy(map.comment, ""); 646 } 647 648 if (insert) 649 pdb_add_group_mapping_entry(&map); 650 else 651 pdb_update_group_mapping_entry(&map); 652 653 return NT_STATUS_OK; 654} 655 656static NTSTATUS 657fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta) 658{ 659 int i; 660 TALLOC_CTX *t = NULL; 661 char **nt_members = NULL; 662 char **unix_members; 663 DOM_SID group_sid; 664 GROUP_MAP map; 665 struct group *grp; 666 667 if (delta->num_members == 0) { 668 return NT_STATUS_OK; 669 } 670 671 sid_copy(&group_sid, get_global_sam_sid()); 672 sid_append_rid(&group_sid, rid); 673 674 if (!get_domain_group_from_sid(group_sid, &map)) { 675 DEBUG(0, ("Could not find global group %d\n", rid)); 676 return NT_STATUS_NO_SUCH_GROUP; 677 } 678 679 if (!(grp = getgrgid(map.gid))) { 680 DEBUG(0, ("Could not find unix group %lu\n", (unsigned long)map.gid)); 681 return NT_STATUS_NO_SUCH_GROUP; 682 } 683 684 d_printf("Group members of %s: ", grp->gr_name); 685 686 if (!(t = talloc_init("fetch_group_mem_info"))) { 687 DEBUG(0, ("could not talloc_init\n")); 688 return NT_STATUS_NO_MEMORY; 689 } 690 691 nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members); 692 693 for (i=0; i<delta->num_members; i++) { 694 NTSTATUS nt_status; 695 SAM_ACCOUNT *member = NULL; 696 DOM_SID member_sid; 697 698 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) { 699 talloc_destroy(t); 700 return nt_status; 701 } 702 703 sid_copy(&member_sid, get_global_sam_sid()); 704 sid_append_rid(&member_sid, delta->rids[i]); 705 706 if (!pdb_getsampwsid(member, &member_sid)) { 707 DEBUG(1, ("Found bogus group member: %d (member_sid=%s group=%s)\n", 708 delta->rids[i], sid_string_static(&member_sid), grp->gr_name)); 709 pdb_free_sam(&member); 710 continue; 711 } 712 713 if (pdb_get_group_rid(member) == rid) { 714 d_printf("%s(primary),", pdb_get_username(member)); 715 pdb_free_sam(&member); 716 continue; 717 } 718 719 d_printf("%s,", pdb_get_username(member)); 720 nt_members[i] = talloc_strdup(t, pdb_get_username(member)); 721 pdb_free_sam(&member); 722 } 723 724 d_printf("\n"); 725 726 unix_members = grp->gr_mem; 727 728 while (*unix_members) { 729 BOOL is_nt_member = False; 730 for (i=0; i<delta->num_members; i++) { 731 if (nt_members[i] == NULL) { 732 /* This was a primary group */ 733 continue; 734 } 735 736 if (strcmp(*unix_members, nt_members[i]) == 0) { 737 is_nt_member = True; 738 break; 739 } 740 } 741 if (!is_nt_member) { 742 /* We look at a unix group member that is not 743 an nt group member. So, remove it. NT is 744 boss here. */ 745 smb_delete_user_group(grp->gr_name, *unix_members); 746 } 747 unix_members += 1; 748 } 749 750 for (i=0; i<delta->num_members; i++) { 751 BOOL is_unix_member = False; 752 753 if (nt_members[i] == NULL) { 754 /* This was the primary group */ 755 continue; 756 } 757 758 unix_members = grp->gr_mem; 759 760 while (*unix_members) { 761 if (strcmp(*unix_members, nt_members[i]) == 0) { 762 is_unix_member = True; 763 break; 764 } 765 unix_members += 1; 766 } 767 768 if (!is_unix_member) { 769 /* We look at a nt group member that is not a 770 unix group member currently. So, add the nt 771 group member. */ 772 smb_add_user_group(grp->gr_name, nt_members[i]); 773 } 774 } 775 776 talloc_destroy(t); 777 return NT_STATUS_OK; 778} 779 780static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta, 781 DOM_SID dom_sid) 782{ 783 fstring name; 784 fstring comment; 785 struct group *grp = NULL; 786 DOM_SID alias_sid; 787 fstring sid_string; 788 GROUP_MAP map; 789 BOOL insert = True; 790 791 unistr2_to_ascii(name, &delta->uni_als_name, sizeof(name)-1); 792 unistr2_to_ascii(comment, &delta->uni_als_desc, sizeof(comment)-1); 793 794 /* Find out whether the group is already mapped */ 795 sid_copy(&alias_sid, &dom_sid); 796 sid_append_rid(&alias_sid, rid); 797 sid_to_string(sid_string, &alias_sid); 798 799 if (pdb_getgrsid(&map, alias_sid)) { 800 grp = getgrgid(map.gid); 801 insert = False; 802 } 803 804 if (grp == NULL) { 805 gid_t gid; 806 807 /* No group found from mapping, find it from its name. */ 808 if ((grp = getgrnam(name)) == NULL) { 809 /* No appropriate group found, create one */ 810 d_printf("Creating unix group: '%s'\n", name); 811 if (smb_create_group(name, &gid) != 0) 812 return NT_STATUS_ACCESS_DENIED; 813 if ((grp = getgrgid(gid)) == NULL) 814 return NT_STATUS_ACCESS_DENIED; 815 } 816 } 817 818 map.gid = grp->gr_gid; 819 map.sid = alias_sid; 820 821 if (sid_equal(&dom_sid, &global_sid_Builtin)) 822 map.sid_name_use = SID_NAME_WKN_GRP; 823 else 824 map.sid_name_use = SID_NAME_ALIAS; 825 826 fstrcpy(map.nt_name, name); 827 fstrcpy(map.comment, comment); 828 829 if (insert) 830 pdb_add_group_mapping_entry(&map); 831 else 832 pdb_update_group_mapping_entry(&map); 833 834 return NT_STATUS_OK; 835} 836 837static NTSTATUS 838fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid) 839{ 840#if 0 /* 841 * commented out right now after talking to Volker. Can't 842 * do much with the membership but seemed a shame to waste 843 * somewhat working code. Needs testing because the membership 844 * that shows up surprises me. Also can't do much with groups 845 * in groups (e.g. Domain Admins being a member of Adminsitrators). 846 * --jerry 847 */ 848 849 int i; 850 TALLOC_CTX *t = NULL; 851 char **nt_members = NULL; 852 char **unix_members; 853 DOM_SID group_sid; 854 GROUP_MAP map; 855 struct group *grp; 856 enum SID_NAME_USE sid_type; 857 858 if (delta->num_members == 0) { 859 return NT_STATUS_OK; 860 } 861 862 sid_copy(&group_sid, &dom_sid); 863 sid_append_rid(&group_sid, rid); 864 865 if (sid_equal(&dom_sid, &global_sid_Builtin)) { 866 sid_type = SID_NAME_WKN_GRP; 867 if (!get_builtin_group_from_sid(&group_sid, &map, False)) { 868 DEBUG(0, ("Could not find builtin group %s\n", sid_string_static(&group_sid))); 869 return NT_STATUS_NO_SUCH_GROUP; 870 } 871 } else { 872 sid_type = SID_NAME_ALIAS; 873 if (!get_local_group_from_sid(&group_sid, &map, False)) { 874 DEBUG(0, ("Could not find local group %s\n", sid_string_static(&group_sid))); 875 return NT_STATUS_NO_SUCH_GROUP; 876 } 877 } 878 879 if (!(grp = getgrgid(map.gid))) { 880 DEBUG(0, ("Could not find unix group %d\n", map.gid)); 881 return NT_STATUS_NO_SUCH_GROUP; 882 } 883 884 d_printf("Group members of %s: ", grp->gr_name); 885 886 if (!(t = talloc_init("fetch_group_mem_info"))) { 887 DEBUG(0, ("could not talloc_init\n")); 888 return NT_STATUS_NO_MEMORY; 889 } 890 891 nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members); 892 893 for (i=0; i<delta->num_members; i++) { 894 NTSTATUS nt_status; 895 SAM_ACCOUNT *member = NULL; 896 DOM_SID member_sid; 897 898 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) { 899 talloc_destroy(t); 900 return nt_status; 901 } 902 903 sid_copy(&member_sid, &delta->sids[i].sid); 904 905 if (!pdb_getsampwsid(member, &member_sid)) { 906 DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n", 907 sid_string_static(&member_sid), grp->gr_name)); 908 pdb_free_sam(&member); 909 continue; 910 } 911 912 if (pdb_get_group_rid(member) == rid) { 913 d_printf("%s(primary),", pdb_get_username(member)); 914 pdb_free_sam(&member); 915 continue; 916 } 917 918 d_printf("%s,", pdb_get_username(member)); 919 nt_members[i] = talloc_strdup(t, pdb_get_username(member)); 920 pdb_free_sam(&member); 921 } 922 923 d_printf("\n"); 924 925 unix_members = grp->gr_mem; 926 927 while (*unix_members) { 928 BOOL is_nt_member = False; 929 for (i=0; i<delta->num_members; i++) { 930 if (nt_members[i] == NULL) { 931 /* This was a primary group */ 932 continue; 933 } 934 935 if (strcmp(*unix_members, nt_members[i]) == 0) { 936 is_nt_member = True; 937 break; 938 } 939 } 940 if (!is_nt_member) { 941 /* We look at a unix group member that is not 942 an nt group member. So, remove it. NT is 943 boss here. */ 944 smb_delete_user_group(grp->gr_name, *unix_members); 945 } 946 unix_members += 1; 947 } 948 949 for (i=0; i<delta->num_members; i++) { 950 BOOL is_unix_member = False; 951 952 if (nt_members[i] == NULL) { 953 /* This was the primary group */ 954 continue; 955 } 956 957 unix_members = grp->gr_mem; 958 959 while (*unix_members) { 960 if (strcmp(*unix_members, nt_members[i]) == 0) { 961 is_unix_member = True; 962 break; 963 } 964 unix_members += 1; 965 } 966 967 if (!is_unix_member) { 968 /* We look at a nt group member that is not a 969 unix group member currently. So, add the nt 970 group member. */ 971 smb_add_user_group(grp->gr_name, nt_members[i]); 972 } 973 } 974 975 talloc_destroy(t); 976 977#endif /* end of fetch_alias_mem() */ 978 979 return NT_STATUS_OK; 980} 981 982static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta) 983{ 984 time_t u_max_age, u_min_age, u_logout, u_lockoutreset, u_lockouttime; 985 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; 986 pstring domname; 987 988 u_max_age = nt_time_to_unix_abs((NTTIME *)&delta->max_pwd_age); 989 u_min_age = nt_time_to_unix_abs((NTTIME *)&delta->min_pwd_age); 990 u_logout = nt_time_to_unix_abs((NTTIME *)&delta->force_logoff); 991 u_lockoutreset = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.reset_count); 992 u_lockouttime = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.lockout_duration); 993 994 unistr2_to_ascii(domname, &delta->uni_dom_name, sizeof(domname) - 1); 995 996 /* we don't handle BUILTIN account policies */ 997 if (!strequal(domname, get_global_sam_name())) { 998 printf("skipping SAM_DOMAIN_INFO delta for '%s' (is not my domain)\n", domname); 999 return NT_STATUS_OK; 1000 } 1001 1002 1003 if (!account_policy_set(AP_PASSWORD_HISTORY, delta->pwd_history_len)) 1004 return nt_status; 1005 1006 if (!account_policy_set(AP_MIN_PASSWORD_LEN, delta->min_pwd_len)) 1007 return nt_status; 1008 1009 if (!account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)u_max_age)) 1010 return nt_status; 1011 1012 if (!account_policy_set(AP_MIN_PASSWORD_AGE, (uint32)u_min_age)) 1013 return nt_status; 1014 1015 if (!account_policy_set(AP_TIME_TO_LOGOUT, (uint32)u_logout)) 1016 return nt_status; 1017 1018 if (!account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout)) 1019 return nt_status; 1020 1021 if (!account_policy_set(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60)) 1022 return nt_status; 1023 1024 if (u_lockouttime != -1) 1025 u_lockouttime /= 60; 1026 1027 if (!account_policy_set(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime)) 1028 return nt_status; 1029 1030 if (!account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass)) 1031 return nt_status; 1032 1033 return NT_STATUS_OK; 1034} 1035 1036 1037static void 1038fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, 1039 DOM_SID dom_sid) 1040{ 1041 switch(hdr_delta->type) { 1042 case SAM_DELTA_ACCOUNT_INFO: 1043 fetch_account_info(hdr_delta->target_rid, 1044 &delta->account_info); 1045 break; 1046 case SAM_DELTA_GROUP_INFO: 1047 fetch_group_info(hdr_delta->target_rid, 1048 &delta->group_info); 1049 break; 1050 case SAM_DELTA_GROUP_MEM: 1051 fetch_group_mem_info(hdr_delta->target_rid, 1052 &delta->grp_mem_info); 1053 break; 1054 case SAM_DELTA_ALIAS_INFO: 1055 fetch_alias_info(hdr_delta->target_rid, 1056 &delta->alias_info, dom_sid); 1057 break; 1058 case SAM_DELTA_ALIAS_MEM: 1059 fetch_alias_mem(hdr_delta->target_rid, 1060 &delta->als_mem_info, dom_sid); 1061 break; 1062 case SAM_DELTA_DOMAIN_INFO: 1063 fetch_domain_info(hdr_delta->target_rid, 1064 &delta->domain_info); 1065 break; 1066 /* The following types are recognised but not handled */ 1067 case SAM_DELTA_RENAME_GROUP: 1068 d_printf("SAM_DELTA_RENAME_GROUP not handled\n"); 1069 break; 1070 case SAM_DELTA_RENAME_USER: 1071 d_printf("SAM_DELTA_RENAME_USER not handled\n"); 1072 break; 1073 case SAM_DELTA_RENAME_ALIAS: 1074 d_printf("SAM_DELTA_RENAME_ALIAS not handled\n"); 1075 break; 1076 case SAM_DELTA_POLICY_INFO: 1077 d_printf("SAM_DELTA_POLICY_INFO not handled\n"); 1078 break; 1079 case SAM_DELTA_TRUST_DOMS: 1080 d_printf("SAM_DELTA_TRUST_DOMS not handled\n"); 1081 break; 1082 case SAM_DELTA_PRIVS_INFO: 1083 d_printf("SAM_DELTA_PRIVS_INFO not handled\n"); 1084 break; 1085 case SAM_DELTA_SECRET_INFO: 1086 d_printf("SAM_DELTA_SECRET_INFO not handled\n"); 1087 break; 1088 case SAM_DELTA_DELETE_GROUP: 1089 d_printf("SAM_DELTA_DELETE_GROUP not handled\n"); 1090 break; 1091 case SAM_DELTA_DELETE_USER: 1092 d_printf("SAM_DELTA_DELETE_USER not handled\n"); 1093 break; 1094 case SAM_DELTA_MODIFIED_COUNT: 1095 d_printf("SAM_DELTA_MODIFIED_COUNT not handled\n"); 1096 break; 1097 default: 1098 d_printf("Unknown delta record type %d\n", hdr_delta->type); 1099 break; 1100 } 1101} 1102 1103static NTSTATUS 1104fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds, 1105 DOM_SID dom_sid) 1106{ 1107 unsigned sync_context = 0; 1108 NTSTATUS result; 1109 int i; 1110 TALLOC_CTX *mem_ctx; 1111 SAM_DELTA_HDR *hdr_deltas; 1112 SAM_DELTA_CTR *deltas; 1113 uint32 num_deltas; 1114 1115 if (!(mem_ctx = talloc_init("fetch_database"))) 1116 return NT_STATUS_NO_MEMORY; 1117 1118 switch( db_type ) { 1119 case SAM_DATABASE_DOMAIN: 1120 d_printf("Fetching DOMAIN database\n"); 1121 break; 1122 case SAM_DATABASE_BUILTIN: 1123 d_printf("Fetching BUILTIN database\n"); 1124 break; 1125 case SAM_DATABASE_PRIVS: 1126 d_printf("Fetching PRIVS databases\n"); 1127 break; 1128 default: 1129 d_printf("Fetching unknown database type %u\n", db_type ); 1130 break; 1131 } 1132 1133 do { 1134 result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, 1135 db_type, sync_context, 1136 &num_deltas, 1137 &hdr_deltas, &deltas); 1138 1139 if (NT_STATUS_IS_OK(result) || 1140 NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) { 1141 1142 clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), 1143 ret_creds); 1144 1145 for (i = 0; i < num_deltas; i++) { 1146 fetch_sam_entry(&hdr_deltas[i], &deltas[i], dom_sid); 1147 } 1148 } else 1149 return result; 1150 1151 sync_context += 1; 1152 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); 1153 1154 talloc_destroy(mem_ctx); 1155 1156 return result; 1157} 1158 1159/* dump sam database via samsync rpc calls */ 1160NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, 1161 const char *domain_name, 1162 struct cli_state *cli, TALLOC_CTX *mem_ctx, 1163 int argc, const char **argv) 1164{ 1165 NTSTATUS result; 1166 uchar trust_password[16]; 1167 DOM_CRED ret_creds; 1168 fstring my_dom_sid_str; 1169 fstring rem_dom_sid_str; 1170 uint32 sec_channel; 1171 1172 ZERO_STRUCT(ret_creds); 1173 1174 if (!sid_equal(domain_sid, get_global_sam_sid())) { 1175 d_printf("Cannot import users from %s at this time, " 1176 "as the current domain:\n\t%s: %s\nconflicts " 1177 "with the remote domain\n\t%s: %s\n" 1178 "Perhaps you need to set: \n\n\tsecurity=user\n\tworkgroup=%s\n\n in your smb.conf?\n", 1179 domain_name, 1180 get_global_sam_name(), sid_to_string(my_dom_sid_str, 1181 get_global_sam_sid()), 1182 domain_name, sid_to_string(rem_dom_sid_str, domain_sid), 1183 domain_name); 1184 return NT_STATUS_UNSUCCESSFUL; 1185 } 1186 1187 fstrcpy(cli->domain, domain_name); 1188 1189 if (!secrets_fetch_trust_account_password(domain_name, 1190 trust_password, NULL, 1191 &sec_channel)) { 1192 result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; 1193 d_printf("Could not retrieve domain trust secret\n"); 1194 goto fail; 1195 } 1196 1197 result = cli_nt_establish_netlogon(cli, sec_channel, trust_password); 1198 1199 if (!NT_STATUS_IS_OK(result)) { 1200 d_printf("Failed to setup BDC creds\n"); 1201 goto fail; 1202 } 1203 1204 result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, *domain_sid); 1205 1206 if (!NT_STATUS_IS_OK(result)) { 1207 d_printf("Failed to fetch domain database: %s\n", 1208 nt_errstr(result)); 1209 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) 1210 d_printf("Perhaps %s is a Windows 2000 native mode " 1211 "domain?\n", domain_name); 1212 goto fail; 1213 } 1214 1215 result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, 1216 global_sid_Builtin); 1217 1218 if (!NT_STATUS_IS_OK(result)) { 1219 d_printf("Failed to fetch builtin database: %s\n", 1220 nt_errstr(result)); 1221 goto fail; 1222 } 1223 1224 /* Currently we crash on PRIVS somewhere in unmarshalling */ 1225 /* Dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); */ 1226 1227fail: 1228 return result; 1229} 1230