my $cmd = "NSS_WRAPPER_PASSWD=$testenv_vars->{NSS_WRAPPER_PASSWD} ";
$cmd .= "NSS_WRAPPER_GROUP=$testenv_vars->{NSS_WRAPPER_GROUP} ";
$cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=$testenv_vars->{SELFTEST_WINBINDD_SOCKET_DIR} ";
- $cmd .= "$wbinfo -p";
+ $cmd .= "$wbinfo -P";
$ret = system($cmd);
if ($ret != 0) {
rndc command = true
dns update command = $ctx->{samba_dnsupdate}
spn update command = $ENV{SRCDIR_ABS}/source4/scripting/bin/samba_spnupdate -s $ctx->{smb_conf}
- gpo update command = $ENV{SRCDIR_ABS}/source4/scripting/bin/samba_gpoupdate -s $ctx->{smb_conf} -H $ctx->{privatedir}/sam.ldb --machine
+ gpo update command = $ENV{SRCDIR_ABS}/source4/scripting/bin/samba-gpupdate -s $ctx->{smb_conf} -H $ctx->{privatedir}/sam.ldb --target=Computer
dreplsrv:periodic_startup_interval = 0
dsdb:schema update allowed = yes
auth event notification = true
dsdb event notification = true
dsdb password event notification = true
+ dsdb group change notification = true
server schannel = auto
";
my $ret = $self->provision($prefix,
auth event notification = true
dsdb event notification = true
dsdb password event notification = true
+ dsdb group change notification = true
$smbconf_args
";
ad_dc_no_nss => [],
ad_dc_no_ntlm => [],
ad_dc_ntvfs => [],
+ backupfromdc => [],
fl2008r2dc => ["ad_dc"],
fl2003dc => ["ad_dc"],
s4member_dflt_domain => ["ad_dc_ntvfs"],
s4member => ["ad_dc_ntvfs"],
+ restoredc => ["backupfromdc"],
+ renamedc => ["backupfromdc"],
+ offlinebackupdc => ["backupfromdc"],
+ labdc => ["backupfromdc"],
+
none => [],
);
return $env;
}
+# Sets up a DC that's solely used to do a domain backup from. We then use the
+# backupfrom-DC to create the restore-DC - this proves that the backup/restore
+# process will create a Samba DC that will actually start up.
+# We don't use the backup-DC for anything else because its domain will conflict
+# with the restore DC.
+sub setup_backupfromdc
+{
+ my ($self, $path) = @_;
+
+ # If we didn't build with ADS, pretend this env was never available
+ if (not $self->{target3}->have_ads()) {
+ return "UNKNOWN";
+ }
+
+ my $env = $self->provision_ad_dc($path, "backupfromdc", "BACKUPDOMAIN",
+ "backupdom.samba.example.com", "");
+ unless ($env) {
+ return undef;
+ }
+
+ if (not defined($self->check_or_start($env, "standard"))) {
+ return undef;
+ }
+
+ my $upn_array = ["$env->{REALM}.upn"];
+ my $spn_array = ["$env->{REALM}.spn"];
+
+ $self->setup_namespaces($env, $upn_array, $spn_array);
+
+ return $env;
+}
+
+# returns the server/user-auth params needed to run an online backup cmd
+sub get_backup_server_args
+{
+ # dcvars contains the env info for the backup DC testenv
+ my ($self, $dcvars) = @_;
+ my $server = $dcvars->{DC_SERVER_IP};
+ my $server_args = "--server=$server ";
+ $server_args .= "-U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
+
+ return $server_args;
+}
+
+# Creates a backup of a running testenv DC
+sub create_backup
+{
+ # note: dcvars contains the env info for the backup DC testenv
+ my ($self, $env, $dcvars, $backupdir, $backup_cmd) = @_;
+
+ # get all the env variables we pass in with the samba-tool command
+ my $cmd_env = "";
+ $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+ if (defined($env->{RESOLV_WRAPPER_CONF})) {
+ $cmd_env .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
+ } else {
+ $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
+ }
+ # Note: use the backupfrom-DC's krb5.conf to do the backup
+ $cmd_env .= " KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" ";
+ $cmd_env .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
+
+ # use samba-tool to create a backup from the 'backupfromdc' DC
+ my $cmd = "";
+ my $samba_tool = Samba::bindir_path($self, "samba-tool");
+
+ $cmd .= "$cmd_env $samba_tool domain backup $backup_cmd";
+ $cmd .= " --targetdir=$backupdir";
+
+ print "Executing: $cmd\n";
+ unless(system($cmd) == 0) {
+ warn("Failed to create backup using: \n$cmd");
+ return undef;
+ }
+
+ # get the name of the backup file created
+ opendir(DIR, $backupdir);
+ my @files = grep(/\.tar/, readdir(DIR));
+ closedir(DIR);
+
+ if(scalar @files != 1) {
+ warn("Backup file not found in directory $backupdir\n");
+ return undef;
+ }
+ my $backup_file = "$backupdir/$files[0]";
+ print "Using backup file $backup_file...\n";
+
+ return $backup_file;
+}
+
+# Restores a backup-file to populate a testenv for a new DC
+sub restore_backup_file
+{
+ my ($self, $backup_file, $restore_opts, $restoredir, $smbconf) = @_;
+
+ # pass the restore command the testenv's smb.conf that we've already
+ # generated. But move it to a temp-dir first, so that the restore doesn't
+ # overwrite it
+ my $tmpdir = File::Temp->newdir();
+ my $tmpconf = "$tmpdir/smb.conf";
+ my $cmd = "cp $smbconf $tmpconf";
+ unless(system($cmd) == 0) {
+ warn("Failed to backup smb.conf using: \n$cmd");
+ return -1;
+ }
+
+ my $samba_tool = Samba::bindir_path($self, "samba-tool");
+ $cmd = "$samba_tool domain backup restore --backup-file=$backup_file";
+ $cmd .= " --targetdir=$restoredir $restore_opts --configfile=$tmpconf";
+
+ print "Executing: $cmd\n";
+ unless(system($cmd) == 0) {
+ warn("Failed to restore backup using: \n$cmd");
+ return -1;
+ }
+
+ print "Restore complete\n";
+ return 0
+}
+
+# sets up the initial directory and returns the new testenv's env info
+# (without actually doing a 'domain join')
+sub prepare_dc_testenv
+{
+ my ($self, $prefix, $dcname, $domain, $realm, $password) = @_;
+
+ my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
+ $dcname,
+ $domain,
+ $realm,
+ undef,
+ "2008",
+ $password,
+ undef,
+ undef);
+
+ # the restore uses a slightly different state-dir location to other testenvs
+ $ctx->{statedir} = "$ctx->{prefix_abs}/state";
+ push(@{$ctx->{directories}}, "$ctx->{statedir}");
+
+ # add support for sysvol/netlogon/tmp shares
+ $ctx->{share} = "$ctx->{prefix_abs}/share";
+ push(@{$ctx->{directories}}, "$ctx->{share}");
+
+ $ctx->{smb_conf_extra_options} = "
+ max xmit = 32K
+ server max protocol = SMB2
+
+[sysvol]
+ path = $ctx->{statedir}/sysvol
+ read only = no
+
+[netlogon]
+ path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
+ read only = no
+
+[tmp]
+ path = $ctx->{share}
+ read only = no
+ posix:sharedelay = 10000
+ posix:oplocktimeout = 3
+ posix:writetimeupdatedelay = 50000
+
+";
+
+ my $env = $self->provision_raw_step1($ctx);
+
+ $env->{DC_SERVER} = $env->{SERVER};
+ $env->{DC_SERVER_IP} = $env->{SERVER_IP};
+ $env->{DC_SERVER_IPV6} = $env->{SERVER_IPV6};
+ $env->{DC_NETBIOSNAME} = $env->{NETBIOSNAME};
+ $env->{DC_USERNAME} = $env->{USERNAME};
+ $env->{DC_PASSWORD} = $env->{PASSWORD};
+
+ return ($env, $ctx);
+}
+
+
+# Set up a DC testenv solely by using the samba-tool domain backup/restore
+# commands. This proves that we can backup an online DC ('backupfromdc') and
+# use the backup file to create a valid, working samba DC.
+sub setup_restoredc
+{
+ # note: dcvars contains the env info for the dependent testenv ('backupfromdc')
+ my ($self, $prefix, $dcvars) = @_;
+ print "Preparing RESTORE DC...\n";
+
+ my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "restoredc",
+ $dcvars->{DOMAIN},
+ $dcvars->{REALM},
+ $dcvars->{PASSWORD});
+
+ # create a backup of the 'backupfromdc'
+ my $backupdir = File::Temp->newdir();
+ my $server_args = $self->get_backup_server_args($dcvars);
+ my $backup_args = "online $server_args";
+ my $backup_file = $self->create_backup($env, $dcvars, $backupdir,
+ $backup_args);
+ unless($backup_file) {
+ return undef;
+ }
+
+ # restore the backup file to populate the restore-DC testenv
+ my $restore_dir = abs_path($prefix);
+ my $ret = $self->restore_backup_file($backup_file,
+ "--newservername=$env->{SERVER}",
+ $restore_dir, $env->{SERVERCONFFILE});
+ unless ($ret == 0) {
+ return undef;
+ }
+
+ # start samba for the restored DC
+ if (not defined($self->check_or_start($env, "standard"))) {
+ return undef;
+ }
+
+ my $upn_array = ["$env->{REALM}.upn"];
+ my $spn_array = ["$env->{REALM}.spn"];
+
+ $self->setup_namespaces($env, $upn_array, $spn_array);
+
+ return $env;
+}
+
+# Set up a DC testenv solely by using the 'samba-tool domain backup rename' and
+# restore commands. This proves that we can backup and rename an online DC
+# ('backupfromdc') and use the backup file to create a valid, working samba DC.
+sub setup_renamedc
+{
+ # note: dcvars contains the env info for the dependent testenv ('backupfromdc')
+ my ($self, $prefix, $dcvars) = @_;
+ print "Preparing RENAME DC...\n";
+
+ my $realm = "renamedom.samba.example.com";
+ my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "renamedc",
+ "RENAMEDOMAIN", $realm,
+ $dcvars->{PASSWORD});
+
+ # create a backup of the 'backupfromdc' which renames the domain
+ my $backupdir = File::Temp->newdir();
+ my $server_args = $self->get_backup_server_args($dcvars);
+ my $backup_args = "rename $env->{DOMAIN} $env->{REALM} $server_args";
+ my $backup_file = $self->create_backup($env, $dcvars, $backupdir,
+ $backup_args);
+ unless($backup_file) {
+ return undef;
+ }
+
+ # restore the backup file to populate the rename-DC testenv
+ my $restore_dir = abs_path($prefix);
+ my $restore_opts = "--newservername=$env->{SERVER} --host-ip=$env->{SERVER_IP}";
+ my $ret = $self->restore_backup_file($backup_file, $restore_opts,
+ $restore_dir, $env->{SERVERCONFFILE});
+ unless ($ret == 0) {
+ return undef;
+ }
+
+ # start samba for the restored DC
+ if (not defined($self->check_or_start($env, "standard"))) {
+ return undef;
+ }
+
+ my $upn_array = ["$env->{REALM}.upn"];
+ my $spn_array = ["$env->{REALM}.spn"];
+
+ $self->setup_namespaces($env, $upn_array, $spn_array);
+
+ return $env;
+}
+
+# Set up a DC testenv solely by using the 'samba-tool domain backup offline' and
+# restore commands. This proves that we do an offline backup of a local DC
+# ('backupfromdc') and use the backup file to create a valid, working samba DC.
+sub setup_offlinebackupdc
+{
+ # note: dcvars contains the env info for the dependent testenv ('backupfromdc')
+ my ($self, $prefix, $dcvars) = @_;
+ print "Preparing OFFLINE BACKUP DC...\n";
+
+ my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "offlinebackupdc",
+ $dcvars->{DOMAIN},
+ $dcvars->{REALM},
+ $dcvars->{PASSWORD});
+
+ # create an offline backup of the 'backupfromdc' target
+ my $backupdir = File::Temp->newdir();
+ my $cmd = "offline -s $dcvars->{SERVERCONFFILE}";
+ my $backup_file = $self->create_backup($env, $dcvars,
+ $backupdir, $cmd);
+
+ unless($backup_file) {
+ return undef;
+ }
+
+ # restore the backup file to populate the rename-DC testenv
+ my $restore_dir = abs_path($prefix);
+ my $restore_opts = "--newservername=$env->{SERVER} --host-ip=$env->{SERVER_IP}";
+ my $ret = $self->restore_backup_file($backup_file, $restore_opts,
+ $restore_dir, $env->{SERVERCONFFILE});
+ unless ($ret == 0) {
+ return undef;
+ }
+
+ # re-create the testenv's krb5.conf (the restore may have overwritten it)
+ Samba::mk_krb5_conf($ctx);
+
+ # start samba for the restored DC
+ if (not defined($self->check_or_start($env, "standard"))) {
+ return undef;
+ }
+
+ my $upn_array = ["$env->{REALM}.upn"];
+ my $spn_array = ["$env->{REALM}.spn"];
+
+ $self->setup_namespaces($env, $upn_array, $spn_array);
+
+ return $env;
+}
+
+# Set up a DC testenv solely by using the samba-tool 'domain backup rename' and
+# restore commands, using the --no-secrets option. This proves that we can
+# create a realistic lab environment from an online DC ('backupfromdc').
+sub setup_labdc
+{
+ # note: dcvars contains the env info for the dependent testenv ('backupfromdc')
+ my ($self, $prefix, $dcvars) = @_;
+ print "Preparing LAB-DOMAIN DC...\n";
+
+ my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "labdc",
+ "LABDOMAIN",
+ "labdom.samba.example.com",
+ $dcvars->{PASSWORD});
+
+ # create a backup of the 'backupfromdc' which renames the domain and uses
+ # the --no-secrets option to scrub any sensitive info
+ my $backupdir = File::Temp->newdir();
+ my $server_args = $self->get_backup_server_args($dcvars);
+ my $backup_args = "rename $env->{DOMAIN} $env->{REALM} $server_args";
+ $backup_args .= " --no-secrets";
+ my $backup_file = $self->create_backup($env, $dcvars, $backupdir,
+ $backup_args);
+ unless($backup_file) {
+ return undef;
+ }
+
+ # restore the backup file to populate the lab-DC testenv
+ my $restore_dir = abs_path($prefix);
+ my $restore_opts = "--newservername=$env->{SERVER} --host-ip=$env->{SERVER_IP}";
+ my $ret = $self->restore_backup_file($backup_file, $restore_opts,
+ $restore_dir, $env->{SERVERCONFFILE});
+ unless ($ret == 0) {
+ return undef;
+ }
+
+ # because we don't include any secrets in the backup, we need to reset the
+ # admin user's password back to what the testenv expects
+ my $samba_tool = Samba::bindir_path($self, "samba-tool");
+ my $cmd = "$samba_tool user setpassword $env->{USERNAME} ";
+ $cmd .= "--newpassword=$env->{PASSWORD} -H $restore_dir/private/sam.ldb";
+
+ unless(system($cmd) == 0) {
+ warn("Failed to reset admin's password: \n$cmd");
+ return -1;
+ }
+
+ # start samba for the restored DC
+ if (not defined($self->check_or_start($env, "standard"))) {
+ return undef;
+ }
+
+ my $upn_array = ["$env->{REALM}.upn"];
+ my $spn_array = ["$env->{REALM}.spn"];
+
+ $self->setup_namespaces($env, $upn_array, $spn_array);
+
+ return $env;
+}
+
sub setup_none
{
my ($self, $path) = @_;