1#!/usr/bin/perl 2# Bootstrap Samba and run a number of tests against it. 3# Copyright (C) 2005-2007 Jelmer Vernooij <jelmer@samba.org> 4# Published under the GNU GPL, v3 or later. 5 6# NOTE: Refer to the README for more details about the various testenvs, 7# and tips about adding new testenvs. 8 9package Samba4; 10 11use strict; 12use Cwd qw(abs_path); 13use FindBin qw($RealBin); 14use POSIX; 15use SocketWrapper; 16use target::Samba; 17use target::Samba3; 18use Archive::Tar; 19use File::Path 'make_path'; 20 21sub new($$$$$) { 22 my ($classname, $bindir, $srcdir, $server_maxtime) = @_; 23 24 my $self = { 25 vars => {}, 26 bindir => $bindir, 27 srcdir => $srcdir, 28 server_maxtime => $server_maxtime, 29 target3 => new Samba3($bindir, $srcdir, $server_maxtime) 30 }; 31 bless $self; 32 return $self; 33} 34 35sub scriptdir_path($$) { 36 my ($self, $path) = @_; 37 return "$self->{srcdir}/source4/scripting/$path"; 38} 39 40sub check_or_start($$$) 41{ 42 my ($self, $env_vars, $process_model) = @_; 43 my $STDIN_READER; 44 45 my $env_ok = $self->check_env($env_vars); 46 if ($env_ok) { 47 return $env_vars->{SAMBA_PID}; 48 } elsif (defined($env_vars->{SAMBA_PID})) { 49 warn("SAMBA PID $env_vars->{SAMBA_PID} is not running (died)"); 50 return undef; 51 } 52 53 # use a pipe for stdin in the child processes. This allows 54 # those processes to monitor the pipe for EOF to ensure they 55 # exit when the test script exits 56 pipe($STDIN_READER, $env_vars->{STDIN_PIPE}); 57 58 # build up the command to run samba 59 my @preargs = (); 60 my @optargs = (); 61 if (defined($ENV{SAMBA_OPTIONS})) { 62 @optargs = split(/ /, $ENV{SAMBA_OPTIONS}); 63 } 64 if(defined($ENV{SAMBA_VALGRIND})) { 65 @preargs = split(/ /,$ENV{SAMBA_VALGRIND}); 66 } 67 68 if (defined($process_model)) { 69 push @optargs, ("-M", $process_model); 70 } 71 my $binary = Samba::bindir_path($self, "samba"); 72 my @full_cmd = (@preargs, $binary, "-i", 73 "--no-process-group", "--maximum-runtime=$self->{server_maxtime}", 74 $env_vars->{CONFIGURATION}, @optargs); 75 76 # the samba process takes some additional env variables (compared to s3) 77 my $samba_envs = Samba::get_env_for_process("samba", $env_vars); 78 $samba_envs->{RESOLV_CONF} = $env_vars->{RESOLV_CONF}; 79 $samba_envs->{UID_WRAPPER} = "1"; 80 if (defined($ENV{MITKRB5})) { 81 $samba_envs->{KRB5_KDC_PROFILE} = $env_vars->{MITKDC_CONFIG}; 82 } 83 84 # fork a child process and exec() samba 85 my $daemon_ctx = { 86 NAME => "samba", 87 BINARY_PATH => $binary, 88 FULL_CMD => [ @full_cmd ], 89 LOG_FILE => $env_vars->{SAMBA_TEST_LOG}, 90 TEE_STDOUT => 1, 91 ENV_VARS => $samba_envs, 92 }; 93 my $pid = Samba::fork_and_exec($self, $env_vars, $daemon_ctx, $STDIN_READER); 94 95 $env_vars->{SAMBA_PID} = $pid; 96 97 # close the parent's read-end of the pipe 98 close($STDIN_READER); 99 100 if ($self->wait_for_start($env_vars) != 0) { 101 warn("Samba $pid failed to start up"); 102 return undef; 103 } 104 105 return $pid; 106} 107 108sub wait_for_start($$) 109{ 110 my ($self, $testenv_vars) = @_; 111 my $count = 0; 112 my $ret = 0; 113 114 if (not $self->check_env($testenv_vars)) { 115 warn("unable to confirm Samba $testenv_vars->{SAMBA_PID} is running"); 116 return -1; 117 } 118 119 # This will return quickly when things are up, but be slow if we 120 # need to wait for (eg) SSL init 121 my $nmblookup = Samba::bindir_path($self, "nmblookup4"); 122 123 do { 124 $ret = system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{SERVER}"); 125 if ($ret != 0) { 126 sleep(1); 127 } else { 128 system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{SERVER}"); 129 system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}"); 130 system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}"); 131 system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}"); 132 system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}"); 133 system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{SERVER}"); 134 system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{SERVER}"); 135 system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}"); 136 system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}"); 137 system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}"); 138 system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}"); 139 } 140 $count++; 141 } while ($ret != 0 && $count < 20); 142 if ($count == 20) { 143 teardown_env($self, $testenv_vars); 144 warn("nbt not reachable after 20 retries\n"); 145 return -1; 146 } 147 148 # Ensure we have the first RID Set before we start tests. This makes the tests more reliable. 149 if ($testenv_vars->{SERVER_ROLE} eq "domain controller") { 150 print "waiting for working LDAP and a RID Set to be allocated\n"; 151 my $ldbsearch = Samba::bindir_path($self, "ldbsearch"); 152 my $count = 0; 153 my $base_dn = "DC=".join(",DC=", split(/\./, $testenv_vars->{REALM})); 154 155 my $search_dn = $base_dn; 156 if ($testenv_vars->{NETBIOSNAME} ne "RODC") { 157 # TODO currently no check for actual rIDAllocationPool 158 $search_dn = "cn=RID Set,cn=$testenv_vars->{NETBIOSNAME},ou=domain controllers,$base_dn"; 159 } 160 my $max_wait = 60; 161 162 # Add hosts file for name lookups 163 my $cmd = "NSS_WRAPPER_HOSTS='$testenv_vars->{NSS_WRAPPER_HOSTS}' "; 164 if (defined($testenv_vars->{RESOLV_WRAPPER_CONF})) { 165 $cmd .= "RESOLV_WRAPPER_CONF='$testenv_vars->{RESOLV_WRAPPER_CONF}' "; 166 } else { 167 $cmd .= "RESOLV_WRAPPER_HOSTS='$testenv_vars->{RESOLV_WRAPPER_HOSTS}' "; 168 } 169 $cmd .= "RESOLV_CONF='$testenv_vars->{RESOLV_CONF}' "; 170 171 $cmd .= "$ldbsearch "; 172 $cmd .= "$testenv_vars->{CONFIGURATION} "; 173 $cmd .= "-H ldap://$testenv_vars->{SERVER} "; 174 $cmd .= "-U$testenv_vars->{USERNAME}%$testenv_vars->{PASSWORD} "; 175 $cmd .= "-s base "; 176 $cmd .= "-b '$search_dn' "; 177 while (system("$cmd >/dev/null") != 0) { 178 $count++; 179 if ($count > $max_wait) { 180 teardown_env($self, $testenv_vars); 181 warn("Timed out ($max_wait sec) waiting for working LDAP and a RID Set to be allocated by $testenv_vars->{NETBIOSNAME} PID $testenv_vars->{SAMBA_PID}"); 182 return -1; 183 } 184 print "Waiting for working LDAP...\n"; 185 sleep(1); 186 } 187 } 188 189 my $wbinfo = Samba::bindir_path($self, "wbinfo"); 190 191 $count = 0; 192 do { 193 my $cmd = "NSS_WRAPPER_PASSWD=$testenv_vars->{NSS_WRAPPER_PASSWD} "; 194 $cmd .= "NSS_WRAPPER_GROUP=$testenv_vars->{NSS_WRAPPER_GROUP} "; 195 $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=$testenv_vars->{SELFTEST_WINBINDD_SOCKET_DIR} "; 196 $cmd .= "$wbinfo -P"; 197 $ret = system($cmd); 198 199 if ($ret != 0) { 200 sleep(1); 201 } 202 $count++; 203 } while ($ret != 0 && $count < 20); 204 if ($count == 20) { 205 teardown_env($self, $testenv_vars); 206 warn("winbind not reachable after 20 retries\n"); 207 return -1; 208 } 209 210 # Ensure we registered all our names 211 if ($testenv_vars->{SERVER_ROLE} eq "domain controller") { 212 my $max_wait = 120; 213 print "Waiting for dns_update_cache to be created.\n"; 214 $count = 0; 215 while (not -e "$testenv_vars->{PRIVATEDIR}/dns_update_cache") { 216 $count++; 217 if ($count > $max_wait) { 218 teardown_env($self, $testenv_vars); 219 warn("Timed out ($max_wait sec) waiting for dns_update_cache PID $testenv_vars->{SAMBA_PID}"); 220 return -1; 221 } 222 print "Waiting for dns_update_cache to be created...\n"; 223 sleep(1); 224 } 225 print "Waiting for dns_update_cache to be filled.\n"; 226 $count = 0; 227 while ((-s "$testenv_vars->{PRIVATEDIR}/dns_update_cache") == 0) { 228 $count++; 229 if ($count > $max_wait) { 230 teardown_env($self, $testenv_vars); 231 warn("Timed out ($max_wait sec) waiting for dns_update_cache PID $testenv_vars->{SAMBA_PID}"); 232 return -1; 233 } 234 print "Waiting for dns_update_cache to be filled...\n"; 235 sleep(1); 236 } 237 } 238 239 print $self->getlog_env($testenv_vars); 240 241 print "READY ($testenv_vars->{SAMBA_PID})\n"; 242 243 return 0 244} 245 246sub write_ldb_file($$$) 247{ 248 my ($self, $file, $ldif) = @_; 249 250 my $ldbadd = Samba::bindir_path($self, "ldbadd"); 251 open(LDIF, "|$ldbadd -H $file >/dev/null"); 252 print LDIF $ldif; 253 return(close(LDIF)); 254} 255 256sub add_wins_config($$) 257{ 258 my ($self, $privatedir) = @_; 259 my $client_ip = Samba::get_ipv4_addr("client"); 260 261 return $self->write_ldb_file("$privatedir/wins_config.ldb", " 262dn: name=TORTURE_11,CN=PARTNERS 263objectClass: wreplPartner 264name: TORTURE_11 265address: $client_ip 266pullInterval: 0 267pushChangeCount: 0 268type: 0x3 269"); 270} 271 272sub setup_dns_hub_internal($$$) 273{ 274 my ($self, $hostname, $prefix) = @_; 275 my $STDIN_READER; 276 277 unless(-d $prefix or make_path($prefix, 0777)) { 278 warn("Unable to create $prefix"); 279 return undef; 280 } 281 my $prefix_abs = abs_path($prefix); 282 283 die ("prefix=''") if $prefix_abs eq ""; 284 die ("prefix='/'") if $prefix_abs eq "/"; 285 286 unless (system("rm -rf $prefix_abs/*") == 0) { 287 warn("Unable to clean up"); 288 } 289 290 my $env = undef; 291 $env->{NETBIOSNAME} = $hostname; 292 293 $env->{SERVER_IP} = Samba::get_ipv4_addr($hostname); 294 $env->{SERVER_IPV6} = Samba::get_ipv6_addr($hostname); 295 $env->{SOCKET_WRAPPER_DEFAULT_IFACE} = Samba::get_interface($hostname); 296 $env->{DNS_HUB_LOG} = "$prefix_abs/dns_hub.log"; 297 $env->{RESOLV_CONF} = "$prefix_abs/resolv.conf"; 298 $env->{TESTENV_DIR} = $prefix_abs; 299 300 open(RESOLV_CONF, ">$env->{RESOLV_CONF}"); 301 print RESOLV_CONF "nameserver $env->{SERVER_IP}\n"; 302 print RESOLV_CONF "nameserver $env->{SERVER_IPV6}\n"; 303 close(RESOLV_CONF); 304 305 my @preargs = (); 306 my @args = (); 307 if (!defined($ENV{PYTHON})) { 308 push (@preargs, "env"); 309 push (@preargs, "python"); 310 } else { 311 push (@preargs, $ENV{PYTHON}); 312 } 313 my $binary = "$self->{srcdir}/selftest/target/dns_hub.py"; 314 push (@args, "$self->{server_maxtime}"); 315 push (@args, "$env->{SERVER_IP}"); 316 push (@args, Samba::realm_to_ip_mappings()); 317 my @full_cmd = (@preargs, $binary, @args); 318 319 my $daemon_ctx = { 320 NAME => "dnshub", 321 BINARY_PATH => $binary, 322 FULL_CMD => [ @full_cmd ], 323 LOG_FILE => $env->{DNS_HUB_LOG}, 324 TEE_STDOUT => 1, 325 PCAP_FILE => "$ENV{SOCKET_WRAPPER_PCAP_DIR}/env-$hostname$.pcap", 326 ENV_VARS => {}, 327 }; 328 329 # use a pipe for stdin in the child processes. This allows 330 # those processes to monitor the pipe for EOF to ensure they 331 # exit when the test script exits 332 pipe($STDIN_READER, $env->{STDIN_PIPE}); 333 334 my $pid = Samba::fork_and_exec($self, $env, $daemon_ctx, $STDIN_READER); 335 336 $env->{SAMBA_PID} = $pid; 337 $env->{KRB5_CONFIG} = "$prefix_abs/no_krb5.conf"; 338 339 # close the parent's read-end of the pipe 340 close($STDIN_READER); 341 342 return $env; 343} 344 345sub setup_dns_hub 346{ 347 my ($self, $prefix) = @_; 348 349 my $hostname = "rootdnsforwarder"; 350 351 my $env = $self->setup_dns_hub_internal("$hostname", "$prefix/$hostname"); 352 353 $self->{dns_hub_env} = $env; 354 355 return $env; 356} 357 358sub get_dns_hub_env($) 359{ 360 my ($self, $prefix) = @_; 361 362 if (defined($self->{dns_hub_env})) { 363 return $self->{dns_hub_env}; 364 } 365 366 die("get_dns_hub_env() not setup 'dns_hub_env'"); 367 return undef; 368} 369 370# Returns the environmental variables that we pass to samba-tool commands 371sub get_cmd_env_vars 372{ 373 my ($self, $localenv) = @_; 374 375 my $cmd_env = "NSS_WRAPPER_HOSTS='$localenv->{NSS_WRAPPER_HOSTS}' "; 376 $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$localenv->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; 377 if (defined($localenv->{RESOLV_WRAPPER_CONF})) { 378 $cmd_env .= "RESOLV_WRAPPER_CONF=\"$localenv->{RESOLV_WRAPPER_CONF}\" "; 379 } else { 380 $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$localenv->{RESOLV_WRAPPER_HOSTS}\" "; 381 } 382 $cmd_env .= " KRB5_CONFIG=\"$localenv->{KRB5_CONFIG}\" "; 383 $cmd_env .= "KRB5CCNAME=\"$localenv->{KRB5_CCACHE}\" "; 384 $cmd_env .= "RESOLV_CONF=\"$localenv->{RESOLV_CONF}\" "; 385 386 return $cmd_env; 387} 388 389# Sets up a forest trust namespace. 390# (Note this is different to kernel namespaces, setup by the 391# USE_NAMESPACES=1 option) 392sub setup_namespaces($$:$$) 393{ 394 my ($self, $localenv, $upn_array, $spn_array) = @_; 395 396 @{$upn_array} = [] unless defined($upn_array); 397 my $upn_args = ""; 398 foreach my $upn (@{$upn_array}) { 399 $upn_args .= " --add-upn-suffix=$upn"; 400 } 401 402 @{$spn_array} = [] unless defined($spn_array); 403 my $spn_args = ""; 404 foreach my $spn (@{$spn_array}) { 405 $spn_args .= " --add-spn-suffix=$spn"; 406 } 407 408 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 409 410 my $cmd_env = $self->get_cmd_env_vars($localenv); 411 412 my $cmd_config = " $localenv->{CONFIGURATION}"; 413 414 my $namespaces = $cmd_env; 415 $namespaces .= " $samba_tool domain trust namespaces $upn_args $spn_args"; 416 $namespaces .= $cmd_config; 417 unless (system($namespaces) == 0) { 418 warn("Failed to add namespaces \n$namespaces"); 419 return; 420 } 421 422 return; 423} 424 425sub setup_trust($$$$$) 426{ 427 my ($self, $localenv, $remoteenv, $type, $extra_args) = @_; 428 429 $localenv->{TRUST_SERVER} = $remoteenv->{SERVER}; 430 431 $localenv->{TRUST_USERNAME} = $remoteenv->{USERNAME}; 432 $localenv->{TRUST_PASSWORD} = $remoteenv->{PASSWORD}; 433 $localenv->{TRUST_DOMAIN} = $remoteenv->{DOMAIN}; 434 $localenv->{TRUST_REALM} = $remoteenv->{REALM}; 435 $localenv->{TRUST_DOMSID} = $remoteenv->{DOMSID}; 436 437 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 438 439 # setup the trust 440 my $cmd_env = $self->get_cmd_env_vars($localenv); 441 442 my $cmd_config = " $localenv->{CONFIGURATION}"; 443 my $cmd_creds = $cmd_config; 444 $cmd_creds .= " -U$localenv->{TRUST_DOMAIN}\\\\$localenv->{TRUST_USERNAME}\%$localenv->{TRUST_PASSWORD}"; 445 446 my $create = $cmd_env; 447 $create .= " $samba_tool domain trust create --type=${type} $localenv->{TRUST_REALM}"; 448 $create .= " $extra_args"; 449 $create .= $cmd_creds; 450 unless (system($create) == 0) { 451 warn("Failed to create trust \n$create"); 452 return undef; 453 } 454 455 my $groupname = "g_$localenv->{TRUST_DOMAIN}"; 456 my $groupadd = $cmd_env; 457 $groupadd .= " $samba_tool group add '$groupname' --group-scope=Domain $cmd_config"; 458 unless (system($groupadd) == 0) { 459 warn("Failed to create group \n$groupadd"); 460 return undef; 461 } 462 my $groupmem = $cmd_env; 463 $groupmem .= " $samba_tool group addmembers '$groupname' '$localenv->{TRUST_DOMSID}-513' $cmd_config"; 464 unless (system($groupmem) == 0) { 465 warn("Failed to add group member \n$groupmem"); 466 return undef; 467 } 468 469 return $localenv 470} 471 472sub provision_raw_prepare($$$$$$$$$$$$) 473{ 474 my ($self, $prefix, $server_role, $hostname, 475 $domain, $realm, $samsid, $functional_level, 476 $password, $kdc_ipv4, $kdc_ipv6) = @_; 477 my $ctx; 478 my $python_cmd = ""; 479 if (defined $ENV{PYTHON}) { 480 $python_cmd = $ENV{PYTHON} . " "; 481 } 482 $ctx->{python} = $python_cmd; 483 my $netbiosname = uc($hostname); 484 485 unless(-d $prefix or mkdir($prefix, 0777)) { 486 warn("Unable to create $prefix"); 487 return undef; 488 } 489 my $prefix_abs = abs_path($prefix); 490 491 die ("prefix=''") if $prefix_abs eq ""; 492 die ("prefix='/'") if $prefix_abs eq "/"; 493 494 unless (system("rm -rf $prefix_abs/*") == 0) { 495 warn("Unable to clean up"); 496 } 497 498 499 my $swiface = Samba::get_interface($hostname); 500 501 $ctx->{prefix} = $prefix; 502 $ctx->{prefix_abs} = $prefix_abs; 503 504 $ctx->{server_role} = $server_role; 505 $ctx->{hostname} = $hostname; 506 $ctx->{netbiosname} = $netbiosname; 507 $ctx->{swiface} = $swiface; 508 $ctx->{password} = $password; 509 $ctx->{kdc_ipv4} = $kdc_ipv4; 510 $ctx->{kdc_ipv6} = $kdc_ipv6; 511 $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}"; 512 if ($functional_level eq "2000") { 513 $ctx->{supported_enctypes} = "arcfour-hmac-md5 des-cbc-md5 des-cbc-crc" 514 } 515 516# 517# Set smbd log level here. 518# 519 $ctx->{server_loglevel} =$ENV{SERVER_LOG_LEVEL} || 1; 520 $ctx->{username} = "Administrator"; 521 $ctx->{domain} = $domain; 522 $ctx->{realm} = uc($realm); 523 $ctx->{dnsname} = lc($realm); 524 $ctx->{samsid} = $samsid; 525 526 $ctx->{functional_level} = $functional_level; 527 528 my $unix_name = ($ENV{USER} or $ENV{LOGNAME} or `whoami`); 529 chomp $unix_name; 530 $ctx->{unix_name} = $unix_name; 531 $ctx->{unix_uid} = $>; 532 my @mygid = split(" ", $(); 533 $ctx->{unix_gid} = $mygid[0]; 534 $ctx->{unix_gids_str} = $); 535 @{$ctx->{unix_gids}} = split(" ", $ctx->{unix_gids_str}); 536 537 $ctx->{etcdir} = "$prefix_abs/etc"; 538 $ctx->{piddir} = "$prefix_abs/pid"; 539 $ctx->{smb_conf} = "$ctx->{etcdir}/smb.conf"; 540 $ctx->{krb5_conf} = "$ctx->{etcdir}/krb5.conf"; 541 $ctx->{krb5_ccache} = "$prefix_abs/krb5_ccache"; 542 $ctx->{mitkdc_conf} = "$ctx->{etcdir}/mitkdc.conf"; 543 $ctx->{privatedir} = "$prefix_abs/private"; 544 $ctx->{binddnsdir} = "$prefix_abs/bind-dns"; 545 $ctx->{ncalrpcdir} = "$prefix_abs/ncalrpc"; 546 $ctx->{lockdir} = "$prefix_abs/lockdir"; 547 $ctx->{logdir} = "$prefix_abs/logs"; 548 $ctx->{statedir} = "$prefix_abs/statedir"; 549 $ctx->{cachedir} = "$prefix_abs/cachedir"; 550 $ctx->{winbindd_socket_dir} = "$prefix_abs/winbindd_socket"; 551 $ctx->{ntp_signd_socket_dir} = "$prefix_abs/ntp_signd_socket"; 552 $ctx->{nsswrap_passwd} = "$ctx->{etcdir}/passwd"; 553 $ctx->{nsswrap_group} = "$ctx->{etcdir}/group"; 554 $ctx->{nsswrap_hosts} = "$ENV{SELFTEST_PREFIX}/hosts"; 555 $ctx->{nsswrap_hostname} = "$ctx->{hostname}.$ctx->{dnsname}"; 556 if ($ENV{SAMBA_DNS_FAKING}) { 557 $ctx->{dns_host_file} = "$ENV{SELFTEST_PREFIX}/dns_host_file"; 558 $ctx->{samba_dnsupdate} = "$ENV{SRCDIR_ABS}/source4/scripting/bin/samba_dnsupdate -s $ctx->{smb_conf} --all-interfaces --use-file=$ctx->{dns_host_file}"; 559 $ctx->{samba_dnsupdate} = $python_cmd . $ctx->{samba_dnsupdate}; 560 } else { 561 $ctx->{samba_dnsupdate} = "$ENV{SRCDIR_ABS}/source4/scripting/bin/samba_dnsupdate -s $ctx->{smb_conf} --all-interfaces"; 562 $ctx->{samba_dnsupdate} = $python_cmd . $ctx->{samba_dnsupdate}; 563 $ctx->{use_resolv_wrapper} = 1; 564 } 565 566 my $dns_hub = $self->get_dns_hub_env(); 567 $ctx->{resolv_conf} = $dns_hub->{RESOLV_CONF}; 568 569 $ctx->{tlsdir} = "$ctx->{privatedir}/tls"; 570 571 $ctx->{ipv4} = Samba::get_ipv4_addr($hostname); 572 $ctx->{ipv6} = Samba::get_ipv6_addr($hostname); 573 574 push(@{$ctx->{directories}}, $ctx->{privatedir}); 575 push(@{$ctx->{directories}}, $ctx->{binddnsdir}); 576 push(@{$ctx->{directories}}, $ctx->{etcdir}); 577 push(@{$ctx->{directories}}, $ctx->{piddir}); 578 push(@{$ctx->{directories}}, $ctx->{lockdir}); 579 push(@{$ctx->{directories}}, $ctx->{logdir}); 580 push(@{$ctx->{directories}}, $ctx->{statedir}); 581 push(@{$ctx->{directories}}, $ctx->{cachedir}); 582 583 $ctx->{smb_conf_extra_options} = ""; 584 585 my @provision_options = (); 586 push (@provision_options, "KRB5_CONFIG=\"$ctx->{krb5_conf}\""); 587 push (@provision_options, "KRB5_CCACHE=\"$ctx->{krb5_ccache}\""); 588 push (@provision_options, "NSS_WRAPPER_PASSWD=\"$ctx->{nsswrap_passwd}\""); 589 push (@provision_options, "NSS_WRAPPER_GROUP=\"$ctx->{nsswrap_group}\""); 590 push (@provision_options, "NSS_WRAPPER_HOSTS=\"$ctx->{nsswrap_hosts}\""); 591 push (@provision_options, "NSS_WRAPPER_HOSTNAME=\"$ctx->{nsswrap_hostname}\""); 592 if (defined($ctx->{use_resolv_wrapper})) { 593 push (@provision_options, "RESOLV_WRAPPER_CONF=\"$ctx->{resolv_conf}\""); 594 push (@provision_options, "RESOLV_CONF=\"$ctx->{resolv_conf}\""); 595 } else { 596 push (@provision_options, "RESOLV_WRAPPER_HOSTS=\"$ctx->{dns_host_file}\""); 597 } 598 if (defined($ENV{GDB_PROVISION})) { 599 push (@provision_options, "gdb --args"); 600 if (!defined($ENV{PYTHON})) { 601 push (@provision_options, "env"); 602 push (@provision_options, "python"); 603 } 604 } 605 if (defined($ENV{VALGRIND_PROVISION})) { 606 push (@provision_options, "valgrind"); 607 if (!defined($ENV{PYTHON})) { 608 push (@provision_options, "env"); 609 push (@provision_options, "python"); 610 } 611 } 612 613 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 614 615 push (@provision_options, $samba_tool); 616 push (@provision_options, "domain"); 617 push (@provision_options, "provision"); 618 push (@provision_options, "--configfile=$ctx->{smb_conf}"); 619 push (@provision_options, "--host-name=$ctx->{hostname}"); 620 push (@provision_options, "--host-ip=$ctx->{ipv4}"); 621 push (@provision_options, "--quiet"); 622 push (@provision_options, "--domain=$ctx->{domain}"); 623 push (@provision_options, "--realm=$ctx->{realm}"); 624 if (defined($ctx->{samsid})) { 625 push (@provision_options, "--domain-sid=$ctx->{samsid}"); 626 } 627 push (@provision_options, "--adminpass=$ctx->{password}"); 628 push (@provision_options, "--krbtgtpass=krbtgt$ctx->{password}"); 629 push (@provision_options, "--machinepass=machine$ctx->{password}"); 630 push (@provision_options, "--root=$ctx->{unix_name}"); 631 push (@provision_options, "--server-role=\"$ctx->{server_role}\""); 632 push (@provision_options, "--function-level=\"$ctx->{functional_level}\""); 633 634 @{$ctx->{provision_options}} = @provision_options; 635 636 return $ctx; 637} 638 639sub has_option 640{ 641 my ($self, $keyword, @options_list) = @_; 642 643 # convert the options-list to a hash-map for easy keyword lookup 644 my %options_dict = map { $_ => 1 } @options_list; 645 646 return exists $options_dict{$keyword}; 647} 648 649# 650# Step1 creates the basic configuration 651# 652sub provision_raw_step1($$) 653{ 654 my ($self, $ctx) = @_; 655 656 mkdir($_, 0777) foreach (@{$ctx->{directories}}); 657 658 ## 659 ## lockdir and piddir must be 0755 660 ## 661 chmod 0755, $ctx->{lockdir}; 662 chmod 0755, $ctx->{piddir}; 663 664 unless (open(CONFFILE, ">$ctx->{smb_conf}")) { 665 warn("can't open $ctx->{smb_conf}$?"); 666 return undef; 667 } 668 669 Samba::prepare_keyblobs($ctx); 670 my $crlfile = "$ctx->{tlsdir}/crl.pem"; 671 $crlfile = "" unless -e ${crlfile}; 672 673 # work out which file server to use. Default to source3 smbd (s3fs), 674 # unless the source4 NTVFS (smb) file server has been specified 675 my $services = "-smb +s3fs"; 676 if ($self->has_option("--use-ntvfs", @{$ctx->{provision_options}})) { 677 $services = "+smb -s3fs"; 678 } 679 680 my $interfaces = Samba::get_interfaces_config($ctx->{netbiosname}); 681 682 print CONFFILE " 683[global] 684 netbios name = $ctx->{netbiosname} 685 posix:eadb = $ctx->{statedir}/eadb.tdb 686 workgroup = $ctx->{domain} 687 realm = $ctx->{realm} 688 private dir = $ctx->{privatedir} 689 binddns dir = $ctx->{binddnsdir} 690 pid directory = $ctx->{piddir} 691 ncalrpc dir = $ctx->{ncalrpcdir} 692 lock dir = $ctx->{lockdir} 693 state directory = $ctx->{statedir} 694 cache directory = $ctx->{cachedir} 695 winbindd socket directory = $ctx->{winbindd_socket_dir} 696 ntp signd socket directory = $ctx->{ntp_signd_socket_dir} 697 winbind separator = / 698 interfaces = $interfaces 699 tls dh params file = $ctx->{tlsdir}/dhparms.pem 700 tls crlfile = ${crlfile} 701 tls verify peer = no_check 702 panic action = $RealBin/gdb_backtrace \%d 703 wins support = yes 704 server role = $ctx->{server_role} 705 server services = +echo $services 706 dcerpc endpoint servers = +winreg +srvsvc 707 notify:inotify = false 708 ldb:nosync = true 709 ldap server require strong auth = yes 710#We don't want to pass our self-tests if the PAC code is wrong 711 gensec:require_pac = true 712 log file = $ctx->{logdir}/log.\%m 713 log level = $ctx->{server_loglevel} 714 lanman auth = Yes 715 ntlm auth = Yes 716 client min protocol = CORE 717 server min protocol = LANMAN1 718 mangled names = yes 719 dns update command = $ctx->{samba_dnsupdate} 720 spn update command = $ctx->{python} $ENV{SRCDIR_ABS}/source4/scripting/bin/samba_spnupdate -s $ctx->{smb_conf} 721 gpo update command = $ctx->{python} $ENV{SRCDIR_ABS}/source4/scripting/bin/samba-gpupdate -s $ctx->{smb_conf} --target=Computer 722 samba kcc command = $ctx->{python} $ENV{SRCDIR_ABS}/source4/scripting/bin/samba_kcc 723 dreplsrv:periodic_startup_interval = 0 724 dsdb:schema update allowed = yes 725 726 vfs objects = dfs_samba4 acl_xattr fake_acls xattr_tdb streams_depot 727 728 idmap_ldb:use rfc2307=yes 729 winbind enum users = yes 730 winbind enum groups = yes 731 732 rpc server port:netlogon = 1026 733 include system krb5 conf = no 734 735"; 736 737 print CONFFILE " 738 739 # Begin extra options 740 $ctx->{smb_conf_extra_options} 741 # End extra options 742"; 743 close(CONFFILE); 744 745 #Default the KDC IP to the server's IP 746 if (not defined($ctx->{kdc_ipv4})) { 747 $ctx->{kdc_ipv4} = $ctx->{ipv4}; 748 } 749 if (not defined($ctx->{kdc_ipv6})) { 750 $ctx->{kdc_ipv6} = $ctx->{ipv6}; 751 } 752 753 Samba::mk_krb5_conf($ctx); 754 Samba::mk_mitkdc_conf($ctx, abs_path(Samba::bindir_path($self, "shared"))); 755 756 open(PWD, ">$ctx->{nsswrap_passwd}"); 757 if ($ctx->{unix_uid} != 0) { 758 print PWD "root:x:0:0:root gecos:$ctx->{prefix_abs}:/bin/false\n"; 759 } 760 print PWD "$ctx->{unix_name}:x:$ctx->{unix_uid}:65531:$ctx->{unix_name} gecos:$ctx->{prefix_abs}:/bin/false\n"; 761 print PWD "nobody:x:65534:65533:nobody gecos:$ctx->{prefix_abs}:/bin/false 762pdbtest:x:65533:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false 763pdbtest2:x:65532:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false 764pdbtest3:x:65531:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false 765pdbtest4:x:65530:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false 766"; 767 close(PWD); 768 my $uid_rfc2307test = 65533; 769 770 open(GRP, ">$ctx->{nsswrap_group}"); 771 if ($ctx->{unix_gid} != 0) { 772 print GRP "root:x:0:\n"; 773 } 774 print GRP "$ctx->{unix_name}:x:$ctx->{unix_gid}:\n"; 775 print GRP "wheel:x:10: 776users:x:65531: 777nobody:x:65533: 778nogroup:x:65534:nobody 779"; 780 close(GRP); 781 my $gid_rfc2307test = 65532; 782 783 my $hostname = lc($ctx->{hostname}); 784 open(HOSTS, ">>$ctx->{nsswrap_hosts}"); 785 if ($hostname eq "localdc") { 786 print HOSTS "$ctx->{ipv4} ${hostname}.$ctx->{dnsname} $ctx->{dnsname} ${hostname}\n"; 787 print HOSTS "$ctx->{ipv6} ${hostname}.$ctx->{dnsname} $ctx->{dnsname} ${hostname}\n"; 788 } else { 789 print HOSTS "$ctx->{ipv4} ${hostname}.$ctx->{dnsname} ${hostname}\n"; 790 print HOSTS "$ctx->{ipv6} ${hostname}.$ctx->{dnsname} ${hostname}\n"; 791 } 792 close(HOSTS); 793 794 my $configuration = "--configfile=$ctx->{smb_conf}"; 795 796#Ensure the config file is valid before we start 797 my $testparm = Samba::bindir_path($self, "samba-tool") . " testparm"; 798 if (system("$testparm $configuration -v --suppress-prompt >/dev/null 2>&1") != 0) { 799 system("$testparm -v --suppress-prompt $configuration >&2"); 800 warn("Failed to create a valid smb.conf configuration $testparm!"); 801 return undef; 802 } 803 unless (system("($testparm $configuration -v --suppress-prompt --parameter-name=\"netbios name\" --section-name=global 2> /dev/null | grep -i \"^$ctx->{netbiosname}\" ) >/dev/null 2>&1") == 0) { 804 warn("Failed to create a valid smb.conf configuration! $testparm $configuration -v --suppress-prompt --parameter-name=\"netbios name\" --section-name=global"); 805 return undef; 806 } 807 808 # Return the environment variables for the new testenv DC. 809 # Note that we have SERVER_X and DC_SERVER_X variables (which have the same 810 # value initially). In a 2 DC setup, $DC_SERVER_X will always be the PDC. 811 my $ret = { 812 KRB5_CONFIG => $ctx->{krb5_conf}, 813 KRB5_CCACHE => $ctx->{krb5_ccache}, 814 MITKDC_CONFIG => $ctx->{mitkdc_conf}, 815 PIDDIR => $ctx->{piddir}, 816 SERVER => $ctx->{hostname}, 817 DC_SERVER => $ctx->{hostname}, 818 SERVER_IP => $ctx->{ipv4}, 819 DC_SERVER_IP => $ctx->{ipv4}, 820 SERVER_IPV6 => $ctx->{ipv6}, 821 DC_SERVER_IPV6 => $ctx->{ipv6}, 822 NETBIOSNAME => $ctx->{netbiosname}, 823 DC_NETBIOSNAME => $ctx->{netbiosname}, 824 DOMAIN => $ctx->{domain}, 825 USERNAME => $ctx->{username}, 826 DC_USERNAME => $ctx->{username}, 827 REALM => $ctx->{realm}, 828 DNSNAME => $ctx->{dnsname}, 829 SAMSID => $ctx->{samsid}, 830 PASSWORD => $ctx->{password}, 831 DC_PASSWORD => $ctx->{password}, 832 LDAPDIR => $ctx->{ldapdir}, 833 LDAP_INSTANCE => $ctx->{ldap_instance}, 834 SELFTEST_WINBINDD_SOCKET_DIR => $ctx->{winbindd_socket_dir}, 835 NCALRPCDIR => $ctx->{ncalrpcdir}, 836 LOCKDIR => $ctx->{lockdir}, 837 STATEDIR => $ctx->{statedir}, 838 CACHEDIR => $ctx->{cachedir}, 839 PRIVATEDIR => $ctx->{privatedir}, 840 BINDDNSDIR => $ctx->{binddnsdir}, 841 SERVERCONFFILE => $ctx->{smb_conf}, 842 TESTENV_DIR => $ctx->{prefix_abs}, 843 CONFIGURATION => $configuration, 844 SOCKET_WRAPPER_DEFAULT_IFACE => $ctx->{swiface}, 845 NSS_WRAPPER_PASSWD => $ctx->{nsswrap_passwd}, 846 NSS_WRAPPER_GROUP => $ctx->{nsswrap_group}, 847 NSS_WRAPPER_HOSTS => $ctx->{nsswrap_hosts}, 848 NSS_WRAPPER_HOSTNAME => $ctx->{nsswrap_hostname}, 849 SAMBA_TEST_FIFO => "$ctx->{prefix}/samba_test.fifo", 850 SAMBA_TEST_LOG => "$ctx->{prefix}/samba_test.log", 851 SAMBA_TEST_LOG_POS => 0, 852 NSS_WRAPPER_MODULE_SO_PATH => Samba::nss_wrapper_winbind_so_path($self), 853 NSS_WRAPPER_MODULE_FN_PREFIX => "winbind", 854 LOCAL_PATH => $ctx->{share}, 855 UID_RFC2307TEST => $uid_rfc2307test, 856 GID_RFC2307TEST => $gid_rfc2307test, 857 SERVER_ROLE => $ctx->{server_role}, 858 RESOLV_CONF => $ctx->{resolv_conf} 859 }; 860 861 if (defined($ctx->{use_resolv_wrapper})) { 862 $ret->{RESOLV_WRAPPER_CONF} = $ctx->{resolv_conf}; 863 } else { 864 $ret->{RESOLV_WRAPPER_HOSTS} = $ctx->{dns_host_file}; 865 } 866 867 if ($ctx->{server_role} eq "domain controller") { 868 $ret->{DOMSID} = $ret->{SAMSID}; 869 } 870 871 return $ret; 872} 873 874# 875# Step2 runs the provision script 876# 877sub provision_raw_step2($$$) 878{ 879 my ($self, $ctx, $ret) = @_; 880 881 my $provision_cmd = join(" ", @{$ctx->{provision_options}}); 882 unless (system($provision_cmd) == 0) { 883 warn("Unable to provision: \n$provision_cmd\n"); 884 return undef; 885 } 886 887 my $testallowed_account = "testallowed"; 888 my $samba_tool_cmd = ""; 889 $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; 890 $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 891 $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") 892 . " user create --configfile=$ctx->{smb_conf} $testallowed_account $ctx->{password}"; 893 unless (system($samba_tool_cmd) == 0) { 894 warn("Unable to add testallowed user: \n$samba_tool_cmd\n"); 895 return undef; 896 } 897 898 my $ldbmodify = ""; 899 $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; 900 $ldbmodify .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 901 $ldbmodify .= Samba::bindir_path($self, "ldbmodify"); 902 $ldbmodify .= " --configfile=$ctx->{smb_conf}"; 903 my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm})); 904 905 if ($ctx->{server_role} ne "domain controller") { 906 $base_dn = "DC=$ctx->{netbiosname}"; 907 } 908 909 my $user_dn = "cn=$testallowed_account,cn=users,$base_dn"; 910 $testallowed_account = "testallowed account"; 911 open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); 912 print LDIF "dn: $user_dn 913changetype: modify 914replace: samAccountName 915samAccountName: $testallowed_account 916- 917"; 918 close(LDIF); 919 920 open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); 921 print LDIF "dn: $user_dn 922changetype: modify 923replace: userPrincipalName 924userPrincipalName: testallowed upn\@$ctx->{realm} 925replace: servicePrincipalName 926servicePrincipalName: host/testallowed 927- 928"; 929 close(LDIF); 930 931 $samba_tool_cmd = ""; 932 $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; 933 $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 934 $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") 935 . " user create --configfile=$ctx->{smb_conf} testdenied $ctx->{password}"; 936 unless (system($samba_tool_cmd) == 0) { 937 warn("Unable to add testdenied user: \n$samba_tool_cmd\n"); 938 return undef; 939 } 940 941 my $user_dn = "cn=testdenied,cn=users,$base_dn"; 942 open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); 943 print LDIF "dn: $user_dn 944changetype: modify 945replace: userPrincipalName 946userPrincipalName: testdenied_upn\@$ctx->{realm}.upn 947- 948"; 949 close(LDIF); 950 951 $samba_tool_cmd = ""; 952 $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; 953 $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 954 $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") 955 . " user create --configfile=$ctx->{smb_conf} testupnspn $ctx->{password}"; 956 unless (system($samba_tool_cmd) == 0) { 957 warn("Unable to add testupnspn user: \n$samba_tool_cmd\n"); 958 return undef; 959 } 960 961 my $user_dn = "cn=testupnspn,cn=users,$base_dn"; 962 open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); 963 print LDIF "dn: $user_dn 964changetype: modify 965replace: userPrincipalName 966userPrincipalName: http/testupnspn.$ctx->{dnsname}\@$ctx->{realm} 967replace: servicePrincipalName 968servicePrincipalName: http/testupnspn.$ctx->{dnsname} 969- 970"; 971 close(LDIF); 972 973 $samba_tool_cmd = ""; 974 $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; 975 $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 976 $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") 977 . " group addmembers --configfile=$ctx->{smb_conf} 'Allowed RODC Password Replication Group' '$testallowed_account'"; 978 unless (system($samba_tool_cmd) == 0) { 979 warn("Unable to add '$testallowed_account' user to 'Allowed RODC Password Replication Group': \n$samba_tool_cmd\n"); 980 return undef; 981 } 982 983 # Create to users alice and bob! 984 my $user_account_array = ["alice", "bob", "jane"]; 985 986 foreach my $user_account (@{$user_account_array}) { 987 my $samba_tool_cmd = ""; 988 989 $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; 990 $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 991 $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") 992 . " user create --configfile=$ctx->{smb_conf} $user_account Secret007"; 993 unless (system($samba_tool_cmd) == 0) { 994 warn("Unable to create user: $user_account\n$samba_tool_cmd\n"); 995 return undef; 996 } 997 } 998 999 my $ldbmodify = ""; 1000 $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; 1001 $ldbmodify .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 1002 $ldbmodify .= Samba::bindir_path($self, "ldbmodify"); 1003 $ldbmodify .= " --configfile=$ctx->{smb_conf}"; 1004 my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm})); 1005 my $user_dn = "cn=jane,cn=users,$base_dn"; 1006 1007 open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb"); 1008 print LDIF "dn: $user_dn 1009changetype: modify 1010replace: userPrincipalName 1011userPrincipalName: jane.doe\@$ctx->{realm} 1012- 1013"; 1014 close(LDIF); 1015 1016 return $ret; 1017} 1018 1019sub provision($$$$$$$$$$) 1020{ 1021 my ($self, $prefix, $server_role, $hostname, 1022 $domain, $realm, $functional_level, 1023 $password, $kdc_ipv4, $kdc_ipv6, $extra_smbconf_options, $extra_smbconf_shares, 1024 $extra_provision_options) = @_; 1025 1026 my $samsid = Samba::random_domain_sid(); 1027 1028 my $ctx = $self->provision_raw_prepare($prefix, $server_role, 1029 $hostname, 1030 $domain, $realm, 1031 $samsid, 1032 $functional_level, 1033 $password, $kdc_ipv4, $kdc_ipv6); 1034 1035 if (defined($extra_provision_options)) { 1036 push (@{$ctx->{provision_options}}, @{$extra_provision_options}); 1037 } 1038 1039 $ctx->{share} = "$ctx->{prefix_abs}/share"; 1040 push(@{$ctx->{directories}}, "$ctx->{share}"); 1041 push(@{$ctx->{directories}}, "$ctx->{share}/test1"); 1042 push(@{$ctx->{directories}}, "$ctx->{share}/test2"); 1043 1044 # precreate directories for printer drivers 1045 push(@{$ctx->{directories}}, "$ctx->{share}/W32X86"); 1046 push(@{$ctx->{directories}}, "$ctx->{share}/x64"); 1047 push(@{$ctx->{directories}}, "$ctx->{share}/WIN40"); 1048 1049 my $msdfs = "no"; 1050 $msdfs = "yes" if ($server_role eq "domain controller"); 1051 $ctx->{smb_conf_extra_options} = " 1052 1053 max xmit = 32K 1054 server max protocol = SMB2 1055 host msdfs = $msdfs 1056 lanman auth = yes 1057 1058 # fruit:copyfile is a global option 1059 fruit:copyfile = yes 1060 1061 $extra_smbconf_options 1062 1063[tmp] 1064 path = $ctx->{share} 1065 read only = no 1066 posix:sharedelay = 100000 1067 posix:oplocktimeout = 3 1068 posix:writetimeupdatedelay = 500000 1069 1070[xcopy_share] 1071 path = $ctx->{share} 1072 read only = no 1073 posix:sharedelay = 100000 1074 posix:oplocktimeout = 3 1075 posix:writetimeupdatedelay = 500000 1076 create mask = 777 1077 force create mode = 777 1078 1079[posix_share] 1080 path = $ctx->{share} 1081 read only = no 1082 create mask = 0777 1083 force create mode = 0 1084 directory mask = 0777 1085 force directory mode = 0 1086 1087[test1] 1088 path = $ctx->{share}/test1 1089 read only = no 1090 posix:sharedelay = 100000 1091 posix:oplocktimeout = 3 1092 posix:writetimeupdatedelay = 500000 1093 1094[test2] 1095 path = $ctx->{share}/test2 1096 read only = no 1097 posix:sharedelay = 100000 1098 posix:oplocktimeout = 3 1099 posix:writetimeupdatedelay = 500000 1100 1101[cifs] 1102 path = $ctx->{share}/_ignore_cifs_ 1103 read only = no 1104 ntvfs handler = cifs 1105 cifs:server = $ctx->{netbiosname} 1106 cifs:share = tmp 1107 cifs:use-s4u2proxy = yes 1108 # There is no username specified here, instead the client is expected 1109 # to log in with kerberos, and the serverwill use delegated credentials. 1110 # Or the server tries s4u2self/s4u2proxy to impersonate the client 1111 1112[simple] 1113 path = $ctx->{share} 1114 read only = no 1115 ntvfs handler = simple 1116 1117[sysvol] 1118 path = $ctx->{statedir}/sysvol 1119 read only = no 1120 1121[netlogon] 1122 path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts 1123 read only = no 1124 1125[cifsposix] 1126 copy = simple 1127 ntvfs handler = cifsposix 1128 1129[vfs_fruit] 1130 path = $ctx->{share} 1131 vfs objects = catia fruit streams_xattr acl_xattr 1132 ea support = yes 1133 fruit:resource = file 1134 fruit:metadata = netatalk 1135 fruit:locking = netatalk 1136 fruit:encoding = native 1137 1138[xattr] 1139 path = $ctx->{share} 1140 # This can be used for testing real fs xattr stuff 1141 vfs objects = streams_xattr acl_xattr 1142 1143$extra_smbconf_shares 1144"; 1145 1146 my $ret = $self->provision_raw_step1($ctx); 1147 unless (defined $ret) { 1148 return undef; 1149 } 1150 1151 return $self->provision_raw_step2($ctx, $ret); 1152} 1153 1154# For multi-DC testenvs, we want $DC_SERVER to always be the PDC (i.e. the 1155# original DC) in the testenv. $SERVER is always the joined DC that we are 1156# actually running the test against 1157sub set_pdc_env_vars 1158{ 1159 my ($self, $env, $dcvars) = @_; 1160 1161 $env->{DC_SERVER} = $dcvars->{DC_SERVER}; 1162 $env->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP}; 1163 $env->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6}; 1164 $env->{DC_SERVERCONFFILE} = $dcvars->{SERVERCONFFILE}; 1165 $env->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME}; 1166 $env->{DC_USERNAME} = $dcvars->{DC_USERNAME}; 1167 $env->{DC_PASSWORD} = $dcvars->{DC_PASSWORD}; 1168} 1169 1170sub provision_s4member($$$$$) 1171{ 1172 my ($self, $prefix, $dcvars, $hostname, $more_conf) = @_; 1173 print "PROVISIONING MEMBER...\n"; 1174 my $extra_smb_conf = " 1175 passdb backend = samba_dsdb 1176winbindd:use external pipes = true 1177 1178# the source4 smb server doesn't allow signing by default 1179server signing = enabled 1180raw NTLMv2 auth = yes 1181 1182rpc_server:default = external 1183rpc_server:svcctl = embedded 1184rpc_server:srvsvc = embedded 1185rpc_server:eventlog = embedded 1186rpc_server:ntsvcs = embedded 1187rpc_server:winreg = embedded 1188rpc_server:spoolss = embedded 1189rpc_daemon:spoolssd = embedded 1190rpc_server:tcpip = no 1191"; 1192 if ($more_conf) { 1193 $extra_smb_conf = $extra_smb_conf . $more_conf . "\n"; 1194 } 1195 my $extra_provision_options = ["--use-ntvfs"]; 1196 my $ret = $self->provision($prefix, 1197 "member server", 1198 $hostname, 1199 $dcvars->{DOMAIN}, 1200 $dcvars->{REALM}, 1201 "2008", 1202 "locMEMpass3", 1203 $dcvars->{SERVER_IP}, 1204 $dcvars->{SERVER_IPV6}, 1205 $extra_smb_conf, "", 1206 $extra_provision_options); 1207 unless ($ret) { 1208 return undef; 1209 } 1210 1211 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 1212 my $cmd = $self->get_cmd_env_vars($ret); 1213 $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} member"; 1214 $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}"; 1215 $cmd .= " --machinepass=machine$ret->{PASSWORD}"; 1216 1217 unless (system($cmd) == 0) { 1218 warn("Join failed\n$cmd"); 1219 return undef; 1220 } 1221 1222 $ret->{DOMSID} = $dcvars->{DOMSID}; 1223 $self->set_pdc_env_vars($ret, $dcvars); 1224 1225 return $ret; 1226} 1227 1228sub provision_rpc_proxy($$$) 1229{ 1230 my ($self, $prefix, $dcvars) = @_; 1231 print "PROVISIONING RPC PROXY...\n"; 1232 1233 my $extra_smbconf_options = " 1234 passdb backend = samba_dsdb 1235 1236 # rpc_proxy 1237 dcerpc_remote:binding = ncacn_ip_tcp:$dcvars->{SERVER} 1238 dcerpc endpoint servers = epmapper, remote 1239 dcerpc_remote:interfaces = rpcecho 1240 dcerpc_remote:allow_anonymous_fallback = yes 1241 1242[cifs_to_dc] 1243 path = /tmp/_ignore_cifs_to_dc_/_none_ 1244 read only = no 1245 ntvfs handler = cifs 1246 cifs:server = $dcvars->{SERVER} 1247 cifs:share = cifs 1248 cifs:use-s4u2proxy = yes 1249 # There is no username specified here, instead the client is expected 1250 # to log in with kerberos, and the serverwill use delegated credentials. 1251 # Or the server tries s4u2self/s4u2proxy to impersonate the client 1252 1253"; 1254 1255 my $extra_provision_options = ["--use-ntvfs"]; 1256 my $ret = $self->provision($prefix, 1257 "member server", 1258 "localrpcproxy", 1259 $dcvars->{DOMAIN}, 1260 $dcvars->{REALM}, 1261 "2008", 1262 "locRPCproxypass4", 1263 $dcvars->{SERVER_IP}, 1264 $dcvars->{SERVER_IPV6}, 1265 $extra_smbconf_options, "", 1266 $extra_provision_options); 1267 unless ($ret) { 1268 return undef; 1269 } 1270 1271 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 1272 1273 # The joind runs in the context of the rpc_proxy/member for now 1274 my $cmd = $self->get_cmd_env_vars($ret); 1275 $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} member"; 1276 $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}"; 1277 $cmd .= " --machinepass=machine$ret->{PASSWORD}"; 1278 1279 unless (system($cmd) == 0) { 1280 warn("Join failed\n$cmd"); 1281 return undef; 1282 } 1283 1284 # Setting up delegation runs in the context of the DC for now 1285 $cmd = ""; 1286 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$dcvars->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; 1287 $cmd .= "KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" "; 1288 $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 1289 $cmd .= "RESOLV_CONF=\"$dcvars->{RESOLV_CONF}\" "; 1290 $cmd .= "$samba_tool delegation for-any-protocol '$ret->{NETBIOSNAME}\$' on"; 1291 $cmd .= " $dcvars->{CONFIGURATION}"; 1292 print $cmd; 1293 1294 unless (system($cmd) == 0) { 1295 warn("Delegation failed\n$cmd"); 1296 return undef; 1297 } 1298 1299 # Setting up delegation runs in the context of the DC for now 1300 $cmd = ""; 1301 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$dcvars->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; 1302 $cmd .= "KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" "; 1303 $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 1304 $cmd .= "RESOLV_CONF=\"$dcvars->{RESOLV_CONF}\" "; 1305 $cmd .= "$samba_tool delegation add-service '$ret->{NETBIOSNAME}\$' cifs/$dcvars->{SERVER}"; 1306 $cmd .= " $dcvars->{CONFIGURATION}"; 1307 1308 unless (system($cmd) == 0) { 1309 warn("Delegation failed\n$cmd"); 1310 return undef; 1311 } 1312 1313 $ret->{DOMSID} = $dcvars->{DOMSID}; 1314 $self->set_pdc_env_vars($ret, $dcvars); 1315 1316 return $ret; 1317} 1318 1319sub provision_promoted_dc($$$) 1320{ 1321 my ($self, $prefix, $dcvars) = @_; 1322 print "PROVISIONING PROMOTED DC...\n"; 1323 1324 # We do this so that we don't run the provision. That's the job of 'samba-tool domain dcpromo'. 1325 my $ctx = $self->provision_raw_prepare($prefix, "domain controller", 1326 "promotedvdc", 1327 $dcvars->{DOMAIN}, 1328 $dcvars->{REALM}, 1329 $dcvars->{SAMSID}, 1330 "2008", 1331 $dcvars->{PASSWORD}, 1332 $dcvars->{SERVER_IP}, 1333 $dcvars->{SERVER_IPV6}); 1334 1335 $ctx->{smb_conf_extra_options} = " 1336 max xmit = 32K 1337 server max protocol = SMB2 1338 1339 ntlm auth = ntlmv2-only 1340 1341[sysvol] 1342 path = $ctx->{statedir}/sysvol 1343 read only = yes 1344 1345[netlogon] 1346 path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts 1347 read only = no 1348 1349"; 1350 1351 my $ret = $self->provision_raw_step1($ctx); 1352 unless ($ret) { 1353 return undef; 1354 } 1355 1356 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 1357 my $cmd = $self->get_cmd_env_vars($ret); 1358 $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} MEMBER --realm=$dcvars->{REALM}"; 1359 $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}"; 1360 $cmd .= " --machinepass=machine$ret->{PASSWORD}"; 1361 1362 unless (system($cmd) == 0) { 1363 warn("Join failed\n$cmd"); 1364 return undef; 1365 } 1366 1367 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 1368 my $cmd = $self->get_cmd_env_vars($ret); 1369 $cmd .= "$samba_tool domain dcpromo $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}"; 1370 $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}"; 1371 $cmd .= " --machinepass=machine$ret->{PASSWORD} --dns-backend=BIND9_DLZ"; 1372 1373 unless (system($cmd) == 0) { 1374 warn("Join failed\n$cmd"); 1375 return undef; 1376 } 1377 1378 $self->set_pdc_env_vars($ret, $dcvars); 1379 1380 return $ret; 1381} 1382 1383sub provision_vampire_dc($$$) 1384{ 1385 my ($self, $prefix, $dcvars, $fl) = @_; 1386 print "PROVISIONING VAMPIRE DC @ FL $fl...\n"; 1387 my $name = "localvampiredc"; 1388 my $extra_conf = ""; 1389 1390 if ($fl == "2000") { 1391 $name = "vampire2000dc"; 1392 } else { 1393 $extra_conf = "drs: immediate link sync = yes 1394 drs: max link sync = 250"; 1395 } 1396 1397 # We do this so that we don't run the provision. That's the job of 'net vampire'. 1398 my $ctx = $self->provision_raw_prepare($prefix, "domain controller", 1399 $name, 1400 $dcvars->{DOMAIN}, 1401 $dcvars->{REALM}, 1402 $dcvars->{DOMSID}, 1403 $fl, 1404 $dcvars->{PASSWORD}, 1405 $dcvars->{SERVER_IP}, 1406 $dcvars->{SERVER_IPV6}); 1407 1408 $ctx->{smb_conf_extra_options} = " 1409 max xmit = 32K 1410 server max protocol = SMB2 1411 1412 ntlm auth = mschapv2-and-ntlmv2-only 1413 $extra_conf 1414 1415[sysvol] 1416 path = $ctx->{statedir}/sysvol 1417 read only = yes 1418 1419[netlogon] 1420 path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts 1421 read only = no 1422 1423"; 1424 1425 my $ret = $self->provision_raw_step1($ctx); 1426 unless ($ret) { 1427 return undef; 1428 } 1429 1430 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 1431 my $cmd = $self->get_cmd_env_vars($ret); 1432 $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}"; 1433 $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD} --domain-critical-only"; 1434 $cmd .= " --machinepass=machine$ret->{PASSWORD}"; 1435 $cmd .= " --backend-store=mdb"; 1436 1437 unless (system($cmd) == 0) { 1438 warn("Join failed\n$cmd"); 1439 return undef; 1440 } 1441 1442 $self->set_pdc_env_vars($ret, $dcvars); 1443 $ret->{DC_REALM} = $dcvars->{DC_REALM}; 1444 1445 return $ret; 1446} 1447 1448sub provision_ad_dc_ntvfs($$$) 1449{ 1450 my ($self, $prefix, $extra_provision_options) = @_; 1451 1452 # We keep the old 'winbind' name here in server services to 1453 # ensure upgrades which used that name still work with the now 1454 # alias. 1455 1456 print "PROVISIONING AD DC (NTVFS)...\n"; 1457 my $extra_conf_options = "netbios aliases = localDC1-a 1458 server services = +winbind -winbindd 1459 ldap server require strong auth = allow_sasl_over_tls 1460 allow nt4 crypto = yes 1461 raw NTLMv2 auth = yes 1462 lsa over netlogon = yes 1463 rpc server port = 1027 1464 auth event notification = true 1465 dsdb event notification = true 1466 dsdb password event notification = true 1467 dsdb group change notification = true 1468 server schannel = auto 1469 "; 1470 push (@{$extra_provision_options}, "--use-ntvfs"); 1471 my $ret = $self->provision($prefix, 1472 "domain controller", 1473 "localdc", 1474 "SAMBADOMAIN", 1475 "samba.example.com", 1476 "2008", 1477 "locDCpass1", 1478 undef, 1479 undef, 1480 $extra_conf_options, 1481 "", 1482 $extra_provision_options); 1483 unless ($ret) { 1484 return undef; 1485 } 1486 1487 unless($self->add_wins_config("$prefix/private")) { 1488 warn("Unable to add wins configuration"); 1489 return undef; 1490 } 1491 $ret->{NETBIOSALIAS} = "localdc1-a"; 1492 $ret->{DC_REALM} = $ret->{REALM}; 1493 1494 return $ret; 1495} 1496 1497sub provision_fl2000dc($$) 1498{ 1499 my ($self, $prefix) = @_; 1500 1501 print "PROVISIONING DC WITH FOREST LEVEL 2000...\n"; 1502 my $extra_conf_options = " 1503 spnego:simulate_w2k=yes 1504 ntlmssp_server:force_old_spnego=yes 1505"; 1506 my $extra_provision_options = ["--base-schema=2008_R2"]; 1507 # This environment uses plain text secrets 1508 # i.e. secret attributes are not encrypted on disk. 1509 # This allows testing of the --plaintext-secrets option for 1510 # provision 1511 push (@{$extra_provision_options}, "--plaintext-secrets"); 1512 my $ret = $self->provision($prefix, 1513 "domain controller", 1514 "dc5", 1515 "SAMBA2000", 1516 "samba2000.example.com", 1517 "2000", 1518 "locDCpass5", 1519 undef, 1520 undef, 1521 $extra_conf_options, 1522 "", 1523 $extra_provision_options); 1524 unless ($ret) { 1525 return undef; 1526 } 1527 1528 unless($self->add_wins_config("$prefix/private")) { 1529 warn("Unable to add wins configuration"); 1530 return undef; 1531 } 1532 $ret->{DC_REALM} = $ret->{REALM}; 1533 1534 return $ret; 1535} 1536 1537sub provision_fl2003dc($$$) 1538{ 1539 my ($self, $prefix, $dcvars) = @_; 1540 my $ip_addr1 = Samba::get_ipv4_addr("fakednsforwarder1"); 1541 my $ip_addr2 = Samba::get_ipv4_addr("fakednsforwarder2"); 1542 1543 print "PROVISIONING DC WITH FOREST LEVEL 2003...\n"; 1544 my $extra_conf_options = "allow dns updates = nonsecure and secure 1545 dcesrv:header signing = no 1546 dcesrv:max auth states = 0 1547 dns forwarder = $ip_addr1 $ip_addr2"; 1548 my $extra_provision_options = ["--base-schema=2008_R2"]; 1549 my $ret = $self->provision($prefix, 1550 "domain controller", 1551 "dc6", 1552 "SAMBA2003", 1553 "samba2003.example.com", 1554 "2003", 1555 "locDCpass6", 1556 undef, 1557 undef, 1558 $extra_conf_options, 1559 "", 1560 $extra_provision_options); 1561 unless (defined $ret) { 1562 return undef; 1563 } 1564 1565 $ret->{DNS_FORWARDER1} = $ip_addr1; 1566 $ret->{DNS_FORWARDER2} = $ip_addr2; 1567 1568 my @samba_tool_options; 1569 push (@samba_tool_options, Samba::bindir_path($self, "samba-tool")); 1570 push (@samba_tool_options, "domain"); 1571 push (@samba_tool_options, "passwordsettings"); 1572 push (@samba_tool_options, "set"); 1573 push (@samba_tool_options, "--configfile=$ret->{SERVERCONFFILE}"); 1574 push (@samba_tool_options, "--min-pwd-age=0"); 1575 push (@samba_tool_options, "--history-length=1"); 1576 1577 my $samba_tool_cmd = join(" ", @samba_tool_options); 1578 1579 unless (system($samba_tool_cmd) == 0) { 1580 warn("Unable to set min password age to 0: \n$samba_tool_cmd\n"); 1581 return undef; 1582 } 1583 1584 unless($self->add_wins_config("$prefix/private")) { 1585 warn("Unable to add wins configuration"); 1586 return undef; 1587 } 1588 1589 return $ret; 1590} 1591 1592sub provision_fl2008r2dc($$$) 1593{ 1594 my ($self, $prefix, $dcvars) = @_; 1595 1596 print "PROVISIONING DC WITH FOREST LEVEL 2008r2...\n"; 1597 my $extra_conf_options = " 1598 ldap server require strong auth = no 1599 # delay by 10 seconds, 10^7 usecs 1600 ldap_server:delay_expire_disconnect = 10000 1601"; 1602 my $extra_provision_options = ["--base-schema=2008_R2"]; 1603 my $ret = $self->provision($prefix, 1604 "domain controller", 1605 "dc7", 1606 "SAMBA2008R2", 1607 "samba2008R2.example.com", 1608 "2008_R2", 1609 "locDCpass7", 1610 undef, 1611 undef, 1612 $extra_conf_options, 1613 "", 1614 $extra_provision_options); 1615 unless (defined $ret) { 1616 return undef; 1617 } 1618 1619 unless ($self->add_wins_config("$prefix/private")) { 1620 warn("Unable to add wins configuration"); 1621 return undef; 1622 } 1623 $ret->{DC_REALM} = $ret->{REALM}; 1624 1625 return $ret; 1626} 1627 1628 1629sub provision_rodc($$$) 1630{ 1631 my ($self, $prefix, $dcvars) = @_; 1632 print "PROVISIONING RODC...\n"; 1633 1634 # We do this so that we don't run the provision. That's the job of 'net join RODC'. 1635 my $ctx = $self->provision_raw_prepare($prefix, "domain controller", 1636 "rodc", 1637 $dcvars->{DOMAIN}, 1638 $dcvars->{REALM}, 1639 $dcvars->{DOMSID}, 1640 "2008", 1641 $dcvars->{PASSWORD}, 1642 $dcvars->{SERVER_IP}, 1643 $dcvars->{SERVER_IPV6}); 1644 unless ($ctx) { 1645 return undef; 1646 } 1647 1648 $ctx->{share} = "$ctx->{prefix_abs}/share"; 1649 push(@{$ctx->{directories}}, "$ctx->{share}"); 1650 1651 $ctx->{smb_conf_extra_options} = " 1652 max xmit = 32K 1653 server max protocol = SMB2 1654 password server = $dcvars->{DC_SERVER} 1655 1656[sysvol] 1657 path = $ctx->{statedir}/sysvol 1658 read only = yes 1659 1660[netlogon] 1661 path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts 1662 read only = yes 1663 1664[tmp] 1665 path = $ctx->{share} 1666 read only = no 1667 posix:sharedelay = 10000 1668 posix:oplocktimeout = 3 1669 posix:writetimeupdatedelay = 50000 1670 1671"; 1672 1673 my $ret = $self->provision_raw_step1($ctx); 1674 unless ($ret) { 1675 return undef; 1676 } 1677 1678 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 1679 my $cmd = $self->get_cmd_env_vars($ret); 1680 $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} RODC"; 1681 $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}"; 1682 $cmd .= " --server=$dcvars->{DC_SERVER}"; 1683 1684 unless (system($cmd) == 0) { 1685 warn("RODC join failed\n$cmd"); 1686 return undef; 1687 } 1688 1689 # This ensures deterministic behaviour for tests that want to have the 'testallowed account' 1690 # user password verified on the RODC 1691 my $testallowed_account = "testallowed account"; 1692 $cmd = "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; 1693 $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; 1694 $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; 1695 $cmd .= "$samba_tool rodc preload '$testallowed_account' $ret->{CONFIGURATION}"; 1696 $cmd .= " --server=$dcvars->{DC_SERVER}"; 1697 1698 unless (system($cmd) == 0) { 1699 warn("RODC join failed\n$cmd"); 1700 return undef; 1701 } 1702 1703 # we overwrite the kdc after the RODC join 1704 # so that use the RODC as kdc and test 1705 # the proxy code 1706 $ctx->{kdc_ipv4} = $ret->{SERVER_IP}; 1707 $ctx->{kdc_ipv6} = $ret->{SERVER_IPV6}; 1708 Samba::mk_krb5_conf($ctx); 1709 Samba::mk_mitkdc_conf($ctx, abs_path(Samba::bindir_path($self, "shared"))); 1710 1711 $self->set_pdc_env_vars($ret, $dcvars); 1712 1713 return $ret; 1714} 1715 1716sub read_config_h($) 1717{ 1718 my ($name) = @_; 1719 my %ret = {}; 1720 open(LF, "<$name") or die("unable to read $name: $!"); 1721 while (<LF>) { 1722 chomp; 1723 next if not (/^#define /); 1724 if (/^#define (.*?)[ \t]+(.*?)$/) { 1725 $ret{$1} = $2; 1726 next; 1727 } 1728 if (/^#define (.*?)[ \t]+$/) { 1729 $ret{$1} = 1;; 1730 next; 1731 } 1732 } 1733 close(LF); 1734 return \%ret; 1735} 1736 1737sub provision_ad_dc($$$$$$) 1738{ 1739 my ($self, $prefix, $hostname, $domain, $realm, $smbconf_args, 1740 $extra_provision_options) = @_; 1741 1742 my $prefix_abs = abs_path($prefix); 1743 1744 my $bindir_abs = abs_path($self->{bindir}); 1745 my $lockdir="$prefix_abs/lockdir"; 1746 my $conffile="$prefix_abs/etc/smb.conf"; 1747 1748 my $require_mutexes = "dbwrap_tdb_require_mutexes:* = yes"; 1749 $require_mutexes = "" if ($ENV{SELFTEST_DONT_REQUIRE_TDB_MUTEX_SUPPORT} eq "1"); 1750 1751 my $config_h = {}; 1752 1753 if (defined($ENV{CONFIG_H})) { 1754 $config_h = read_config_h($ENV{CONFIG_H}); 1755 } 1756 1757 my $password_hash_gpg_key_ids = "password hash gpg key ids = 4952E40301FAB41A"; 1758 $password_hash_gpg_key_ids = "" unless defined($config_h->{HAVE_GPGME}); 1759 1760 my $extra_smbconf_options = " 1761 xattr_tdb:file = $prefix_abs/statedir/xattr.tdb 1762 1763 dbwrap_tdb_mutexes:* = yes 1764 ${require_mutexes} 1765 1766 ${password_hash_gpg_key_ids} 1767 1768 kernel oplocks = no 1769 kernel change notify = no 1770 smb2 leases = no 1771 1772 logging = file 1773 printing = bsd 1774 printcap name = /dev/null 1775 1776 max protocol = SMB3 1777 read only = no 1778 1779 smbd:sharedelay = 100000 1780 smbd:writetimeupdatedelay = 500000 1781 create mask = 755 1782 dos filemode = yes 1783 check parent directory delete on close = yes 1784 1785 dcerpc endpoint servers = -winreg -srvsvc 1786 1787 printcap name = /dev/null 1788 1789 addprinter command = $ENV{SRCDIR_ABS}/source3/script/tests/printing/modprinter.pl -a -s $conffile -- 1790 deleteprinter command = $ENV{SRCDIR_ABS}/source3/script/tests/printing/modprinter.pl -d -s $conffile -- 1791 1792 printing = vlp 1793 print command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb print %p %s 1794 lpq command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpq %p 1795 lp rm command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lprm %p %j 1796 lp pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lppause %p %j 1797 lp resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpresume %p %j 1798 queue pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queuepause %p 1799 queue resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queueresume %p 1800 lpq cache time = 0 1801 print notify backchannel = yes 1802 1803 server schannel = auto 1804 auth event notification = true 1805 dsdb event notification = true 1806 dsdb password event notification = true 1807 dsdb group change notification = true 1808 $smbconf_args 1809"; 1810 1811 my $extra_smbconf_shares = " 1812 1813[tmpenc] 1814 copy = tmp 1815 smb encrypt = required 1816 1817[tmpcase] 1818 copy = tmp 1819 case sensitive = yes 1820 1821[tmpguest] 1822 copy = tmp 1823 guest ok = yes 1824 1825[hideunread] 1826 copy = tmp 1827 hide unreadable = yes 1828 1829[durable] 1830 copy = tmp 1831 kernel share modes = no 1832 kernel oplocks = no 1833 posix locking = no 1834 1835[print\$] 1836 copy = tmp 1837 1838[print1] 1839 copy = tmp 1840 printable = yes 1841 1842[print2] 1843 copy = print1 1844[print3] 1845 copy = print1 1846[print4] 1847 copy = print1 1848 guest ok = yes 1849[lp] 1850 copy = print1 1851"; 1852 1853 push (@{$extra_provision_options}, "--backend-store=mdb"); 1854 print "PROVISIONING AD DC...\n"; 1855 my $ret = $self->provision($prefix, 1856 "domain controller", 1857 $hostname, 1858 $domain, 1859 $realm, 1860 "2008", 1861 "locDCpass1", 1862 undef, 1863 undef, 1864 $extra_smbconf_options, 1865 $extra_smbconf_shares, 1866 $extra_provision_options); 1867 unless (defined $ret) { 1868 return undef; 1869 } 1870 1871 unless($self->add_wins_config("$prefix/private")) { 1872 warn("Unable to add wins configuration"); 1873 return undef; 1874 } 1875 1876 return $ret; 1877} 1878 1879sub provision_chgdcpass($$) 1880{ 1881 my ($self, $prefix) = @_; 1882 1883 print "PROVISIONING CHGDCPASS...\n"; 1884 # This environment disallows the use of this password 1885 # (and also removes the default AD complexity checks) 1886 my $unacceptable_password = "Paßßword-widk3Dsle32jxdBdskldsk55klASKQ"; 1887 my $extra_smb_conf = " 1888 check password script = $self->{srcdir}/selftest/checkpassword_arg1.sh ${unacceptable_password} 1889 allow dcerpc auth level connect:lsarpc = yes 1890 dcesrv:max auth states = 8 1891"; 1892 my $extra_provision_options = ["--dns-backend=BIND9_DLZ"]; 1893 my $ret = $self->provision($prefix, 1894 "domain controller", 1895 "chgdcpass", 1896 "CHDCDOMAIN", 1897 "chgdcpassword.samba.example.com", 1898 "2008", 1899 "chgDCpass1", 1900 undef, 1901 undef, 1902 $extra_smb_conf, 1903 "", 1904 $extra_provision_options); 1905 unless (defined $ret) { 1906 return undef; 1907 } 1908 1909 unless($self->add_wins_config("$prefix/private")) { 1910 warn("Unable to add wins configuration"); 1911 return undef; 1912 } 1913 1914 # Remove secrets.tdb from this environment to test that we 1915 # still start up on systems without the new matching 1916 # secrets.tdb records. 1917 unless (unlink("$ret->{PRIVATEDIR}/secrets.tdb") || unlink("$ret->{PRIVATEDIR}/secrets.ntdb")) { 1918 warn("Unable to remove $ret->{PRIVATEDIR}/secrets.tdb added during provision"); 1919 return undef; 1920 } 1921 1922 $ret->{UNACCEPTABLE_PASSWORD} = $unacceptable_password; 1923 1924 return $ret; 1925} 1926 1927sub teardown_env_terminate($$) 1928{ 1929 my ($self, $envvars) = @_; 1930 my $pid; 1931 1932 # This should cause samba to terminate gracefully 1933 my $smbcontrol = Samba::bindir_path($self, "smbcontrol"); 1934 my $cmd = ""; 1935 $cmd .= "$smbcontrol samba shutdown $envvars->{CONFIGURATION}"; 1936 my $ret = system($cmd); 1937 if ($ret != 0) { 1938 warn "'$cmd' failed with '$ret'\n"; 1939 } 1940 1941 # This should cause samba to terminate gracefully 1942 close($envvars->{STDIN_PIPE}); 1943 1944 $pid = $envvars->{SAMBA_PID}; 1945 my $count = 0; 1946 my $childpid; 1947 1948 # This should give it time to write out the gcov data 1949 until ($count > 15) { 1950 if (Samba::cleanup_child($pid, "samba") != 0) { 1951 return; 1952 } 1953 sleep(1); 1954 $count++; 1955 } 1956 1957 # After 15 Seconds, work out why this thing is still alive 1958 warn "server process $pid took more than $count seconds to exit, showing backtrace:\n"; 1959 system("$self->{srcdir}/selftest/gdb_backtrace $pid"); 1960 1961 until ($count > 30) { 1962 if (Samba::cleanup_child($pid, "samba") != 0) { 1963 return; 1964 } 1965 sleep(1); 1966 $count++; 1967 } 1968 1969 if (kill(0, $pid)) { 1970 warn "server process $pid took more than $count seconds to exit, sending SIGTERM\n"; 1971 kill "TERM", $pid; 1972 } 1973 1974 until ($count > 40) { 1975 if (Samba::cleanup_child($pid, "samba") != 0) { 1976 return; 1977 } 1978 sleep(1); 1979 $count++; 1980 } 1981 # If it is still around, kill it 1982 if (kill(0, $pid)) { 1983 warn "server process $pid took more than $count seconds to exit, killing\n with SIGKILL\n"; 1984 kill 9, $pid; 1985 } 1986 return; 1987} 1988 1989sub teardown_env($$) 1990{ 1991 my ($self, $envvars) = @_; 1992 teardown_env_terminate($self, $envvars); 1993 1994 print $self->getlog_env($envvars); 1995 1996 return; 1997} 1998 1999sub getlog_env($$) 2000{ 2001 my ($self, $envvars) = @_; 2002 my $title = "SAMBA LOG of: $envvars->{NETBIOSNAME} pid $envvars->{SAMBA_PID}\n"; 2003 my $out = $title; 2004 2005 open(LOG, "<$envvars->{SAMBA_TEST_LOG}"); 2006 2007 seek(LOG, $envvars->{SAMBA_TEST_LOG_POS}, SEEK_SET); 2008 while (<LOG>) { 2009 $out .= $_; 2010 } 2011 $envvars->{SAMBA_TEST_LOG_POS} = tell(LOG); 2012 close(LOG); 2013 2014 return "" if $out eq $title; 2015 2016 return $out; 2017} 2018 2019sub check_env($$) 2020{ 2021 my ($self, $envvars) = @_; 2022 my $samba_pid = $envvars->{SAMBA_PID}; 2023 2024 if (not defined($samba_pid)) { 2025 return 0; 2026 } elsif ($samba_pid > 0) { 2027 my $childpid = Samba::cleanup_child($samba_pid, "samba"); 2028 2029 if ($childpid == 0) { 2030 return 1; 2031 } 2032 return 0; 2033 } else { 2034 return 1; 2035 } 2036} 2037 2038# Declare the environments Samba4 makes available. 2039# To be set up, they will be called as 2040# samba4->setup_$envname($self, $path, $dep_1_vars, $dep_2_vars, ...) 2041# The interdependencies between the testenvs are declared below. Some testenvs 2042# are dependent on another testenv running first, e.g. vampire_dc is dependent 2043# on ad_dc_ntvfs because vampire_dc joins ad_dc_ntvfs's domain. All DCs are 2044# dependent on dns_hub, which handles resolving DNS queries for the realm. 2045%Samba4::ENV_DEPS = ( 2046 # name => [dep_1, dep_2, ...], 2047 dns_hub => [], 2048 ad_dc_ntvfs => ["dns_hub"], 2049 ad_dc => ["dns_hub"], 2050 ad_dc_no_nss => ["dns_hub"], 2051 ad_dc_no_ntlm => ["dns_hub"], 2052 2053 fl2008r2dc => ["ad_dc"], 2054 fl2003dc => ["ad_dc"], 2055 fl2000dc => ["dns_hub"], 2056 2057 vampire_2000_dc => ["fl2000dc"], 2058 vampire_dc => ["ad_dc_ntvfs"], 2059 promoted_dc => ["ad_dc_ntvfs"], 2060 2061 rodc => ["ad_dc_ntvfs"], 2062 rpc_proxy => ["ad_dc_ntvfs"], 2063 chgdcpass => ["dns_hub"], 2064 2065 s4member_dflt_domain => ["ad_dc_ntvfs"], 2066 s4member => ["ad_dc_ntvfs"], 2067 2068 # envs that test the server process model 2069 proclimitdc => ["dns_hub"], 2070 preforkrestartdc => ["dns_hub"], 2071 2072 # backup/restore testenvs 2073 backupfromdc => ["dns_hub"], 2074 customdc => ["dns_hub"], 2075 restoredc => ["backupfromdc"], 2076 renamedc => ["backupfromdc"], 2077 offlinebackupdc => ["backupfromdc"], 2078 labdc => ["backupfromdc"], 2079 2080 # aliases in order to split autbuild tasks 2081 fl2008dc => ["ad_dc"], 2082 ad_dc_default => ["ad_dc"], 2083 ad_dc_slowtests => ["ad_dc"], 2084 ad_dc_backup => ["ad_dc"], 2085 2086 schema_dc => ["dns_hub"], 2087 schema_pair_dc => ["schema_dc"], 2088 2089 none => [], 2090); 2091 2092%Samba4::ENV_DEPS_POST = ( 2093 schema_dc => ["schema_pair_dc"], 2094); 2095 2096sub return_alias_env 2097{ 2098 my ($self, $path, $env) = @_; 2099 2100 # just an alias 2101 return $env; 2102} 2103 2104sub setup_fl2008dc 2105{ 2106 my ($self, $path) = @_; 2107 2108 my $extra_args = ["--base-schema=2008_R2"]; 2109 my $env = $self->provision_ad_dc_ntvfs($path, $extra_args); 2110 if (defined $env) { 2111 if (not defined($self->check_or_start($env, "standard"))) { 2112 warn("Failed to start fl2008dc"); 2113 return undef; 2114 } 2115 } 2116 return $env; 2117} 2118 2119sub setup_ad_dc_default 2120{ 2121 my ($self, $path, $dep_env) = @_; 2122 return $self->return_alias_env($path, $dep_env) 2123} 2124 2125sub setup_ad_dc_slowtests 2126{ 2127 my ($self, $path, $dep_env) = @_; 2128 return $self->return_alias_env($path, $dep_env) 2129} 2130 2131sub setup_ad_dc_backup 2132{ 2133 my ($self, $path, $dep_env) = @_; 2134 return $self->return_alias_env($path, $dep_env) 2135} 2136 2137sub setup_s4member 2138{ 2139 my ($self, $path, $dc_vars) = @_; 2140 2141 my $env = $self->provision_s4member($path, $dc_vars, "s4member"); 2142 2143 if (defined $env) { 2144 if (not defined($self->check_or_start($env, "standard"))) { 2145 return undef; 2146 } 2147 } 2148 2149 return $env; 2150} 2151 2152sub setup_s4member_dflt_domain 2153{ 2154 my ($self, $path, $dc_vars) = @_; 2155 2156 my $env = $self->provision_s4member($path, $dc_vars, "s4member_dflt", 2157 "winbind use default domain = yes"); 2158 2159 if (defined $env) { 2160 if (not defined($self->check_or_start($env, "standard"))) { 2161 return undef; 2162 } 2163 } 2164 2165 return $env; 2166} 2167 2168sub setup_rpc_proxy 2169{ 2170 my ($self, $path, $dc_vars) = @_; 2171 2172 my $env = $self->provision_rpc_proxy($path, $dc_vars); 2173 2174 if (defined $env) { 2175 if (not defined($self->check_or_start($env, "standard"))) { 2176 return undef; 2177 } 2178 } 2179 return $env; 2180} 2181 2182sub setup_ad_dc_ntvfs 2183{ 2184 my ($self, $path) = @_; 2185 2186 my $env = $self->provision_ad_dc_ntvfs($path, undef); 2187 if (defined $env) { 2188 if (not defined($self->check_or_start($env, "standard"))) { 2189 warn("Failed to start ad_dc_ntvfs"); 2190 return undef; 2191 } 2192 } 2193 return $env; 2194} 2195 2196sub setup_chgdcpass 2197{ 2198 my ($self, $path) = @_; 2199 2200 my $env = $self->provision_chgdcpass($path); 2201 if (defined $env) { 2202 if (not defined($self->check_or_start($env, "standard"))) { 2203 return undef; 2204 } 2205 } 2206 return $env; 2207} 2208 2209sub setup_fl2000dc 2210{ 2211 my ($self, $path) = @_; 2212 2213 my $env = $self->provision_fl2000dc($path); 2214 if (defined $env) { 2215 if (not defined($self->check_or_start($env, "standard"))) { 2216 return undef; 2217 } 2218 } 2219 2220 return $env; 2221} 2222 2223sub setup_fl2003dc 2224{ 2225 my ($self, $path, $dc_vars) = @_; 2226 2227 my $env = $self->provision_fl2003dc($path); 2228 2229 if (defined $env) { 2230 if (not defined($self->check_or_start($env, "standard"))) { 2231 return undef; 2232 } 2233 2234 $env = $self->setup_trust($env, $dc_vars, "external", "--no-aes-keys"); 2235 } 2236 return $env; 2237} 2238 2239sub setup_fl2008r2dc 2240{ 2241 my ($self, $path, $dc_vars) = @_; 2242 2243 my $env = $self->provision_fl2008r2dc($path); 2244 2245 if (defined $env) { 2246 if (not defined($self->check_or_start($env, "standard"))) { 2247 return undef; 2248 } 2249 2250 my $upn_array = ["$env->{REALM}.upn"]; 2251 my $spn_array = ["$env->{REALM}.spn"]; 2252 2253 $self->setup_namespaces($env, $upn_array, $spn_array); 2254 2255 $env = $self->setup_trust($env, $dc_vars, "forest", ""); 2256 } 2257 2258 return $env; 2259} 2260 2261sub setup_vampire_dc 2262{ 2263 return setup_generic_vampire_dc(@_, "2008"); 2264} 2265 2266sub setup_vampire_2000_dc 2267{ 2268 return setup_generic_vampire_dc(@_, "2000"); 2269} 2270 2271sub setup_generic_vampire_dc 2272{ 2273 my ($self, $path, $dc_vars, $fl) = @_; 2274 2275 my $env = $self->provision_vampire_dc($path, $dc_vars, $fl); 2276 2277 if (defined $env) { 2278 if (not defined($self->check_or_start($env, "single"))) { 2279 return undef; 2280 } 2281 2282 # force replicated DC to update repsTo/repsFrom 2283 # for vampired partitions 2284 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 2285 2286 # as 'vampired' dc may add data in its local replica 2287 # we need to synchronize data between DCs 2288 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM})); 2289 my $cmd = $self->get_cmd_env_vars($env); 2290 $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}"; 2291 $cmd .= " $dc_vars->{CONFIGURATION}"; 2292 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}"; 2293 # replicate Configuration NC 2294 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\""; 2295 unless(system($cmd_repl) == 0) { 2296 warn("Failed to replicate\n$cmd_repl"); 2297 return undef; 2298 } 2299 # replicate Default NC 2300 $cmd_repl = "$cmd \"$base_dn\""; 2301 unless(system($cmd_repl) == 0) { 2302 warn("Failed to replicate\n$cmd_repl"); 2303 return undef; 2304 } 2305 2306 # Pull in a full set of changes from the main DC 2307 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM})); 2308 $cmd = $self->get_cmd_env_vars($env); 2309 $cmd .= " $samba_tool drs replicate $env->{SERVER} $env->{DC_SERVER}"; 2310 $cmd .= " $dc_vars->{CONFIGURATION}"; 2311 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}"; 2312 # replicate Configuration NC 2313 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\""; 2314 unless(system($cmd_repl) == 0) { 2315 warn("Failed to replicate\n$cmd_repl"); 2316 return undef; 2317 } 2318 # replicate Default NC 2319 $cmd_repl = "$cmd \"$base_dn\""; 2320 unless(system($cmd_repl) == 0) { 2321 warn("Failed to replicate\n$cmd_repl"); 2322 return undef; 2323 } 2324 } 2325 2326 return $env; 2327} 2328 2329sub setup_promoted_dc 2330{ 2331 my ($self, $path, $dc_vars) = @_; 2332 2333 my $env = $self->provision_promoted_dc($path, $dc_vars); 2334 2335 if (defined $env) { 2336 if (not defined($self->check_or_start($env, "single"))) { 2337 return undef; 2338 } 2339 2340 # force source and replicated DC to update repsTo/repsFrom 2341 # for vampired partitions 2342 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 2343 my $cmd = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' "; 2344 # as 'vampired' dc may add data in its local replica 2345 # we need to synchronize data between DCs 2346 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM})); 2347 $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\""; 2348 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\""; 2349 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" "; 2350 $cmd .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" "; 2351 $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}"; 2352 $cmd .= " $dc_vars->{CONFIGURATION}"; 2353 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}"; 2354 # replicate Configuration NC 2355 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\""; 2356 unless(system($cmd_repl) == 0) { 2357 warn("Failed to replicate\n$cmd_repl"); 2358 return undef; 2359 } 2360 # replicate Default NC 2361 $cmd_repl = "$cmd \"$base_dn\""; 2362 unless(system($cmd_repl) == 0) { 2363 warn("Failed to replicate\n$cmd_repl"); 2364 return undef; 2365 } 2366 } 2367 2368 return $env; 2369} 2370 2371sub setup_rodc 2372{ 2373 my ($self, $path, $dc_vars) = @_; 2374 2375 my $env = $self->provision_rodc($path, $dc_vars); 2376 2377 unless ($env) { 2378 return undef; 2379 } 2380 2381 if (not defined($self->check_or_start($env, "standard"))) { 2382 return undef; 2383 } 2384 2385 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 2386 my $cmd = ""; 2387 2388 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM})); 2389 $cmd .= "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' "; 2390 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\""; 2391 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\""; 2392 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" "; 2393 $cmd .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" "; 2394 $cmd .= " $samba_tool drs replicate $env->{SERVER} $env->{DC_SERVER}"; 2395 $cmd .= " $dc_vars->{CONFIGURATION}"; 2396 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}"; 2397 # replicate Configuration NC 2398 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\""; 2399 unless(system($cmd_repl) == 0) { 2400 warn("Failed to replicate\n$cmd_repl"); 2401 return undef; 2402 } 2403 # replicate Default NC 2404 $cmd_repl = "$cmd \"$base_dn\""; 2405 unless(system($cmd_repl) == 0) { 2406 warn("Failed to replicate\n$cmd_repl"); 2407 return undef; 2408 } 2409 2410 return $env; 2411} 2412 2413sub setup_ad_dc 2414{ 2415 my ($self, $path) = @_; 2416 2417 # If we didn't build with ADS, pretend this env was never available 2418 if (not $self->{target3}->have_ads()) { 2419 return "UNKNOWN"; 2420 } 2421 2422 my $env = $self->provision_ad_dc($path, "addc", "ADDOMAIN", 2423 "addom.samba.example.com", "", undef); 2424 unless ($env) { 2425 return undef; 2426 } 2427 2428 if (not defined($self->check_or_start($env, "prefork"))) { 2429 return undef; 2430 } 2431 2432 my $upn_array = ["$env->{REALM}.upn"]; 2433 my $spn_array = ["$env->{REALM}.spn"]; 2434 2435 $self->setup_namespaces($env, $upn_array, $spn_array); 2436 2437 return $env; 2438} 2439 2440sub setup_ad_dc_no_nss 2441{ 2442 my ($self, $path) = @_; 2443 2444 # If we didn't build with ADS, pretend this env was never available 2445 if (not $self->{target3}->have_ads()) { 2446 return "UNKNOWN"; 2447 } 2448 2449 my $env = $self->provision_ad_dc($path, "addc_no_nss", "ADNONSSDOMAIN", 2450 "adnonssdom.samba.example.com", "", undef); 2451 unless ($env) { 2452 return undef; 2453 } 2454 2455 $env->{NSS_WRAPPER_MODULE_SO_PATH} = undef; 2456 $env->{NSS_WRAPPER_MODULE_FN_PREFIX} = undef; 2457 2458 if (not defined($self->check_or_start($env, "single"))) { 2459 return undef; 2460 } 2461 2462 my $upn_array = ["$env->{REALM}.upn"]; 2463 my $spn_array = ["$env->{REALM}.spn"]; 2464 2465 $self->setup_namespaces($env, $upn_array, $spn_array); 2466 2467 return $env; 2468} 2469 2470sub setup_ad_dc_no_ntlm 2471{ 2472 my ($self, $path) = @_; 2473 2474 # If we didn't build with ADS, pretend this env was never available 2475 if (not $self->{target3}->have_ads()) { 2476 return "UNKNOWN"; 2477 } 2478 2479 my $env = $self->provision_ad_dc($path, "addc_no_ntlm", "ADNONTLMDOMAIN", 2480 "adnontlmdom.samba.example.com", 2481 "ntlm auth = disabled", undef); 2482 unless ($env) { 2483 return undef; 2484 } 2485 2486 if (not defined($self->check_or_start($env, "prefork"))) { 2487 return undef; 2488 } 2489 2490 my $upn_array = ["$env->{REALM}.upn"]; 2491 my $spn_array = ["$env->{REALM}.spn"]; 2492 2493 $self->setup_namespaces($env, $upn_array, $spn_array); 2494 2495 return $env; 2496} 2497 2498# 2499# AD DC test environment used solely to test pre-fork process restarts. 2500# As processes get killed off and restarted it should not be used for other 2501sub setup_preforkrestartdc 2502{ 2503 my ($self, $path) = @_; 2504 2505 # If we didn't build with ADS, pretend this env was never available 2506 if (not $self->{target3}->have_ads()) { 2507 return "UNKNOWN"; 2508 } 2509 2510 # note DC name must be <= 15 chars so we use 'prockill' instead of 2511 # 'preforkrestart' 2512 my $env = $self->provision_ad_dc( 2513 $path, 2514 "prockilldc", 2515 "PROCKILLDOMAIN", 2516 "prockilldom.samba.example.com", 2517 "prefork backoff increment = 5\nprefork maximum backoff=10"); 2518 unless ($env) { 2519 return undef; 2520 } 2521 2522 $env->{NSS_WRAPPER_MODULE_SO_PATH} = undef; 2523 $env->{NSS_WRAPPER_MODULE_FN_PREFIX} = undef; 2524 2525 if (not defined($self->check_or_start($env, "prefork"))) { 2526 return undef; 2527 } 2528 2529 my $upn_array = ["$env->{REALM}.upn"]; 2530 my $spn_array = ["$env->{REALM}.spn"]; 2531 2532 $self->setup_namespaces($env, $upn_array, $spn_array); 2533 2534 return $env; 2535} 2536 2537# 2538# ad_dc test environment used solely to test standard process model connection 2539# process limits. As the limit is set artificially low it should not be used 2540# for other tests. 2541sub setup_proclimitdc 2542{ 2543 my ($self, $path) = @_; 2544 2545 # If we didn't build with ADS, pretend this env was never available 2546 if (not $self->{target3}->have_ads()) { 2547 return "UNKNOWN"; 2548 } 2549 2550 my $env = $self->provision_ad_dc( 2551 $path, 2552 "proclimitdc", 2553 "PROCLIMITDOM", 2554 "proclimit.samba.example.com", 2555 "max smbd processes = 20"); 2556 unless ($env) { 2557 return undef; 2558 } 2559 2560 $env->{NSS_WRAPPER_MODULE_SO_PATH} = undef; 2561 $env->{NSS_WRAPPER_MODULE_FN_PREFIX} = undef; 2562 2563 if (not defined($self->check_or_start($env, "standard"))) { 2564 return undef; 2565 } 2566 2567 my $upn_array = ["$env->{REALM}.upn"]; 2568 my $spn_array = ["$env->{REALM}.spn"]; 2569 2570 $self->setup_namespaces($env, $upn_array, $spn_array); 2571 2572 return $env; 2573} 2574 2575# Used to test a live upgrade of the schema on a 2 DC network. 2576sub setup_schema_dc 2577{ 2578 my ($self, $path) = @_; 2579 2580 # provision the PDC using an older base schema 2581 my $provision_args = ["--base-schema=2008_R2", "--backend-store=mdb"]; 2582 2583 my $env = $self->provision_ad_dc($path, "liveupgrade1dc", "SCHEMADOMAIN", 2584 "schema.samba.example.com", 2585 "drs: max link sync = 2", 2586 $provision_args); 2587 unless ($env) { 2588 return undef; 2589 } 2590 2591 if (not defined($self->check_or_start($env, "prefork"))) { 2592 return undef; 2593 } 2594 2595 my $upn_array = ["$env->{REALM}.upn"]; 2596 my $spn_array = ["$env->{REALM}.spn"]; 2597 2598 $self->setup_namespaces($env, $upn_array, $spn_array); 2599 2600 return $env; 2601} 2602 2603# the second DC in the live schema upgrade pair 2604sub setup_schema_pair_dc 2605{ 2606 # note: dcvars contains the env info for the dependent testenv ('schema_dc') 2607 my ($self, $prefix, $dcvars) = @_; 2608 print "Preparing SCHEMA UPGRADE PAIR DC...\n"; 2609 2610 my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "liveupgrade2dc", 2611 $dcvars->{DOMAIN}, 2612 $dcvars->{REALM}, 2613 $dcvars->{PASSWORD}, 2614 ""); 2615 2616 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 2617 my $cmd_vars = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' "; 2618 $cmd_vars .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; 2619 if (defined($env->{RESOLV_WRAPPER_CONF})) { 2620 $cmd_vars .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" "; 2621 } else { 2622 $cmd_vars .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" "; 2623 } 2624 $cmd_vars .= "KRB5_CONFIG=\"$env->{KRB5_CONFIG}\" "; 2625 $cmd_vars .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" "; 2626 $cmd_vars .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" "; 2627 2628 my $join_cmd = $cmd_vars; 2629 $join_cmd .= "$samba_tool domain join $env->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}"; 2630 $join_cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD} "; 2631 $join_cmd .= " --backend-store=mdb"; 2632 2633 my $upgrade_cmd = $cmd_vars; 2634 $upgrade_cmd .= "$samba_tool domain schemaupgrade $dcvars->{CONFIGURATION}"; 2635 $upgrade_cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}"; 2636 2637 my $repl_cmd = $cmd_vars; 2638 $repl_cmd .= "$samba_tool drs replicate $env->{SERVER} $dcvars->{SERVER}"; 2639 $repl_cmd .= " CN=Schema,CN=Configuration,DC=schema,DC=samba,DC=example,DC=com"; 2640 $repl_cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}"; 2641 2642 unless (system($join_cmd) == 0) { 2643 warn("Join failed\n$join_cmd"); 2644 return undef; 2645 } 2646 2647 $env->{DC_SERVER} = $dcvars->{SERVER}; 2648 $env->{DC_SERVER_IP} = $dcvars->{SERVER_IP}; 2649 $env->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6}; 2650 $env->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME}; 2651 2652 # start samba for the new DC 2653 if (not defined($self->check_or_start($env, "standard"))) { 2654 return undef; 2655 } 2656 2657 unless (system($upgrade_cmd) == 0) { 2658 warn("Schema upgrade failed\n$upgrade_cmd"); 2659 return undef; 2660 } 2661 2662 unless (system($repl_cmd) == 0) { 2663 warn("Post-update schema replication failed\n$repl_cmd"); 2664 return undef; 2665 } 2666 2667 return $env; 2668} 2669 2670# Sets up a DC that's solely used to do a domain backup from. We then use the 2671# backupfrom-DC to create the restore-DC - this proves that the backup/restore 2672# process will create a Samba DC that will actually start up. 2673# We don't use the backup-DC for anything else because its domain will conflict 2674# with the restore DC. 2675sub setup_backupfromdc 2676{ 2677 my ($self, $path) = @_; 2678 2679 # If we didn't build with ADS, pretend this env was never available 2680 if (not $self->{target3}->have_ads()) { 2681 return "UNKNOWN"; 2682 } 2683 2684 my $provision_args = ["--site=Backup-Site"]; 2685 2686 my $env = $self->provision_ad_dc($path, "backupfromdc", "BACKUPDOMAIN", 2687 "backupdom.samba.example.com", 2688 "samba kcc command = /bin/true", 2689 $provision_args); 2690 unless ($env) { 2691 return undef; 2692 } 2693 2694 if (not defined($self->check_or_start($env))) { 2695 return undef; 2696 } 2697 2698 my $upn_array = ["$env->{REALM}.upn"]; 2699 my $spn_array = ["$env->{REALM}.spn"]; 2700 2701 $self->setup_namespaces($env, $upn_array, $spn_array); 2702 2703 # Set up a dangling forward link to an expunged object 2704 # 2705 # We need this to ensure that the "samba-tool domain backup rename" 2706 # that is part of the creation of the labdc environment can 2707 # cope with this situation on the source DC. 2708 2709 if (not $self->write_ldb_file("$env->{PRIVATEDIR}/sam.ldb", " 2710dn: ou=linktest,dc=backupdom,dc=samba,dc=example,dc=com 2711objectclass: organizationalUnit 2712- 2713 2714dn: cn=linkto,ou=linktest,dc=backupdom,dc=samba,dc=example,dc=com 2715objectclass: msExchConfigurationContainer 2716- 2717 2718dn: cn=linkfrom,ou=linktest,dc=backupdom,dc=samba,dc=example,dc=com 2719objectclass: msExchConfigurationContainer 2720addressBookRoots: cn=linkto,ou=linktest,dc=backupdom,dc=samba,dc=example,dc=com 2721- 2722 2723")) { 2724 return undef; 2725 } 2726 my $ldbdel = Samba::bindir_path($self, "ldbdel"); 2727 my $cmd = "$ldbdel -H $env->{PRIVATEDIR}/sam.ldb cn=linkto,ou=linktest,dc=backupdom,dc=samba,dc=example,dc=com"; 2728 2729 unless(system($cmd) == 0) { 2730 warn("Failed to delete link target: \n$cmd"); 2731 return undef; 2732 } 2733 2734 # Expunge will ensure that linkto is totally wiped from the DB 2735 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 2736 $cmd = "$samba_tool domain tombstones expunge --tombstone-lifetime=0 $env->{CONFIGURATION}"; 2737 2738 unless(system($cmd) == 0) { 2739 warn("Failed to expunge link target: \n$cmd"); 2740 return undef; 2741 } 2742 return $env; 2743} 2744 2745# returns the server/user-auth params needed to run an online backup cmd 2746sub get_backup_server_args 2747{ 2748 # dcvars contains the env info for the backup DC testenv 2749 my ($self, $dcvars) = @_; 2750 my $server = $dcvars->{DC_SERVER_IP}; 2751 my $server_args = "--server=$server "; 2752 $server_args .= "-U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}"; 2753 $server_args .= " $dcvars->{CONFIGURATION}"; 2754 2755 return $server_args; 2756} 2757 2758# Creates a backup of a running testenv DC 2759sub create_backup 2760{ 2761 # note: dcvars contains the env info for the backup DC testenv 2762 my ($self, $env, $dcvars, $backupdir, $backup_cmd) = @_; 2763 2764 # get all the env variables we pass in with the samba-tool command 2765 my $cmd_env = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' "; 2766 $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; 2767 if (defined($env->{RESOLV_WRAPPER_CONF})) { 2768 $cmd_env .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" "; 2769 } else { 2770 $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" "; 2771 } 2772 # Note: use the backupfrom-DC's krb5.conf to do the backup 2773 $cmd_env .= " KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" "; 2774 $cmd_env .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" "; 2775 2776 # use samba-tool to create a backup from the 'backupfromdc' DC 2777 my $cmd = ""; 2778 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 2779 2780 $cmd .= "$cmd_env $samba_tool domain backup $backup_cmd"; 2781 $cmd .= " --targetdir=$backupdir"; 2782 2783 print "Executing: $cmd\n"; 2784 unless(system($cmd) == 0) { 2785 warn("Failed to create backup using: \n$cmd"); 2786 return undef; 2787 } 2788 2789 # get the name of the backup file created 2790 opendir(DIR, $backupdir); 2791 my @files = grep(/\.tar/, readdir(DIR)); 2792 closedir(DIR); 2793 2794 if(scalar @files != 1) { 2795 warn("Backup file not found in directory $backupdir\n"); 2796 return undef; 2797 } 2798 my $backup_file = "$backupdir/$files[0]"; 2799 print "Using backup file $backup_file...\n"; 2800 2801 return $backup_file; 2802} 2803 2804# Restores a backup-file to populate a testenv for a new DC 2805sub restore_backup_file 2806{ 2807 my ($self, $backup_file, $restore_opts, $restoredir, $smbconf) = @_; 2808 2809 # pass the restore command the testenv's smb.conf that we've already 2810 # generated. But move it to a temp-dir first, so that the restore doesn't 2811 # overwrite it 2812 my $tmpdir = File::Temp->newdir(); 2813 my $tmpconf = "$tmpdir/smb.conf"; 2814 my $cmd = "cp $smbconf $tmpconf"; 2815 unless(system($cmd) == 0) { 2816 warn("Failed to backup smb.conf using: \n$cmd"); 2817 return -1; 2818 } 2819 2820 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 2821 $cmd = "$samba_tool domain backup restore --backup-file=$backup_file"; 2822 $cmd .= " --targetdir=$restoredir $restore_opts --configfile=$tmpconf"; 2823 2824 print "Executing: $cmd\n"; 2825 unless(system($cmd) == 0) { 2826 warn("Failed to restore backup using: \n$cmd"); 2827 return -1; 2828 } 2829 2830 print "Restore complete\n"; 2831 return 0 2832} 2833 2834# sets up the initial directory and returns the new testenv's env info 2835# (without actually doing a 'domain join') 2836sub prepare_dc_testenv 2837{ 2838 my ($self, $prefix, $dcname, $domain, $realm, 2839 $password, $conf_options) = @_; 2840 2841 my $ctx = $self->provision_raw_prepare($prefix, "domain controller", 2842 $dcname, 2843 $domain, 2844 $realm, 2845 undef, 2846 "2008", 2847 $password, 2848 undef, 2849 undef); 2850 2851 # the restore uses a slightly different state-dir location to other testenvs 2852 $ctx->{statedir} = "$ctx->{prefix_abs}/state"; 2853 push(@{$ctx->{directories}}, "$ctx->{statedir}"); 2854 2855 # add support for sysvol/netlogon/tmp shares 2856 $ctx->{share} = "$ctx->{prefix_abs}/share"; 2857 push(@{$ctx->{directories}}, "$ctx->{share}"); 2858 push(@{$ctx->{directories}}, "$ctx->{share}/test1"); 2859 2860 $ctx->{smb_conf_extra_options} = " 2861 $conf_options 2862 max xmit = 32K 2863 server max protocol = SMB2 2864 samba kcc command = /bin/true 2865 xattr_tdb:file = $ctx->{statedir}/xattr.tdb 2866 2867[sysvol] 2868 path = $ctx->{statedir}/sysvol 2869 read only = no 2870 2871[netlogon] 2872 path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts 2873 read only = no 2874 2875[tmp] 2876 path = $ctx->{share} 2877 read only = no 2878 posix:sharedelay = 10000 2879 posix:oplocktimeout = 3 2880 posix:writetimeupdatedelay = 50000 2881 2882[test1] 2883 path = $ctx->{share}/test1 2884 read only = no 2885 posix:sharedelay = 100000 2886 posix:oplocktimeout = 3 2887 posix:writetimeupdatedelay = 500000 2888"; 2889 2890 my $env = $self->provision_raw_step1($ctx); 2891 2892 return ($env, $ctx); 2893} 2894 2895 2896# Set up a DC testenv solely by using the samba-tool domain backup/restore 2897# commands. This proves that we can backup an online DC ('backupfromdc') and 2898# use the backup file to create a valid, working samba DC. 2899sub setup_restoredc 2900{ 2901 # note: dcvars contains the env info for the dependent testenv ('backupfromdc') 2902 my ($self, $prefix, $dcvars) = @_; 2903 print "Preparing RESTORE DC...\n"; 2904 2905 # we arbitrarily designate the restored DC as having SMBv1 disabled 2906 my $extra_conf = " 2907 server min protocol = SMB2 2908 client min protocol = SMB2 2909 prefork children = 1"; 2910 2911 my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "restoredc", 2912 $dcvars->{DOMAIN}, 2913 $dcvars->{REALM}, 2914 $dcvars->{PASSWORD}, 2915 $extra_conf); 2916 2917 # create a backup of the 'backupfromdc' 2918 my $backupdir = File::Temp->newdir(); 2919 my $server_args = $self->get_backup_server_args($dcvars); 2920 my $backup_args = "online $server_args"; 2921 my $backup_file = $self->create_backup($env, $dcvars, $backupdir, 2922 $backup_args); 2923 unless($backup_file) { 2924 return undef; 2925 } 2926 2927 # restore the backup file to populate the restore-DC testenv 2928 my $restore_dir = abs_path($prefix); 2929 my $ret = $self->restore_backup_file($backup_file, 2930 "--newservername=$env->{SERVER}", 2931 $restore_dir, $env->{SERVERCONFFILE}); 2932 unless ($ret == 0) { 2933 return undef; 2934 } 2935 2936 # start samba for the restored DC 2937 if (not defined($self->check_or_start($env))) { 2938 return undef; 2939 } 2940 2941 return $env; 2942} 2943 2944# Set up a DC testenv solely by using the 'samba-tool domain backup rename' and 2945# restore commands. This proves that we can backup and rename an online DC 2946# ('backupfromdc') and use the backup file to create a valid, working samba DC. 2947sub setup_renamedc 2948{ 2949 # note: dcvars contains the env info for the dependent testenv ('backupfromdc') 2950 my ($self, $prefix, $dcvars) = @_; 2951 print "Preparing RENAME DC...\n"; 2952 my $extra_conf = "prefork children = 1"; 2953 2954 my $realm = "renamedom.samba.example.com"; 2955 my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "renamedc", 2956 "RENAMEDOMAIN", $realm, 2957 $dcvars->{PASSWORD}, $extra_conf); 2958 2959 # create a backup of the 'backupfromdc' which renames the domain 2960 my $backupdir = File::Temp->newdir(); 2961 my $server_args = $self->get_backup_server_args($dcvars); 2962 my $backup_args = "rename $env->{DOMAIN} $env->{REALM} $server_args"; 2963 $backup_args .= " --backend-store=tdb"; 2964 my $backup_file = $self->create_backup($env, $dcvars, $backupdir, 2965 $backup_args); 2966 unless($backup_file) { 2967 return undef; 2968 } 2969 2970 # restore the backup file to populate the rename-DC testenv 2971 my $restore_dir = abs_path($prefix); 2972 my $restore_opts = "--newservername=$env->{SERVER} --host-ip=$env->{SERVER_IP}"; 2973 my $ret = $self->restore_backup_file($backup_file, $restore_opts, 2974 $restore_dir, $env->{SERVERCONFFILE}); 2975 unless ($ret == 0) { 2976 return undef; 2977 } 2978 2979 # start samba for the restored DC 2980 if (not defined($self->check_or_start($env))) { 2981 return undef; 2982 } 2983 2984 my $upn_array = ["$env->{REALM}.upn"]; 2985 my $spn_array = ["$env->{REALM}.spn"]; 2986 2987 $self->setup_namespaces($env, $upn_array, $spn_array); 2988 2989 return $env; 2990} 2991 2992# Set up a DC testenv solely by using the 'samba-tool domain backup offline' and 2993# restore commands. This proves that we do an offline backup of a local DC 2994# ('backupfromdc') and use the backup file to create a valid, working samba DC. 2995sub setup_offlinebackupdc 2996{ 2997 # note: dcvars contains the env info for the dependent testenv ('backupfromdc') 2998 my ($self, $prefix, $dcvars) = @_; 2999 print "Preparing OFFLINE BACKUP DC...\n"; 3000 my $extra_conf = "prefork children = 1"; 3001 3002 my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "offlinebackupdc", 3003 $dcvars->{DOMAIN}, 3004 $dcvars->{REALM}, 3005 $dcvars->{PASSWORD}, $extra_conf); 3006 3007 # create an offline backup of the 'backupfromdc' target 3008 my $backupdir = File::Temp->newdir(); 3009 my $cmd = "offline -s $dcvars->{SERVERCONFFILE}"; 3010 my $backup_file = $self->create_backup($env, $dcvars, 3011 $backupdir, $cmd); 3012 3013 unless($backup_file) { 3014 return undef; 3015 } 3016 3017 # restore the backup file to populate the rename-DC testenv 3018 my $restore_dir = abs_path($prefix); 3019 my $restore_opts = "--newservername=$env->{SERVER} --host-ip=$env->{SERVER_IP}"; 3020 my $ret = $self->restore_backup_file($backup_file, $restore_opts, 3021 $restore_dir, $env->{SERVERCONFFILE}); 3022 unless ($ret == 0) { 3023 return undef; 3024 } 3025 3026 # re-create the testenv's krb5.conf (the restore may have overwritten it) 3027 Samba::mk_krb5_conf($ctx); 3028 3029 # start samba for the restored DC 3030 if (not defined($self->check_or_start($env))) { 3031 return undef; 3032 } 3033 3034 return $env; 3035} 3036 3037# Set up a DC testenv solely by using the samba-tool 'domain backup rename' and 3038# restore commands, using the --no-secrets option. This proves that we can 3039# create a realistic lab environment from an online DC ('backupfromdc'). 3040sub setup_labdc 3041{ 3042 # note: dcvars contains the env info for the dependent testenv ('backupfromdc') 3043 my ($self, $prefix, $dcvars) = @_; 3044 print "Preparing LAB-DOMAIN DC...\n"; 3045 my $extra_conf = "prefork children = 1"; 3046 3047 my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "labdc", 3048 "LABDOMAIN", 3049 "labdom.samba.example.com", 3050 $dcvars->{PASSWORD}, $extra_conf); 3051 3052 # create a backup of the 'backupfromdc' which renames the domain and uses 3053 # the --no-secrets option to scrub any sensitive info 3054 my $backupdir = File::Temp->newdir(); 3055 my $server_args = $self->get_backup_server_args($dcvars); 3056 my $backup_args = "rename $env->{DOMAIN} $env->{REALM} $server_args"; 3057 $backup_args .= " --no-secrets --backend-store=mdb"; 3058 my $backup_file = $self->create_backup($env, $dcvars, $backupdir, 3059 $backup_args); 3060 unless($backup_file) { 3061 return undef; 3062 } 3063 3064 # restore the backup file to populate the lab-DC testenv 3065 my $restore_dir = abs_path($prefix); 3066 my $restore_opts = "--newservername=$env->{SERVER} --host-ip=$env->{SERVER_IP}"; 3067 my $ret = $self->restore_backup_file($backup_file, $restore_opts, 3068 $restore_dir, $env->{SERVERCONFFILE}); 3069 unless ($ret == 0) { 3070 return undef; 3071 } 3072 3073 # because we don't include any secrets in the backup, we need to reset the 3074 # admin user's password back to what the testenv expects 3075 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 3076 my $cmd = "$samba_tool user setpassword $env->{USERNAME} "; 3077 $cmd .= "--newpassword=$env->{PASSWORD} -H $restore_dir/private/sam.ldb"; 3078 $cmd .= " $env->{CONFIGURATION}"; 3079 3080 unless(system($cmd) == 0) { 3081 warn("Failed to reset admin's password: \n$cmd"); 3082 return undef; 3083 } 3084 3085 # start samba for the restored DC 3086 if (not defined($self->check_or_start($env))) { 3087 return undef; 3088 } 3089 3090 my $upn_array = ["$env->{REALM}.upn"]; 3091 my $spn_array = ["$env->{REALM}.spn"]; 3092 3093 $self->setup_namespaces($env, $upn_array, $spn_array); 3094 3095 return $env; 3096} 3097 3098# Inspects a backup *.tar.bz2 file and determines the realm/domain it contains 3099sub get_backup_domain_realm 3100{ 3101 my ($self, $backup_file) = @_; 3102 3103 print "Determining REALM/DOMAIN values in backup...\n"; 3104 3105 # The backup will have the correct domain/realm values in the smb.conf. 3106 # So we can work out the env variables the testenv should use based on 3107 # that. Let's start by extracting the smb.conf 3108 my $tar = Archive::Tar->new($backup_file); 3109 my $tmpdir = File::Temp->newdir(); 3110 my $smbconf = "$tmpdir/smb.conf"; 3111 3112 # note that the filepaths within the tar-file differ slightly for online 3113 # and offline backups 3114 if ($tar->contains_file("etc/smb.conf")) { 3115 $tar->extract_file("etc/smb.conf", $smbconf); 3116 } elsif ($tar->contains_file("./etc/smb.conf")) { 3117 $tar->extract_file("./etc/smb.conf", $smbconf); 3118 } else { 3119 warn("Could not find smb.conf in $backup_file"); 3120 return undef, undef; 3121 } 3122 3123 # make sure we don't try to create locks/sockets in the default install 3124 # location (i.e. /usr/local/samba/) 3125 my $options = "--option=\"private dir = $tmpdir\""; 3126 $options .= " --option=\"lock dir = $tmpdir\""; 3127 3128 # now use testparm to read the values we're interested in 3129 my $testparm = Samba::bindir_path($self, "testparm"); 3130 my $domain = `$testparm $smbconf -sl --parameter-name=WORKGROUP $options`; 3131 my $realm = `$testparm $smbconf -sl --parameter-name=REALM $options`; 3132 chomp $realm; 3133 chomp $domain; 3134 print "Backup-file REALM is $realm, DOMAIN is $domain\n"; 3135 3136 return ($domain, $realm); 3137} 3138 3139# This spins up a custom testenv that can be based on any backup-file you want. 3140# This is just intended for manual testing (rather than automated test-cases) 3141sub setup_customdc 3142{ 3143 my ($self, $prefix) = @_; 3144 print "Preparing CUSTOM RESTORE DC...\n"; 3145 my $dc_name = "customdc"; 3146 my $password = "locDCpass1"; 3147 my $backup_file = $ENV{'BACKUP_FILE'}; 3148 3149 # user must specify a backup file to restore via an ENV variable, i.e. 3150 # BACKUP_FILE=backup-blah.tar.bz2 SELFTEST_TESTENV=customdc make testenv 3151 if (not defined($backup_file)) { 3152 warn("Please specify BACKUP_FILE"); 3153 return undef; 3154 } 3155 3156 # work out the correct domain/realm env values from the backup-file 3157 my ($domain, $realm) = $self->get_backup_domain_realm($backup_file); 3158 if ($domain eq '' or $realm eq '') { 3159 warn("Could not determine domain or realm"); 3160 return undef; 3161 } 3162 3163 # create a placeholder directory and smb.conf, as well as the env vars. 3164 my ($env, $ctx) = $self->prepare_dc_testenv($prefix, $dc_name, 3165 $domain, $realm, $password, ""); 3166 3167 # restore the specified backup file to populate the testenv 3168 my $restore_dir = abs_path($prefix); 3169 my $ret = $self->restore_backup_file($backup_file, 3170 "--newservername=$env->{SERVER}", 3171 $restore_dir, $env->{SERVERCONFFILE}); 3172 unless ($ret == 0) { 3173 return undef; 3174 } 3175 3176 # Change the admin password to the testenv default, just in case it's 3177 # different, or in case this was a --no-secrets backup 3178 my $samba_tool = Samba::bindir_path($self, "samba-tool"); 3179 my $cmd = "$samba_tool user setpassword $env->{USERNAME} "; 3180 $cmd .= "--newpassword=$password -H $restore_dir/private/sam.ldb"; 3181 $cmd .= " $env->{CONFIGURATION}"; 3182 3183 unless(system($cmd) == 0) { 3184 warn("Failed to reset admin's password: \n$cmd"); 3185 return undef; 3186 } 3187 3188 # re-create the testenv's krb5.conf (the restore may have overwritten it, 3189 # if the backup-file was an offline backup) 3190 Samba::mk_krb5_conf($ctx); 3191 3192 # start samba for the restored DC 3193 if (not defined($self->check_or_start($env))) { 3194 return undef; 3195 } 3196 3197 # if this was a backup-rename, then we may need to setup namespaces 3198 my $upn_array = ["$env->{REALM}.upn"]; 3199 my $spn_array = ["$env->{REALM}.spn"]; 3200 3201 $self->setup_namespaces($env, $upn_array, $spn_array); 3202 3203 return $env; 3204} 3205 3206sub setup_none 3207{ 3208 my ($self, $path) = @_; 3209 3210 my $ret = { 3211 KRB5_CONFIG => abs_path($path) . "/no_krb5.conf", 3212 SAMBA_PID => -1, 3213 } 3214} 3215 32161; 3217