1209893792fc846b669bc740ccbf6a829bf01107
[samba.git] / selftest / target / Samba4.pm
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 package Samba4;
7
8 use strict;
9 use Cwd qw(abs_path);
10 use FindBin qw($RealBin);
11 use POSIX;
12 use SocketWrapper;
13 use target::Samba;
14 use target::Samba3;
15
16 sub new($$$$$) {
17         my ($classname, $bindir, $ldap, $srcdir, $server_maxtime) = @_;
18
19         my $self = {
20                 vars => {},
21                 ldap => $ldap,
22                 bindir => $bindir,
23                 srcdir => $srcdir,
24                 server_maxtime => $server_maxtime,
25                 target3 => new Samba3($bindir, $srcdir, $server_maxtime)
26         };
27         bless $self;
28         return $self;
29 }
30
31 sub scriptdir_path($$) {
32         my ($self, $path) = @_;
33         return "$self->{srcdir}/source4/scripting/$path";
34 }
35
36 sub openldap_start($$$) {
37 }
38
39 sub slapd_start($$)
40 {
41         my $count = 0;
42         my ($self, $env_vars, $STDIN_READER) = @_;
43         my $ldbsearch = Samba::bindir_path($self, "ldbsearch");
44
45         my $uri = $env_vars->{LDAP_URI};
46
47         if (system("$ldbsearch -H $uri -s base -b \"\" supportedLDAPVersion > /dev/null") == 0) {
48             print "A SLAPD is still listening to $uri before we started the LDAP backend.  Aborting!";
49             return 1;
50         }
51         # running slapd in the background means it stays in the same process group, so it can be
52         # killed by timelimit
53         my $pid = fork();
54         if ($pid == 0) {
55                 open STDOUT, ">$env_vars->{LDAPDIR}/logs";
56                 open STDERR, '>&STDOUT';
57                 close($env_vars->{STDIN_PIPE});
58                 open STDIN, ">&", $STDIN_READER or die "can't dup STDIN_READER to STDIN: $!";
59
60                 if ($self->{ldap} eq "fedora-ds") {
61                         exec("$ENV{FEDORA_DS_ROOT}/sbin/ns-slapd", "-D", $env_vars->{FEDORA_DS_DIR}, "-d0", "-i", $env_vars->{FEDORA_DS_PIDFILE});
62                 } elsif ($self->{ldap} eq "openldap") {
63                         exec($ENV{OPENLDAP_SLAPD}, "-dnone", "-F", $env_vars->{SLAPD_CONF_D}, "-h", $uri);
64                 }
65                 die("Unable to start slapd: $!");
66         }
67         $env_vars->{SLAPD_PID} = $pid;
68         sleep(1);
69         while (system("$ldbsearch -H $uri -s base -b \"\" supportedLDAPVersion > /dev/null") != 0) {
70                 $count++;
71                 if ($count > 40) {
72                         $self->slapd_stop($env_vars);
73                         return 0;
74                 }
75                 sleep(1);
76         }
77         return 1;
78 }
79
80 sub slapd_stop($$)
81 {
82         my ($self, $envvars) = @_;
83         kill 9, $envvars->{SLAPD_PID};
84         return 1;
85 }
86
87 sub check_or_start($$$)
88 {
89         my ($self, $env_vars, $process_model) = @_;
90         my $STDIN_READER;
91
92         my $env_ok = $self->check_env($env_vars);
93         if ($env_ok) {
94                 return $env_vars->{SAMBA_PID};
95         } elsif (defined($env_vars->{SAMBA_PID})) {
96                 warn("SAMBA PID $env_vars->{SAMBA_PID} is not running (died)");
97                 return undef;
98         }
99
100         # use a pipe for stdin in the child processes. This allows
101         # those processes to monitor the pipe for EOF to ensure they
102         # exit when the test script exits
103         pipe($STDIN_READER, $env_vars->{STDIN_PIPE});
104
105         # Start slapd before samba, but with the fifo on stdin
106         if (defined($self->{ldap})) {
107                 unless($self->slapd_start($env_vars, $STDIN_READER)) {
108                         warn("couldn't start slapd (main run)");
109                         return undef;
110                 }
111         }
112
113         print "STARTING SAMBA...\n";
114         my $pid = fork();
115         if ($pid == 0) {
116                 # we want out from samba to go to the log file, but also
117                 # to the users terminal when running 'make test' on the command
118                 # line. This puts it on stderr on the terminal
119                 open STDOUT, "| tee $env_vars->{SAMBA_TEST_LOG} 1>&2";
120                 open STDERR, '>&STDOUT';
121
122                 SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
123
124                 $ENV{KRB5_CONFIG} = $env_vars->{KRB5_CONFIG};
125                 $ENV{KRB5CCNAME} = "$env_vars->{KRB5_CCACHE}.samba";
126                 $ENV{SELFTEST_WINBINDD_SOCKET_DIR} = $env_vars->{SELFTEST_WINBINDD_SOCKET_DIR};
127                 $ENV{NMBD_SOCKET_DIR} = $env_vars->{NMBD_SOCKET_DIR};
128
129                 $ENV{NSS_WRAPPER_PASSWD} = $env_vars->{NSS_WRAPPER_PASSWD};
130                 $ENV{NSS_WRAPPER_GROUP} = $env_vars->{NSS_WRAPPER_GROUP};
131                 $ENV{NSS_WRAPPER_HOSTS} = $env_vars->{NSS_WRAPPER_HOSTS};
132                 $ENV{NSS_WRAPPER_HOSTNAME} = $env_vars->{NSS_WRAPPER_HOSTNAME};
133                 $ENV{NSS_WRAPPER_MODULE_SO_PATH} = $env_vars->{NSS_WRAPPER_MODULE_SO_PATH};
134                 $ENV{NSS_WRAPPER_MODULE_FN_PREFIX} = $env_vars->{NSS_WRAPPER_MODULE_FN_PREFIX};
135
136                 if (defined($env_vars->{RESOLV_WRAPPER_CONF})) {
137                         $ENV{RESOLV_WRAPPER_CONF} = $env_vars->{RESOLV_WRAPPER_CONF};
138                 } else {
139                         $ENV{RESOLV_WRAPPER_HOSTS} = $env_vars->{RESOLV_WRAPPER_HOSTS};
140                 }
141
142                 $ENV{UID_WRAPPER} = "1";
143                 $ENV{UID_WRAPPER_ROOT} = "1";
144
145                 $ENV{MAKE_TEST_BINARY} = Samba::bindir_path($self, "samba");
146                 my @preargs = ();
147                 my @optargs = ();
148                 if (defined($ENV{SAMBA_OPTIONS})) {
149                         @optargs = split(/ /, $ENV{SAMBA_OPTIONS});
150                 }
151                 if(defined($ENV{SAMBA_VALGRIND})) {
152                         @preargs = split(/ /,$ENV{SAMBA_VALGRIND});
153                 }
154
155                 close($env_vars->{STDIN_PIPE});
156                 open STDIN, ">&", $STDIN_READER or die "can't dup STDIN_READER to STDIN: $!";
157
158                 exec(@preargs, Samba::bindir_path($self, "samba"), "-M", $process_model, "-i", "--maximum-runtime=$self->{server_maxtime}", $env_vars->{CONFIGURATION}, @optargs) or die("Unable to start samba: $!");
159         }
160         $env_vars->{SAMBA_PID} = $pid;
161         print "DONE ($pid)\n";
162
163         close($STDIN_READER);
164
165         if ($self->wait_for_start($env_vars) != 0) {
166             warn("Samba $pid failed to start up");
167             return undef;
168         }
169
170         return $pid;
171 }
172
173 sub wait_for_start($$)
174 {
175         my ($self, $testenv_vars) = @_;
176         my $count = 0;
177         my $ret = 0;
178
179         if (not $self->check_env($testenv_vars)) {
180             warn("unable to confirm Samba $testenv_vars->{SAMBA_PID} is running");
181             return -1;
182         }
183
184         # This will return quickly when things are up, but be slow if we
185         # need to wait for (eg) SSL init
186         my $nmblookup =  Samba::bindir_path($self, "nmblookup4");
187
188         do {
189                 $ret = system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{SERVER}");
190                 if ($ret != 0) {
191                         sleep(1);
192                 } else {
193                         system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{SERVER}");
194                         system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}");
195                         system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}");
196                         system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}");
197                         system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}");
198                         system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{SERVER}");
199                         system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{SERVER}");
200                         system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}");
201                         system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}");
202                         system("$nmblookup $testenv_vars->{CONFIGURATION} $testenv_vars->{NETBIOSNAME}");
203                         system("$nmblookup $testenv_vars->{CONFIGURATION} -U $testenv_vars->{SERVER_IP} $testenv_vars->{NETBIOSNAME}");
204                 }
205                 $count++;
206         } while ($ret != 0 && $count < 20);
207         if ($count == 10) {
208                 warn("nbt not reachable after 20 retries\n");
209                 teardown_env($self, $testenv_vars);
210                 return 0;
211         }
212
213         # Ensure we have the first RID Set before we start tests.  This makes the tests more reliable.
214         if ($testenv_vars->{SERVER_ROLE} eq "domain controller") {
215                 # Add hosts file for name lookups
216                 $ENV{NSS_WRAPPER_HOSTS} = $testenv_vars->{NSS_WRAPPER_HOSTS};
217                 if (defined($testenv_vars->{RESOLV_WRAPPER_CONF})) {
218                         $ENV{RESOLV_WRAPPER_CONF} = $testenv_vars->{RESOLV_WRAPPER_CONF};
219                 } else {
220                         $ENV{RESOLV_WRAPPER_HOSTS} = $testenv_vars->{RESOLV_WRAPPER_HOSTS};
221                 }
222
223                 print "waiting for working LDAP and a RID Set to be allocated\n";
224                 my $ldbsearch = Samba::bindir_path($self, "ldbsearch");
225                 my $count = 0;
226                 my $base_dn = "DC=".join(",DC=", split(/\./, $testenv_vars->{REALM}));
227
228                 my $search_dn = $base_dn;
229                 if ($testenv_vars->{NETBIOSNAME} ne "RODC") {
230                         # TODO currently no check for actual rIDAllocationPool
231                         $search_dn = "cn=RID Set,cn=$testenv_vars->{NETBIOSNAME},ou=domain controllers,$base_dn";
232                 }
233                 my $max_wait = 60;
234                 my $cmd = "$ldbsearch $testenv_vars->{CONFIGURATION} -H ldap://$testenv_vars->{SERVER} -U$testenv_vars->{USERNAME}%$testenv_vars->{PASSWORD} -s base -b \"$search_dn\"";
235                 while (system("$cmd >/dev/null") != 0) {
236                         $count++;
237                         if ($count > $max_wait) {
238                                 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}");
239                                 $ret = -1;
240                                 last;
241                         }
242                         sleep(1);
243                 }
244         }
245         print $self->getlog_env($testenv_vars);
246
247         return $ret
248 }
249
250 sub write_ldb_file($$$)
251 {
252         my ($self, $file, $ldif) = @_;
253
254         my $ldbadd =  Samba::bindir_path($self, "ldbadd");
255         open(LDIF, "|$ldbadd -H $file >/dev/null");
256         print LDIF $ldif;
257         return(close(LDIF));
258 }
259
260 sub add_wins_config($$)
261 {
262         my ($self, $privatedir) = @_;
263
264         return $self->write_ldb_file("$privatedir/wins_config.ldb", "
265 dn: name=TORTURE_11,CN=PARTNERS
266 objectClass: wreplPartner
267 name: TORTURE_11
268 address: 127.0.0.11
269 pullInterval: 0
270 pushChangeCount: 0
271 type: 0x3
272 ");
273 }
274
275 sub mk_fedora_ds($$)
276 {
277         my ($self, $ctx) = @_;
278
279         #Make the subdirectory be as fedora DS would expect
280         my $fedora_ds_dir = "$ctx->{ldapdir}/slapd-$ctx->{ldap_instance}";
281
282         my $pidfile = "$fedora_ds_dir/logs/slapd-$ctx->{ldap_instance}.pid";
283
284         return ($fedora_ds_dir, $pidfile);
285 }
286
287 sub mk_openldap($$)
288 {
289         my ($self, $ctx) = @_;
290
291         my $slapd_conf_d = "$ctx->{ldapdir}/slapd.d";
292         my $pidfile = "$ctx->{ldapdir}/slapd.pid";
293
294         return ($slapd_conf_d, $pidfile);
295 }
296
297 sub setup_namespaces($$:$$)
298 {
299         my ($self, $localenv, $upn_array, $spn_array) = @_;
300
301         @{$upn_array} = [] unless defined($upn_array);
302         my $upn_args = "";
303         foreach my $upn (@{$upn_array}) {
304                 $upn_args .= " --add-upn-suffix=$upn";
305         }
306
307         @{$spn_array} = [] unless defined($spn_array);
308         my $spn_args = "";
309         foreach my $spn (@{$spn_array}) {
310                 $spn_args .= " --add-spn-suffix=$spn";
311         }
312
313         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
314
315         my $cmd_env = "";
316         $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$localenv->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
317         if (defined($localenv->{RESOLV_WRAPPER_CONF})) {
318                 $cmd_env .= "RESOLV_WRAPPER_CONF=\"$localenv->{RESOLV_WRAPPER_CONF}\" ";
319         } else {
320                 $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$localenv->{RESOLV_WRAPPER_HOSTS}\" ";
321         }
322         $cmd_env .= " KRB5_CONFIG=\"$localenv->{KRB5_CONFIG}\" ";
323         $cmd_env .= "KRB5CCNAME=\"$localenv->{KRB5_CCACHE}\" ";
324
325         my $cmd_config = " $localenv->{CONFIGURATION}";
326
327         my $namespaces = $cmd_env;
328         $namespaces .= " $samba_tool domain trust namespaces $upn_args $spn_args";
329         $namespaces .= $cmd_config;
330         unless (system($namespaces) == 0) {
331                 warn("Failed to add namespaces \n$namespaces");
332                 return;
333         }
334
335         return;
336 }
337
338 sub setup_trust($$$$$)
339 {
340         my ($self, $localenv, $remoteenv, $type, $extra_args) = @_;
341
342         $localenv->{TRUST_SERVER} = $remoteenv->{SERVER};
343         $localenv->{TRUST_SERVER_IP} = $remoteenv->{SERVER_IP};
344         $localenv->{TRUST_SERVER_IPV6} = $remoteenv->{SERVER_IPV6};
345         $localenv->{TRUST_NETBIOSNAME} = $remoteenv->{NETBIOSNAME};
346         $localenv->{TRUST_USERNAME} = $remoteenv->{USERNAME};
347         $localenv->{TRUST_PASSWORD} = $remoteenv->{PASSWORD};
348         $localenv->{TRUST_DOMAIN} = $remoteenv->{DOMAIN};
349         $localenv->{TRUST_REALM} = $remoteenv->{REALM};
350
351         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
352         # setup the trust
353         my $cmd_env = "";
354         $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$localenv->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
355         if (defined($localenv->{RESOLV_WRAPPER_CONF})) {
356                 $cmd_env .= "RESOLV_WRAPPER_CONF=\"$localenv->{RESOLV_WRAPPER_CONF}\" ";
357         } else {
358                 $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$localenv->{RESOLV_WRAPPER_HOSTS}\" ";
359         }
360         $cmd_env .= " KRB5_CONFIG=\"$localenv->{KRB5_CONFIG}\" ";
361         $cmd_env .= "KRB5CCNAME=\"$localenv->{KRB5_CCACHE}\" ";
362
363         my $cmd_config = " $localenv->{CONFIGURATION}";
364         my $cmd_creds = $cmd_config;
365         $cmd_creds .= " -U$localenv->{TRUST_DOMAIN}\\\\$localenv->{TRUST_USERNAME}\%$localenv->{TRUST_PASSWORD}";
366
367         my $create = $cmd_env;
368         $create .= " $samba_tool domain trust create --type=${type} $localenv->{TRUST_REALM}";
369         $create .= " $extra_args";
370         $create .= $cmd_creds;
371         unless (system($create) == 0) {
372                 warn("Failed to create trust \n$create");
373                 return undef;
374         }
375
376         return $localenv
377 }
378
379 sub provision_raw_prepare($$$$$$$$$$$)
380 {
381         my ($self, $prefix, $server_role, $hostname,
382             $domain, $realm, $functional_level,
383             $password, $kdc_ipv4, $kdc_ipv6) = @_;
384         my $ctx;
385         my $netbiosname = uc($hostname);
386
387         unless(-d $prefix or mkdir($prefix, 0777)) {
388                 warn("Unable to create $prefix");
389                 return undef;
390         }
391         my $prefix_abs = abs_path($prefix);
392
393         die ("prefix=''") if $prefix_abs eq "";
394         die ("prefix='/'") if $prefix_abs eq "/";
395
396         unless (system("rm -rf $prefix_abs/*") == 0) {
397                 warn("Unable to clean up");
398         }
399
400         
401         my $swiface = Samba::get_interface($hostname);
402
403         $ctx->{prefix} = $prefix;
404         $ctx->{prefix_abs} = $prefix_abs;
405
406         $ctx->{server_role} = $server_role;
407         $ctx->{hostname} = $hostname;
408         $ctx->{netbiosname} = $netbiosname;
409         $ctx->{swiface} = $swiface;
410         $ctx->{password} = $password;
411         $ctx->{kdc_ipv4} = $kdc_ipv4;
412         $ctx->{kdc_ipv6} = $kdc_ipv6;
413         $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
414         if ($functional_level eq "2000") {
415                 $ctx->{supported_enctypes} = "arcfour-hmac-md5 des-cbc-md5 des-cbc-crc"
416         }
417
418 #
419 # Set smbd log level here.
420 #
421         $ctx->{server_loglevel} =$ENV{SERVER_LOG_LEVEL} || 1;
422         $ctx->{username} = "Administrator";
423         $ctx->{domain} = $domain;
424         $ctx->{realm} = uc($realm);
425         $ctx->{dnsname} = lc($realm);
426
427         $ctx->{functional_level} = $functional_level;
428
429         my $unix_name = ($ENV{USER} or $ENV{LOGNAME} or `whoami`);
430         chomp $unix_name;
431         $ctx->{unix_name} = $unix_name;
432         $ctx->{unix_uid} = $>;
433         my @mygid = split(" ", $();
434         $ctx->{unix_gid} = $mygid[0];
435         $ctx->{unix_gids_str} = $);
436         @{$ctx->{unix_gids}} = split(" ", $ctx->{unix_gids_str});
437
438         $ctx->{etcdir} = "$prefix_abs/etc";
439         $ctx->{piddir} = "$prefix_abs/pid";
440         $ctx->{smb_conf} = "$ctx->{etcdir}/smb.conf";
441         $ctx->{krb5_conf} = "$ctx->{etcdir}/krb5.conf";
442         $ctx->{krb5_ccache} = "$prefix_abs/krb5_ccache";
443         $ctx->{privatedir} = "$prefix_abs/private";
444         $ctx->{ncalrpcdir} = "$prefix_abs/ncalrpc";
445         $ctx->{lockdir} = "$prefix_abs/lockdir";
446         $ctx->{logdir} = "$prefix_abs/logs";
447         $ctx->{statedir} = "$prefix_abs/statedir";
448         $ctx->{cachedir} = "$prefix_abs/cachedir";
449         $ctx->{winbindd_socket_dir} = "$prefix_abs/winbindd_socket";
450         $ctx->{ntp_signd_socket_dir} = "$prefix_abs/ntp_signd_socket";
451         $ctx->{nsswrap_passwd} = "$ctx->{etcdir}/passwd";
452         $ctx->{nsswrap_group} = "$ctx->{etcdir}/group";
453         $ctx->{nsswrap_hosts} = "$ENV{SELFTEST_PREFIX}/hosts";
454         $ctx->{nsswrap_hostname} = "$ctx->{hostname}.$ctx->{dnsname}";
455         if ($ENV{SAMBA_DNS_FAKING}) {
456                 $ctx->{dns_host_file} = "$ENV{SELFTEST_PREFIX}/dns_host_file";
457                 $ctx->{samba_dnsupdate} = "$ENV{SRCDIR_ABS}/source4/scripting/bin/samba_dnsupdate -s $ctx->{smb_conf} --all-interfaces --use-file=$ctx->{dns_host_file}";
458         } else {
459                 $ctx->{samba_dnsupdate} = "$ENV{SRCDIR_ABS}/source4/scripting/bin/samba_dnsupdate -s $ctx->{smb_conf} --all-interfaces";
460                 $ctx->{use_resolv_wrapper} = 1;
461         }
462         $ctx->{resolv_conf} = "$ctx->{etcdir}/resolv.conf";
463
464         $ctx->{tlsdir} = "$ctx->{privatedir}/tls";
465
466         $ctx->{ipv4} = "127.0.0.$swiface";
467         $ctx->{ipv6} = sprintf("fd00:0000:0000:0000:0000:0000:5357:5f%02x", $swiface);
468         $ctx->{interfaces} = "$ctx->{ipv4}/8 $ctx->{ipv6}/64";
469
470         push(@{$ctx->{directories}}, $ctx->{privatedir});
471         push(@{$ctx->{directories}}, $ctx->{etcdir});
472         push(@{$ctx->{directories}}, $ctx->{piddir});
473         push(@{$ctx->{directories}}, $ctx->{lockdir});
474         push(@{$ctx->{directories}}, $ctx->{logdir});
475         push(@{$ctx->{directories}}, $ctx->{statedir});
476         push(@{$ctx->{directories}}, $ctx->{cachedir});
477
478         $ctx->{smb_conf_extra_options} = "";
479
480         my @provision_options = ();
481         push (@provision_options, "KRB5_CONFIG=\"$ctx->{krb5_conf}\"");
482         push (@provision_options, "KRB5_CCACHE=\"$ctx->{krb5_ccache}\"");
483         push (@provision_options, "NSS_WRAPPER_PASSWD=\"$ctx->{nsswrap_passwd}\"");
484         push (@provision_options, "NSS_WRAPPER_GROUP=\"$ctx->{nsswrap_group}\"");
485         push (@provision_options, "NSS_WRAPPER_HOSTS=\"$ctx->{nsswrap_hosts}\"");
486         push (@provision_options, "NSS_WRAPPER_HOSTNAME=\"$ctx->{nsswrap_hostname}\"");
487         if (defined($ctx->{use_resolv_wrapper})) {
488                 push (@provision_options, "RESOLV_WRAPPER_CONF=\"$ctx->{resolv_conf}\"");
489         } else {
490                 push (@provision_options, "RESOLV_WRAPPER_HOSTS=\"$ctx->{dns_host_file}\"");
491         }
492         if (defined($ENV{GDB_PROVISION})) {
493                 push (@provision_options, "gdb --args");
494                 if (!defined($ENV{PYTHON})) {
495                     push (@provision_options, "env");
496                     push (@provision_options, "python");
497                 }
498         }
499         if (defined($ENV{VALGRIND_PROVISION})) {
500                 push (@provision_options, "valgrind");
501                 if (!defined($ENV{PYTHON})) {
502                     push (@provision_options, "env");
503                     push (@provision_options, "python");
504                 }
505         }
506         if (defined($ENV{PYTHON})) {
507                 push (@provision_options, $ENV{PYTHON});
508         }
509         push (@provision_options, Samba::bindir_path($self, "samba-tool"));
510         push (@provision_options, "domain");
511         push (@provision_options, "provision");
512         push (@provision_options, "--configfile=$ctx->{smb_conf}");
513         push (@provision_options, "--host-name=$ctx->{hostname}");
514         push (@provision_options, "--host-ip=$ctx->{ipv4}");
515         push (@provision_options, "--quiet");
516         push (@provision_options, "--domain=$ctx->{domain}");
517         push (@provision_options, "--realm=$ctx->{realm}");
518         push (@provision_options, "--adminpass=$ctx->{password}");
519         push (@provision_options, "--krbtgtpass=krbtgt$ctx->{password}");
520         push (@provision_options, "--machinepass=machine$ctx->{password}");
521         push (@provision_options, "--root=$ctx->{unix_name}");
522         push (@provision_options, "--server-role=\"$ctx->{server_role}\"");
523         push (@provision_options, "--function-level=\"$ctx->{functional_level}\"");
524
525         @{$ctx->{provision_options}} = @provision_options;
526
527         return $ctx;
528 }
529
530 #
531 # Step1 creates the basic configuration
532 #
533 sub provision_raw_step1($$)
534 {
535         my ($self, $ctx) = @_;
536
537         mkdir($_, 0777) foreach (@{$ctx->{directories}});
538
539         ##
540         ## lockdir and piddir must be 0755
541         ##
542         chmod 0755, $ctx->{lockdir};
543         chmod 0755, $ctx->{piddir};
544
545         unless (open(CONFFILE, ">$ctx->{smb_conf}")) {
546                 warn("can't open $ctx->{smb_conf}$?");
547                 return undef;
548         }
549
550         Samba::prepare_keyblobs($ctx);
551         my $crlfile = "$ctx->{tlsdir}/crl.pem";
552         $crlfile = "" unless -e ${crlfile};
553
554         print CONFFILE "
555 [global]
556         netbios name = $ctx->{netbiosname}
557         posix:eadb = $ctx->{statedir}/eadb.tdb
558         workgroup = $ctx->{domain}
559         realm = $ctx->{realm}
560         private dir = $ctx->{privatedir}
561         pid directory = $ctx->{piddir}
562         ncalrpc dir = $ctx->{ncalrpcdir}
563         lock dir = $ctx->{lockdir}
564         state directory = $ctx->{statedir}
565         cache directory = $ctx->{cachedir}
566         winbindd socket directory = $ctx->{winbindd_socket_dir}
567         ntp signd socket directory = $ctx->{ntp_signd_socket_dir}
568         winbind separator = /
569         interfaces = $ctx->{interfaces}
570         tls dh params file = $ctx->{tlsdir}/dhparms.pem
571         tls crlfile = ${crlfile}
572         tls verify peer = no_check
573         panic action = $RealBin/gdb_backtrace \%d
574         wins support = yes
575         server role = $ctx->{server_role}
576         server services = +echo +smb -s3fs
577         dcerpc endpoint servers = +winreg +srvsvc
578         notify:inotify = false
579         ldb:nosync = true
580         ldap server require strong auth = yes
581 #We don't want to pass our self-tests if the PAC code is wrong
582         gensec:require_pac = true
583         log file = $ctx->{logdir}/log.\%m
584         log level = $ctx->{server_loglevel}
585         lanman auth = Yes
586         ntlm auth = Yes
587         rndc command = true
588         dns update command = $ctx->{samba_dnsupdate}
589         spn update command = $ENV{SRCDIR_ABS}/source4/scripting/bin/samba_spnupdate -s $ctx->{smb_conf}
590         dreplsrv:periodic_startup_interval = 0
591         dsdb:schema update allowed = yes
592
593         vfs objects = dfs_samba4 acl_xattr fake_acls xattr_tdb streams_depot
594
595         idmap_ldb:use rfc2307=yes
596         winbind enum users = yes
597         winbind enum groups = yes
598
599         rpc server port:netlogon = 1026
600
601 ";
602
603         print CONFFILE "
604
605         # Begin extra options
606         $ctx->{smb_conf_extra_options}
607         # End extra options
608 ";
609         close(CONFFILE);
610
611         #Default the KDC IP to the server's IP
612         if (not defined($ctx->{kdc_ipv4})) {
613                 $ctx->{kdc_ipv4} = $ctx->{ipv4};
614         }
615         if (not defined($ctx->{kdc_ipv6})) {
616                 $ctx->{kdc_ipv6} = $ctx->{ipv6};
617         }
618
619         Samba::mk_krb5_conf($ctx);
620
621         open(PWD, ">$ctx->{nsswrap_passwd}");
622         if ($ctx->{unix_uid} != 0) {
623                 print PWD "root:x:0:0:root gecos:$ctx->{prefix_abs}:/bin/false\n";
624         }
625         print PWD "$ctx->{unix_name}:x:$ctx->{unix_uid}:65531:$ctx->{unix_name} gecos:$ctx->{prefix_abs}:/bin/false\n";
626         print PWD "nobody:x:65534:65533:nobody gecos:$ctx->{prefix_abs}:/bin/false
627 pdbtest:x:65533:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false
628 pdbtest2:x:65532:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false
629 pdbtest3:x:65531:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false
630 pdbtest4:x:65530:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false
631 ";
632         close(PWD);
633         my $uid_rfc2307test = 65533;
634
635         open(GRP, ">$ctx->{nsswrap_group}");
636         if ($ctx->{unix_gid} != 0) {
637                 print GRP "root:x:0:\n";
638         }
639         print GRP "$ctx->{unix_name}:x:$ctx->{unix_gid}:\n";
640         print GRP "wheel:x:10:
641 users:x:65531:
642 nobody:x:65533:
643 nogroup:x:65534:nobody
644 ";
645         close(GRP);
646         my $gid_rfc2307test = 65532;
647
648         my $hostname = lc($ctx->{hostname});
649         open(HOSTS, ">>$ctx->{nsswrap_hosts}");
650         if ($hostname eq "localdc") {
651                 print HOSTS "$ctx->{ipv4} ${hostname}.$ctx->{dnsname} $ctx->{dnsname} ${hostname}\n";
652                 print HOSTS "$ctx->{ipv6} ${hostname}.$ctx->{dnsname} $ctx->{dnsname} ${hostname}\n";
653         } else {
654                 print HOSTS "$ctx->{ipv4} ${hostname}.$ctx->{dnsname} ${hostname}\n";
655                 print HOSTS "$ctx->{ipv6} ${hostname}.$ctx->{dnsname} ${hostname}\n";
656         }
657         close(HOSTS);
658
659         if (defined($ctx->{resolv_conf})) {
660                 open(RESOLV_CONF, ">$ctx->{resolv_conf}");
661                 print RESOLV_CONF "nameserver $ctx->{kdc_ipv4}\n";
662                 print RESOLV_CONF "nameserver $ctx->{kdc_ipv6}\n";
663                 close(RESOLV_CONF);
664         }
665
666         my $configuration = "--configfile=$ctx->{smb_conf}";
667
668 #Ensure the config file is valid before we start
669         my $testparm = Samba::bindir_path($self, "samba-tool") . " testparm";
670         if (system("$testparm $configuration -v --suppress-prompt >/dev/null 2>&1") != 0) {
671                 system("$testparm -v --suppress-prompt $configuration >&2");
672                 warn("Failed to create a valid smb.conf configuration $testparm!");
673                 return undef;
674         }
675         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) {
676                 warn("Failed to create a valid smb.conf configuration! $testparm $configuration -v --suppress-prompt --parameter-name=\"netbios name\" --section-name=global");
677                 return undef;
678         }
679
680         my $ret = {
681                 KRB5_CONFIG => $ctx->{krb5_conf},
682                 KRB5_CCACHE => $ctx->{krb5_ccache},
683                 PIDDIR => $ctx->{piddir},
684                 SERVER => $ctx->{hostname},
685                 SERVER_IP => $ctx->{ipv4},
686                 SERVER_IPV6 => $ctx->{ipv6},
687                 NETBIOSNAME => $ctx->{netbiosname},
688                 DOMAIN => $ctx->{domain},
689                 USERNAME => $ctx->{username},
690                 REALM => $ctx->{realm},
691                 PASSWORD => $ctx->{password},
692                 LDAPDIR => $ctx->{ldapdir},
693                 LDAP_INSTANCE => $ctx->{ldap_instance},
694                 SELFTEST_WINBINDD_SOCKET_DIR => $ctx->{winbindd_socket_dir},
695                 NCALRPCDIR => $ctx->{ncalrpcdir},
696                 LOCKDIR => $ctx->{lockdir},
697                 STATEDIR => $ctx->{statedir},
698                 CACHEDIR => $ctx->{cachedir},
699                 PRIVATEDIR => $ctx->{privatedir},
700                 SERVERCONFFILE => $ctx->{smb_conf},
701                 CONFIGURATION => $configuration,
702                 SOCKET_WRAPPER_DEFAULT_IFACE => $ctx->{swiface},
703                 NSS_WRAPPER_PASSWD => $ctx->{nsswrap_passwd},
704                 NSS_WRAPPER_GROUP => $ctx->{nsswrap_group},
705                 NSS_WRAPPER_HOSTS => $ctx->{nsswrap_hosts},
706                 NSS_WRAPPER_HOSTNAME => $ctx->{nsswrap_hostname},
707                 SAMBA_TEST_FIFO => "$ctx->{prefix}/samba_test.fifo",
708                 SAMBA_TEST_LOG => "$ctx->{prefix}/samba_test.log",
709                 SAMBA_TEST_LOG_POS => 0,
710                 NSS_WRAPPER_MODULE_SO_PATH => Samba::nss_wrapper_winbind_so_path($self),
711                 NSS_WRAPPER_MODULE_FN_PREFIX => "winbind",
712                 LOCAL_PATH => $ctx->{share},
713                 UID_RFC2307TEST => $uid_rfc2307test,
714                 GID_RFC2307TEST => $gid_rfc2307test,
715                 SERVER_ROLE => $ctx->{server_role},
716                 RESOLV_CONF => $ctx->{resolv_conf}
717         };
718
719         if (defined($ctx->{use_resolv_wrapper})) {
720                 $ret->{RESOLV_WRAPPER_CONF} = $ctx->{resolv_conf};
721         } else {
722                 $ret->{RESOLV_WRAPPER_HOSTS} = $ctx->{dns_host_file};
723         }
724
725         return $ret;
726 }
727
728 #
729 # Step2 runs the provision script
730 #
731 sub provision_raw_step2($$$)
732 {
733         my ($self, $ctx, $ret) = @_;
734
735         my $provision_cmd = join(" ", @{$ctx->{provision_options}});
736         unless (system($provision_cmd) == 0) {
737                 warn("Unable to provision: \n$provision_cmd\n");
738                 return undef;
739         }
740
741         my $testallowed_account = "testallowed";
742         my $samba_tool_cmd = "";
743         $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
744         $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
745         $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool")
746             . " user create --configfile=$ctx->{smb_conf} $testallowed_account $ctx->{password}";
747         unless (system($samba_tool_cmd) == 0) {
748                 warn("Unable to add testallowed user: \n$samba_tool_cmd\n");
749                 return undef;
750         }
751
752         my $ldbmodify = "";
753         $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
754         $ldbmodify .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
755         $ldbmodify .= Samba::bindir_path($self, "ldbmodify");
756         my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm}));
757
758         if ($ctx->{server_role} ne "domain controller") {
759                 $base_dn = "DC=$ctx->{netbiosname}";
760         }
761
762         my $user_dn = "cn=$testallowed_account,cn=users,$base_dn";
763         $testallowed_account = "testallowed account";
764         open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb");
765         print LDIF "dn: $user_dn
766 changetype: modify
767 replace: samAccountName
768 samAccountName: $testallowed_account
769 -
770 ";
771         close(LDIF);
772
773         open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb");
774         print LDIF "dn: $user_dn
775 changetype: modify
776 replace: userPrincipalName
777 userPrincipalName: testallowed upn\@$ctx->{realm}
778 replace: servicePrincipalName
779 servicePrincipalName: host/testallowed
780 -           
781 ";
782         close(LDIF);
783
784         $samba_tool_cmd = "";
785         $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
786         $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
787         $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool")
788             . " user create --configfile=$ctx->{smb_conf} testdenied $ctx->{password}";
789         unless (system($samba_tool_cmd) == 0) {
790                 warn("Unable to add testdenied user: \n$samba_tool_cmd\n");
791                 return undef;
792         }
793
794         my $user_dn = "cn=testdenied,cn=users,$base_dn";
795         open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb");
796         print LDIF "dn: $user_dn
797 changetype: modify
798 replace: userPrincipalName
799 userPrincipalName: testdenied_upn\@$ctx->{realm}.upn
800 -           
801 ";
802         close(LDIF);
803
804         $samba_tool_cmd = "";
805         $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
806         $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
807         $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool")
808             . " group addmembers --configfile=$ctx->{smb_conf} 'Allowed RODC Password Replication Group' '$testallowed_account'";
809         unless (system($samba_tool_cmd) == 0) {
810                 warn("Unable to add '$testallowed_account' user to 'Allowed RODC Password Replication Group': \n$samba_tool_cmd\n");
811                 return undef;
812         }
813
814         # Create to users alice and bob!
815         my $user_account_array = ["alice", "bob"];
816
817         foreach my $user_account (@{$user_account_array}) {
818                 my $samba_tool_cmd = "";
819
820                 $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
821                 $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
822                 $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool")
823                     . " user create --configfile=$ctx->{smb_conf} $user_account Secret007";
824                 unless (system($samba_tool_cmd) == 0) {
825                         warn("Unable to create user: $user_account\n$samba_tool_cmd\n");
826                         return undef;
827                 }
828         }
829
830         return $ret;
831 }
832
833 sub provision($$$$$$$$$$)
834 {
835         my ($self, $prefix, $server_role, $hostname,
836             $domain, $realm, $functional_level,
837             $password, $kdc_ipv4, $kdc_ipv6, $extra_smbconf_options, $extra_smbconf_shares,
838             $extra_provision_options) = @_;
839
840         my $ctx = $self->provision_raw_prepare($prefix, $server_role,
841                                                $hostname,
842                                                $domain, $realm, $functional_level,
843                                                $password, $kdc_ipv4, $kdc_ipv6);
844
845         if (defined($extra_provision_options)) {
846                 push (@{$ctx->{provision_options}}, @{$extra_provision_options});
847         } else {
848                 push (@{$ctx->{provision_options}}, "--use-ntvfs");
849         }
850
851         $ctx->{share} = "$ctx->{prefix_abs}/share";
852         push(@{$ctx->{directories}}, "$ctx->{share}");
853         push(@{$ctx->{directories}}, "$ctx->{share}/test1");
854         push(@{$ctx->{directories}}, "$ctx->{share}/test2");
855
856         # precreate directories for printer drivers
857         push(@{$ctx->{directories}}, "$ctx->{share}/W32X86");
858         push(@{$ctx->{directories}}, "$ctx->{share}/x64");
859         push(@{$ctx->{directories}}, "$ctx->{share}/WIN40");
860
861         my $msdfs = "no";
862         $msdfs = "yes" if ($server_role eq "domain controller");
863         $ctx->{smb_conf_extra_options} = "
864
865         max xmit = 32K
866         server max protocol = SMB2
867         host msdfs = $msdfs
868         lanman auth = yes
869
870         # fruit:copyfile is a global option
871         fruit:copyfile = yes
872
873         $extra_smbconf_options
874
875 [tmp]
876         path = $ctx->{share}
877         read only = no
878         posix:sharedelay = 100000
879         posix:oplocktimeout = 3
880         posix:writetimeupdatedelay = 500000
881
882 [xcopy_share]
883         path = $ctx->{share}
884         read only = no
885         posix:sharedelay = 100000
886         posix:oplocktimeout = 3
887         posix:writetimeupdatedelay = 500000
888         create mask = 777
889         force create mode = 777
890
891 [posix_share]
892         path = $ctx->{share}
893         read only = no
894         create mask = 0777
895         force create mode = 0
896         directory mask = 0777
897         force directory mode = 0
898
899 [test1]
900         path = $ctx->{share}/test1
901         read only = no
902         posix:sharedelay = 100000
903         posix:oplocktimeout = 3
904         posix:writetimeupdatedelay = 500000
905
906 [test2]
907         path = $ctx->{share}/test2
908         read only = no
909         posix:sharedelay = 100000
910         posix:oplocktimeout = 3
911         posix:writetimeupdatedelay = 500000
912
913 [cifs]
914         path = $ctx->{share}/_ignore_cifs_
915         read only = no
916         ntvfs handler = cifs
917         cifs:server = $ctx->{netbiosname}
918         cifs:share = tmp
919         cifs:use-s4u2proxy = yes
920         # There is no username specified here, instead the client is expected
921         # to log in with kerberos, and the serverwill use delegated credentials.
922         # Or the server tries s4u2self/s4u2proxy to impersonate the client
923
924 [simple]
925         path = $ctx->{share}
926         read only = no
927         ntvfs handler = simple
928
929 [sysvol]
930         path = $ctx->{statedir}/sysvol
931         read only = no
932
933 [netlogon]
934         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
935         read only = no
936
937 [cifsposix]
938         copy = simple
939         ntvfs handler = cifsposix
940
941 [vfs_fruit]
942         path = $ctx->{share}
943         vfs objects = catia fruit streams_xattr acl_xattr
944         ea support = yes
945         fruit:resource = file
946         fruit:metadata = netatalk
947         fruit:locking = netatalk
948         fruit:encoding = native
949
950 $extra_smbconf_shares
951 ";
952
953         if (defined($self->{ldap})) {
954                 $ctx->{ldapdir} = "$ctx->{privatedir}/ldap";
955                 push(@{$ctx->{directories}}, "$ctx->{ldapdir}");
956
957                 my $ldap_uri= "$ctx->{ldapdir}/ldapi";
958                 $ldap_uri =~ s|/|%2F|g;
959                 $ldap_uri = "ldapi://$ldap_uri";
960                 $ctx->{ldap_uri} = $ldap_uri;
961
962                 $ctx->{ldap_instance} = lc($ctx->{netbiosname});
963         }
964
965         my $ret = $self->provision_raw_step1($ctx);
966         unless (defined $ret) {
967                 return undef;
968         }
969
970         if (defined($self->{ldap})) {
971                 $ret->{LDAP_URI} = $ctx->{ldap_uri};
972                 push (@{$ctx->{provision_options}}, "--ldap-backend-type=" . $self->{ldap});
973                 push (@{$ctx->{provision_options}}, "--ldap-backend-nosync");
974                 if ($self->{ldap} eq "openldap") {
975                         push (@{$ctx->{provision_options}}, "--slapd-path=" . $ENV{OPENLDAP_SLAPD});
976                         ($ret->{SLAPD_CONF_D}, $ret->{OPENLDAP_PIDFILE}) = $self->mk_openldap($ctx) or die("Unable to create openldap directories");
977
978                 } elsif ($self->{ldap} eq "fedora-ds") {
979                         push (@{$ctx->{provision_options}}, "--slapd-path=" . "$ENV{FEDORA_DS_ROOT}/sbin/ns-slapd");
980                         push (@{$ctx->{provision_options}}, "--setup-ds-path=" . "$ENV{FEDORA_DS_ROOT}/sbin/setup-ds.pl");
981                         ($ret->{FEDORA_DS_DIR}, $ret->{FEDORA_DS_PIDFILE}) = $self->mk_fedora_ds($ctx) or die("Unable to create fedora ds directories");
982                 }
983
984         }
985
986         return $self->provision_raw_step2($ctx, $ret);
987 }
988
989 sub provision_s4member($$$$$)
990 {
991         my ($self, $prefix, $dcvars, $hostname, $more_conf) = @_;
992         print "PROVISIONING MEMBER...\n";
993         my $extra_smb_conf = "
994         passdb backend = samba_dsdb
995 winbindd:use external pipes = true
996
997 # the source4 smb server doesn't allow signing by default
998 server signing = enabled
999
1000 rpc_server:default = external
1001 rpc_server:svcctl = embedded
1002 rpc_server:srvsvc = embedded
1003 rpc_server:eventlog = embedded
1004 rpc_server:ntsvcs = embedded
1005 rpc_server:winreg = embedded
1006 rpc_server:spoolss = embedded
1007 rpc_daemon:spoolssd = embedded
1008 rpc_server:tcpip = no
1009 ";
1010         if ($more_conf) {
1011                 $extra_smb_conf = $extra_smb_conf . $more_conf . "\n";
1012         }
1013         my $ret = $self->provision($prefix,
1014                                    "member server",
1015                                    $hostname,
1016                                    "SAMBADOMAIN",
1017                                    "samba.example.com",
1018                                    "2008",
1019                                    "locMEMpass3",
1020                                    $dcvars->{SERVER_IP},
1021                                    $dcvars->{SERVER_IPV6},
1022                                    $extra_smb_conf, "", undef);
1023         unless ($ret) {
1024                 return undef;
1025         }
1026
1027         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1028         my $cmd = "";
1029         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1030         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1031                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1032         } else {
1033                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1034         }
1035         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1036         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1037         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} member";
1038         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1039         $cmd .= " --machinepass=machine$ret->{PASSWORD}";
1040
1041         unless (system($cmd) == 0) {
1042                 warn("Join failed\n$cmd");
1043                 return undef;
1044         }
1045
1046         $ret->{MEMBER_SERVER} = $ret->{SERVER};
1047         $ret->{MEMBER_SERVER_IP} = $ret->{SERVER_IP};
1048         $ret->{MEMBER_SERVER_IPV6} = $ret->{SERVER_IPV6};
1049         $ret->{MEMBER_NETBIOSNAME} = $ret->{NETBIOSNAME};
1050         $ret->{MEMBER_USERNAME} = $ret->{USERNAME};
1051         $ret->{MEMBER_PASSWORD} = $ret->{PASSWORD};
1052
1053         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1054         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1055         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1056         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1057         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1058         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1059
1060         return $ret;
1061 }
1062
1063 sub provision_rpc_proxy($$$)
1064 {
1065         my ($self, $prefix, $dcvars) = @_;
1066         print "PROVISIONING RPC PROXY...\n";
1067
1068         my $extra_smbconf_options = "
1069         passdb backend = samba_dsdb
1070
1071         # rpc_proxy
1072         dcerpc_remote:binding = ncacn_ip_tcp:$dcvars->{SERVER}
1073         dcerpc endpoint servers = epmapper, remote
1074         dcerpc_remote:interfaces = rpcecho
1075
1076 [cifs_to_dc]
1077         path = /tmp/_ignore_cifs_to_dc_/_none_
1078         read only = no
1079         ntvfs handler = cifs
1080         cifs:server = $dcvars->{SERVER}
1081         cifs:share = cifs
1082         cifs:use-s4u2proxy = yes
1083         # There is no username specified here, instead the client is expected
1084         # to log in with kerberos, and the serverwill use delegated credentials.
1085         # Or the server tries s4u2self/s4u2proxy to impersonate the client
1086
1087 ";
1088
1089         my $ret = $self->provision($prefix,
1090                                    "member server",
1091                                    "localrpcproxy",
1092                                    "SAMBADOMAIN",
1093                                    "samba.example.com",
1094                                    "2008",
1095                                    "locRPCproxypass4",
1096                                    $dcvars->{SERVER_IP},
1097                                    $dcvars->{SERVER_IPV6},
1098                                    $extra_smbconf_options, "", undef);
1099         unless ($ret) {
1100                 return undef;
1101         }
1102
1103         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1104
1105         # The joind runs in the context of the rpc_proxy/member for now
1106         my $cmd = "";
1107         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1108         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1109                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1110         } else {
1111                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1112         }
1113         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1114         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1115         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} member";
1116         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1117         $cmd .= " --machinepass=machine$ret->{PASSWORD}";
1118
1119         unless (system($cmd) == 0) {
1120                 warn("Join failed\n$cmd");
1121                 return undef;
1122         }
1123
1124         # Setting up delegation runs in the context of the DC for now
1125         $cmd = "";
1126         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$dcvars->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1127         $cmd .= "KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" ";
1128         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1129         $cmd .= "$samba_tool delegation for-any-protocol '$ret->{NETBIOSNAME}\$' on";
1130         $cmd .= " $dcvars->{CONFIGURATION}";
1131         print $cmd;
1132
1133         unless (system($cmd) == 0) {
1134                 warn("Delegation failed\n$cmd");
1135                 return undef;
1136         }
1137
1138         # Setting up delegation runs in the context of the DC for now
1139         $cmd = "";
1140         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$dcvars->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1141         $cmd .= "KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" ";
1142         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1143         $cmd .= "$samba_tool delegation add-service '$ret->{NETBIOSNAME}\$' cifs/$dcvars->{SERVER}";
1144         $cmd .= " $dcvars->{CONFIGURATION}";
1145
1146         unless (system($cmd) == 0) {
1147                 warn("Delegation failed\n$cmd");
1148                 return undef;
1149         }
1150
1151         $ret->{RPC_PROXY_SERVER} = $ret->{SERVER};
1152         $ret->{RPC_PROXY_SERVER_IP} = $ret->{SERVER_IP};
1153         $ret->{RPC_PROXY_SERVER_IPV6} = $ret->{SERVER_IPV6};
1154         $ret->{RPC_PROXY_NETBIOSNAME} = $ret->{NETBIOSNAME};
1155         $ret->{RPC_PROXY_USERNAME} = $ret->{USERNAME};
1156         $ret->{RPC_PROXY_PASSWORD} = $ret->{PASSWORD};
1157
1158         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1159         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1160         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1161         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1162         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1163         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1164
1165         return $ret;
1166 }
1167
1168 sub provision_promoted_dc($$$)
1169 {
1170         my ($self, $prefix, $dcvars) = @_;
1171         print "PROVISIONING PROMOTED DC...\n";
1172
1173         # We do this so that we don't run the provision.  That's the job of 'samba-tool domain dcpromo'.
1174         my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
1175                                                "promotedvdc",
1176                                                "SAMBADOMAIN",
1177                                                "samba.example.com",
1178                                                "2008",
1179                                                $dcvars->{PASSWORD},
1180                                                $dcvars->{SERVER_IP},
1181                                                $dcvars->{SERVER_IPV6});
1182
1183         push (@{$ctx->{provision_options}}, "--use-ntvfs");
1184
1185         $ctx->{smb_conf_extra_options} = "
1186         max xmit = 32K
1187         server max protocol = SMB2
1188
1189 [sysvol]
1190         path = $ctx->{statedir}/sysvol
1191         read only = yes
1192
1193 [netlogon]
1194         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
1195         read only = no
1196
1197 ";
1198
1199         my $ret = $self->provision_raw_step1($ctx);
1200         unless ($ret) {
1201                 return undef;
1202         }
1203
1204         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1205         my $cmd = "";
1206         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1207         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1208                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1209         } else {
1210                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1211         }
1212         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1213         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1214         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} MEMBER --realm=$dcvars->{REALM}";
1215         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1216         $cmd .= " --machinepass=machine$ret->{PASSWORD}";
1217
1218         unless (system($cmd) == 0) {
1219                 warn("Join failed\n$cmd");
1220                 return undef;
1221         }
1222
1223         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1224         my $cmd = "";
1225         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1226         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1227         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1228         $cmd .= "$samba_tool domain dcpromo $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}";
1229         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1230         $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs --dns-backend=BIND9_DLZ";
1231
1232         unless (system($cmd) == 0) {
1233                 warn("Join failed\n$cmd");
1234                 return undef;
1235         }
1236
1237         $ret->{PROMOTED_DC_SERVER} = $ret->{SERVER};
1238         $ret->{PROMOTED_DC_SERVER_IP} = $ret->{SERVER_IP};
1239         $ret->{PROMOTED_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1240         $ret->{PROMOTED_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1241
1242         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1243         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1244         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1245         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1246         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1247         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1248
1249         return $ret;
1250 }
1251
1252 sub provision_vampire_dc($$$)
1253 {
1254         my ($self, $prefix, $dcvars, $fl) = @_;
1255         print "PROVISIONING VAMPIRE DC @ FL $fl...\n";
1256         my $name = "localvampiredc";
1257
1258         if ($fl == "2000") {
1259             $name = "vampire2000dc";
1260         }
1261
1262         # We do this so that we don't run the provision.  That's the job of 'net vampire'.
1263         my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
1264                                                $name,
1265                                                $dcvars->{DOMAIN},
1266                                                $dcvars->{REALM},
1267                                                $fl,
1268                                                $dcvars->{PASSWORD},
1269                                                $dcvars->{SERVER_IP},
1270                                                $dcvars->{SERVER_IPV6});
1271
1272         push (@{$ctx->{provision_options}}, "--use-ntvfs");
1273
1274         $ctx->{smb_conf_extra_options} = "
1275         max xmit = 32K
1276         server max protocol = SMB2
1277
1278 [sysvol]
1279         path = $ctx->{statedir}/sysvol
1280         read only = yes
1281
1282 [netlogon]
1283         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
1284         read only = no
1285
1286 ";
1287
1288         my $ret = $self->provision_raw_step1($ctx);
1289         unless ($ret) {
1290                 return undef;
1291         }
1292
1293         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1294         my $cmd = "";
1295         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1296         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1297                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1298         } else {
1299                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1300         }
1301         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1302         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1303         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}";
1304         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD} --domain-critical-only";
1305         $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs";
1306
1307         unless (system($cmd) == 0) {
1308                 warn("Join failed\n$cmd");
1309                 return undef;
1310         }
1311
1312         if ($fl == "2000") {
1313                 $ret->{VAMPIRE_2000_DC_SERVER} = $ret->{SERVER};
1314                 $ret->{VAMPIRE_2000_DC_SERVER_IP} = $ret->{SERVER_IP};
1315                 $ret->{VAMPIRE_2000_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1316                 $ret->{VAMPIRE_2000_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1317         } else {
1318                 $ret->{VAMPIRE_DC_SERVER} = $ret->{SERVER};
1319                 $ret->{VAMPIRE_DC_SERVER_IP} = $ret->{SERVER_IP};
1320                 $ret->{VAMPIRE_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1321                 $ret->{VAMPIRE_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1322         }
1323         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1324         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1325         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1326         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1327         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1328         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1329         $ret->{DC_REALM} = $dcvars->{DC_REALM};
1330
1331         return $ret;
1332 }
1333
1334 sub provision_subdom_dc($$$)
1335 {
1336         my ($self, $prefix, $dcvars) = @_;
1337         print "PROVISIONING SUBDOMAIN DC...\n";
1338
1339         # We do this so that we don't run the provision.  That's the job of 'net vampire'.
1340         my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
1341                                                "localsubdc",
1342                                                "SAMBASUBDOM",
1343                                                "sub.samba.example.com",
1344                                                "2008",
1345                                                $dcvars->{PASSWORD},
1346                                                undef);
1347
1348         push (@{$ctx->{provision_options}}, "--use-ntvfs");
1349
1350         $ctx->{smb_conf_extra_options} = "
1351         max xmit = 32K
1352         server max protocol = SMB2
1353
1354 [sysvol]
1355         path = $ctx->{statedir}/sysvol
1356         read only = yes
1357
1358 [netlogon]
1359         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
1360         read only = no
1361
1362 ";
1363
1364         my $ret = $self->provision_raw_step1($ctx);
1365         unless ($ret) {
1366                 return undef;
1367         }
1368
1369         Samba::mk_krb5_conf($ctx);
1370
1371         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1372         my $cmd = "";
1373         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1374         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1375                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1376         } else {
1377                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1378         }
1379         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1380         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1381         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $ctx->{dnsname} subdomain ";
1382         $cmd .= "--parent-domain=$dcvars->{REALM} -U$dcvars->{DC_USERNAME}\@$dcvars->{REALM}\%$dcvars->{DC_PASSWORD}";
1383         $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs";
1384         $cmd .= " --adminpass=$ret->{PASSWORD}";
1385
1386         unless (system($cmd) == 0) {
1387                 warn("Join failed\n$cmd");
1388                 return undef;
1389         }
1390
1391         $ret->{SUBDOM_DC_SERVER} = $ret->{SERVER};
1392         $ret->{SUBDOM_DC_SERVER_IP} = $ret->{SERVER_IP};
1393         $ret->{SUBDOM_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1394         $ret->{SUBDOM_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1395
1396         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1397         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1398         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1399         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1400         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1401         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1402
1403         return $ret;
1404 }
1405
1406 sub provision_ad_dc_ntvfs($$)
1407 {
1408         my ($self, $prefix) = @_;
1409
1410         # We keep the old 'winbind' name here in server services to
1411         # ensure upgrades which used that name still work with the now
1412         # alias.
1413
1414         print "PROVISIONING AD DC (NTVFS)...\n";
1415         my $extra_conf_options = "netbios aliases = localDC1-a
1416         server services = +winbind -winbindd
1417         ldap server require strong auth = allow_sasl_over_tls
1418         allow nt4 crypto = yes
1419         lsa over netlogon = yes
1420         rpc server port = 1027
1421         ";
1422         my $ret = $self->provision($prefix,
1423                                    "domain controller",
1424                                    "localdc",
1425                                    "SAMBADOMAIN",
1426                                    "samba.example.com",
1427                                    "2008",
1428                                    "locDCpass1",
1429                                    undef,
1430                                    undef,
1431                                    $extra_conf_options,
1432                                    "",
1433                                    undef);
1434         unless ($ret) {
1435                 return undef;
1436         }
1437
1438         unless($self->add_wins_config("$prefix/private")) {
1439                 warn("Unable to add wins configuration");
1440                 return undef;
1441         }
1442         $ret->{NETBIOSALIAS} = "localdc1-a";
1443         $ret->{DC_SERVER} = $ret->{SERVER};
1444         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1445         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1446         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1447         $ret->{DC_USERNAME} = $ret->{USERNAME};
1448         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1449         $ret->{DC_REALM} = $ret->{REALM};
1450
1451         return $ret;
1452 }
1453
1454 sub provision_fl2000dc($$)
1455 {
1456         my ($self, $prefix) = @_;
1457
1458         print "PROVISIONING DC WITH FOREST LEVEL 2000...\n";
1459         my $extra_conf_options = "
1460         spnego:simulate_w2k=yes
1461         ntlmssp_server:force_old_spnego=yes
1462 ";
1463         my $ret = $self->provision($prefix,
1464                                    "domain controller",
1465                                    "dc5",
1466                                    "SAMBA2000",
1467                                    "samba2000.example.com",
1468                                    "2000",
1469                                    "locDCpass5",
1470                                    undef,
1471                                    undef,
1472                                    $extra_conf_options,
1473                                    "",
1474                                    undef);
1475         unless ($ret) {
1476                 return undef;
1477         }
1478
1479         unless($self->add_wins_config("$prefix/private")) {
1480                 warn("Unable to add wins configuration");
1481                 return undef;
1482         }
1483         $ret->{DC_SERVER} = $ret->{SERVER};
1484         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1485         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1486         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1487         $ret->{DC_USERNAME} = $ret->{USERNAME};
1488         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1489         $ret->{DC_REALM} = $ret->{REALM};
1490
1491         return $ret;
1492 }
1493
1494 sub provision_fl2003dc($$$)
1495 {
1496         my ($self, $prefix, $dcvars) = @_;
1497         my $swiface1 = Samba::get_interface("fakednsforwarder1");
1498         my $swiface2 = Samba::get_interface("fakednsforwarder2");
1499
1500         print "PROVISIONING DC WITH FOREST LEVEL 2003...\n";
1501         my $extra_conf_options = "allow dns updates = nonsecure and secure
1502         dns forwarder = 127.0.0.$swiface1 127.0.0.$swiface2";
1503         my $ret = $self->provision($prefix,
1504                                    "domain controller",
1505                                    "dc6",
1506                                    "SAMBA2003",
1507                                    "samba2003.example.com",
1508                                    "2003",
1509                                    "locDCpass6",
1510                                    undef,
1511                                    undef,
1512                                    $extra_conf_options,
1513                                    "",
1514                                    undef);
1515         unless (defined $ret) {
1516                 return undef;
1517         }
1518
1519         $ret->{DC_SERVER} = $ret->{SERVER};
1520         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1521         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1522         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1523         $ret->{DC_USERNAME} = $ret->{USERNAME};
1524         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1525         $ret->{DNS_FORWARDER1} = "127.0.0.$swiface1";
1526         $ret->{DNS_FORWARDER2} = "127.0.0.$swiface2";
1527
1528         my @samba_tool_options;
1529         push (@samba_tool_options, Samba::bindir_path($self, "samba-tool"));
1530         push (@samba_tool_options, "domain");
1531         push (@samba_tool_options, "passwordsettings");
1532         push (@samba_tool_options, "set");
1533         push (@samba_tool_options, "--configfile=$ret->{SERVERCONFFILE}");
1534         push (@samba_tool_options, "--min-pwd-age=0");
1535         push (@samba_tool_options, "--history-length=1");
1536
1537         my $samba_tool_cmd = join(" ", @samba_tool_options);
1538
1539         unless (system($samba_tool_cmd) == 0) {
1540                 warn("Unable to set min password age to 0: \n$samba_tool_cmd\n");
1541                 return undef;
1542         }
1543
1544         unless($self->add_wins_config("$prefix/private")) {
1545                 warn("Unable to add wins configuration");
1546                 return undef;
1547         }
1548
1549         return $ret;
1550 }
1551
1552 sub provision_fl2008r2dc($$$)
1553 {
1554         my ($self, $prefix, $dcvars) = @_;
1555
1556         print "PROVISIONING DC WITH FOREST LEVEL 2008r2...\n";
1557         my $extra_conf_options = "ldap server require strong auth = no";
1558         my $ret = $self->provision($prefix,
1559                                    "domain controller",
1560                                    "dc7",
1561                                    "SAMBA2008R2",
1562                                    "samba2008R2.example.com",
1563                                    "2008_R2",
1564                                    "locDCpass7",
1565                                    undef,
1566                                    undef,
1567                                    $extra_conf_options,
1568                                    "",
1569                                    undef);
1570         unless (defined $ret) {
1571                 return undef;
1572         }
1573
1574         unless ($self->add_wins_config("$prefix/private")) {
1575                 warn("Unable to add wins configuration");
1576                 return undef;
1577         }
1578         $ret->{DC_SERVER} = $ret->{SERVER};
1579         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1580         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1581         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1582         $ret->{DC_USERNAME} = $ret->{USERNAME};
1583         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1584         $ret->{DC_REALM} = $ret->{REALM};
1585
1586         return $ret;
1587 }
1588
1589
1590 sub provision_rodc($$$)
1591 {
1592         my ($self, $prefix, $dcvars) = @_;
1593         print "PROVISIONING RODC...\n";
1594
1595         # We do this so that we don't run the provision.  That's the job of 'net join RODC'.
1596         my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
1597                                                "rodc",
1598                                                "SAMBADOMAIN",
1599                                                "samba.example.com",
1600                                                "2008",
1601                                                $dcvars->{PASSWORD},
1602                                                $dcvars->{SERVER_IP},
1603                                                $dcvars->{SERVER_IPV6});
1604         unless ($ctx) {
1605                 return undef;
1606         }
1607
1608         push (@{$ctx->{provision_options}}, "--use-ntvfs");
1609
1610         $ctx->{share} = "$ctx->{prefix_abs}/share";
1611         push(@{$ctx->{directories}}, "$ctx->{share}");
1612
1613         $ctx->{smb_conf_extra_options} = "
1614         max xmit = 32K
1615         server max protocol = SMB2
1616
1617 [sysvol]
1618         path = $ctx->{statedir}/sysvol
1619         read only = yes
1620
1621 [netlogon]
1622         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
1623         read only = yes
1624
1625 [tmp]
1626         path = $ctx->{share}
1627         read only = no
1628         posix:sharedelay = 10000
1629         posix:oplocktimeout = 3
1630         posix:writetimeupdatedelay = 50000
1631
1632 ";
1633
1634         my $ret = $self->provision_raw_step1($ctx);
1635         unless ($ret) {
1636                 return undef;
1637         }
1638
1639         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1640         my $cmd = "";
1641         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1642         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1643                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1644         } else {
1645                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1646         }
1647         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1648         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1649         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} RODC";
1650         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1651         $cmd .= " --server=$dcvars->{DC_SERVER} --use-ntvfs";
1652
1653         unless (system($cmd) == 0) {
1654                 warn("RODC join failed\n$cmd");
1655                 return undef;
1656         }
1657
1658         # This ensures deterministic behaviour for tests that want to have the 'testallowed account'
1659         # user password verified on the RODC
1660         my $testallowed_account = "testallowed account";
1661         $cmd = "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1662         $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
1663         $cmd .= "$samba_tool rodc preload '$testallowed_account' $ret->{CONFIGURATION}";
1664         $cmd .= " --server=$dcvars->{DC_SERVER}";
1665
1666         unless (system($cmd) == 0) {
1667                 warn("RODC join failed\n$cmd");
1668                 return undef;
1669         }
1670
1671         # we overwrite the kdc after the RODC join
1672         # so that use the RODC as kdc and test
1673         # the proxy code
1674         $ctx->{kdc_ipv4} = $ret->{SERVER_IP};
1675         $ctx->{kdc_ipv6} = $ret->{SERVER_IPV6};
1676         Samba::mk_krb5_conf($ctx);
1677
1678         $ret->{RODC_DC_SERVER} = $ret->{SERVER};
1679         $ret->{RODC_DC_SERVER_IP} = $ret->{SERVER_IP};
1680         $ret->{RODC_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1681         $ret->{RODC_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1682
1683         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1684         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1685         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1686         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1687         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1688         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1689
1690         return $ret;
1691 }
1692
1693 sub read_config_h($)
1694 {
1695         my ($name) = @_;
1696         my %ret = {};
1697         open(LF, "<$name") or die("unable to read $name: $!");
1698         while (<LF>) {
1699                 chomp;
1700                 next if not (/^#define /);
1701                 if (/^#define (.*?)[ \t]+(.*?)$/) {
1702                         $ret{$1} = $2;
1703                         next;
1704                 }
1705                 if (/^#define (.*?)[ \t]+$/) {
1706                         $ret{$1} = 1;;
1707                         next;
1708                 }
1709         }
1710         close(LF);
1711         return \%ret;
1712 }
1713
1714 sub provision_ad_dc($$)
1715 {
1716         my ($self, $prefix) = @_;
1717
1718         my $prefix_abs = abs_path($prefix);
1719
1720         my $bindir_abs = abs_path($self->{bindir});
1721         my $lockdir="$prefix_abs/lockdir";
1722         my $conffile="$prefix_abs/etc/smb.conf";
1723
1724         my $require_mutexes = "dbwrap_tdb_require_mutexes:* = yes";
1725         $require_mutexes = "" if ($ENV{SELFTEST_DONT_REQUIRE_TDB_MUTEX_SUPPORT} eq "1");
1726
1727         my $config_h = {};
1728
1729         if (defined($ENV{CONFIG_H})) {
1730                 $config_h = read_config_h($ENV{CONFIG_H});
1731         }
1732
1733         my $password_hash_gpg_key_ids = "password hash gpg key ids = 4952E40301FAB41A";
1734         $password_hash_gpg_key_ids = "" unless defined($config_h->{HAVE_GPGME});
1735
1736         my $extra_smbconf_options = "
1737         server services = -smb +s3fs
1738         xattr_tdb:file = $prefix_abs/statedir/xattr.tdb
1739
1740         dbwrap_tdb_mutexes:* = yes
1741         ${require_mutexes}
1742
1743         ${password_hash_gpg_key_ids}
1744
1745         kernel oplocks = no
1746         kernel change notify = no
1747         smb2 leases = no
1748
1749         logging = file
1750         printing = bsd
1751         printcap name = /dev/null
1752
1753         max protocol = SMB3
1754         read only = no
1755
1756         smbd:sharedelay = 100000
1757         smbd:writetimeupdatedelay = 500000
1758         create mask = 755
1759         dos filemode = yes
1760
1761         dcerpc endpoint servers = -winreg -srvsvc
1762
1763         printcap name = /dev/null
1764
1765         addprinter command = $ENV{SRCDIR_ABS}/source3/script/tests/printing/modprinter.pl -a -s $conffile --
1766         deleteprinter command = $ENV{SRCDIR_ABS}/source3/script/tests/printing/modprinter.pl -d -s $conffile --
1767
1768         printing = vlp
1769         print command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb print %p %s
1770         lpq command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpq %p
1771         lp rm command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lprm %p %j
1772         lp pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lppause %p %j
1773         lp resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpresume %p %j
1774         queue pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queuepause %p
1775         queue resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queueresume %p
1776         lpq cache time = 0
1777         print notify backchannel = yes
1778 ";
1779
1780         my $extra_smbconf_shares = "
1781
1782 [tmpenc]
1783         copy = tmp
1784         smb encrypt = required
1785
1786 [tmpcase]
1787         copy = tmp
1788         case sensitive = yes
1789
1790 [tmpguest]
1791         copy = tmp
1792         guest ok = yes
1793
1794 [hideunread]
1795         copy = tmp
1796         hide unreadable = yes
1797
1798 [durable]
1799         copy = tmp
1800         kernel share modes = no
1801         kernel oplocks = no
1802         posix locking = no
1803
1804 [print\$]
1805         copy = tmp
1806
1807 [print1]
1808         copy = tmp
1809         printable = yes
1810
1811 [print2]
1812         copy = print1
1813 [print3]
1814         copy = print1
1815 [lp]
1816         copy = print1
1817 ";
1818
1819         print "PROVISIONING AD DC...\n";
1820         my $ret = $self->provision($prefix,
1821                                    "domain controller",
1822                                    "addc",
1823                                    "ADDOMAIN",
1824                                    "addom.samba.example.com",
1825                                    "2008",
1826                                    "locDCpass1",
1827                                    undef,
1828                                    undef,
1829                                    $extra_smbconf_options,
1830                                    $extra_smbconf_shares,
1831                                    undef);
1832         unless (defined $ret) {
1833                 return undef;
1834         }
1835
1836         unless($self->add_wins_config("$prefix/private")) {
1837                 warn("Unable to add wins configuration");
1838                 return undef;
1839         }
1840
1841         $ret->{DC_SERVER} = $ret->{SERVER};
1842         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1843         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1844         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1845         $ret->{DC_USERNAME} = $ret->{USERNAME};
1846         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1847
1848         return $ret;
1849 }
1850
1851 sub provision_chgdcpass($$)
1852 {
1853         my ($self, $prefix) = @_;
1854
1855         print "PROVISIONING CHGDCPASS...\n";
1856         my $extra_provision_options = undef;
1857         # This environment disallows the use of this password
1858         # (and also removes the default AD complexity checks)
1859         my $unacceptable_password = "widk3Dsle32jxdBdskldsk55klASKQ";
1860         push (@{$extra_provision_options}, "--dns-backend=BIND9_DLZ");
1861         my $ret = $self->provision($prefix,
1862                                    "domain controller",
1863                                    "chgdcpass",
1864                                    "CHDCDOMAIN",
1865                                    "chgdcpassword.samba.example.com",
1866                                    "2008",
1867                                    "chgDCpass1",
1868                                    undef,
1869                                    undef,
1870                                    "check password script = sed -e '/$unacceptable_password/{;q1}; /$unacceptable_password/!{q0}'\n",
1871                                    "",
1872                                    $extra_provision_options);
1873         unless (defined $ret) {
1874                 return undef;
1875         }
1876
1877         unless($self->add_wins_config("$prefix/private")) {
1878                 warn("Unable to add wins configuration");
1879                 return undef;
1880         }
1881         
1882         # Remove secrets.tdb from this environment to test that we
1883         # still start up on systems without the new matching
1884         # secrets.tdb records.
1885         unless (unlink("$ret->{PRIVATEDIR}/secrets.tdb") || unlink("$ret->{PRIVATEDIR}/secrets.ntdb")) {
1886                 warn("Unable to remove $ret->{PRIVATEDIR}/secrets.tdb added during provision");
1887                 return undef;
1888         }
1889             
1890         $ret->{DC_SERVER} = $ret->{SERVER};
1891         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1892         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1893         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1894         $ret->{DC_USERNAME} = $ret->{USERNAME};
1895         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1896         $ret->{UNACCEPTABLE_PASSWORD} = $unacceptable_password;
1897
1898         return $ret;
1899 }
1900
1901 sub teardown_env_terminate($$)
1902 {
1903         my ($self, $envvars) = @_;
1904         my $pid;
1905
1906         # This should cause samba to terminate gracefully
1907         close($envvars->{STDIN_PIPE});
1908
1909         $pid = $envvars->{SAMBA_PID};
1910         my $count = 0;
1911         my $childpid;
1912
1913         # This should give it time to write out the gcov data
1914         until ($count > 15) {
1915             if (Samba::cleanup_child($pid, "samba") != 0) {
1916                 return;
1917             }
1918             sleep(1);
1919             $count++;
1920         }
1921
1922         # After 15 Seconds, work out why this thing is still alive
1923         warn "server process $pid took more than $count seconds to exit, showing backtrace:\n";
1924         system("$self->{srcdir}/selftest/gdb_backtrace $pid");
1925
1926         until ($count > 30) {
1927             if (Samba::cleanup_child($pid, "samba") != 0) {
1928                 return;
1929             }
1930             sleep(1);
1931             $count++;
1932         }
1933
1934         if (kill(0, $pid)) {
1935             warn "server process $pid took more than $count seconds to exit, sending SIGTERM\n";
1936             kill "TERM", $pid;
1937         }
1938
1939         until ($count > 40) {
1940             if (Samba::cleanup_child($pid, "samba") != 0) {
1941                 return;
1942             }
1943             sleep(1);
1944             $count++;
1945         }
1946         # If it is still around, kill it
1947         if (kill(0, $pid)) {
1948             warn "server process $pid took more than $count seconds to exit, killing\n with SIGKILL\n";
1949             kill 9, $pid;
1950         }
1951         return;
1952 }
1953
1954 sub teardown_env($$)
1955 {
1956         my ($self, $envvars) = @_;
1957         teardown_env_terminate($self, $envvars);
1958
1959         $self->slapd_stop($envvars) if ($self->{ldap});
1960
1961         print $self->getlog_env($envvars);
1962
1963         return;
1964 }
1965
1966 sub getlog_env($$)
1967 {
1968         my ($self, $envvars) = @_;
1969         my $title = "SAMBA LOG of: $envvars->{NETBIOSNAME} pid $envvars->{SAMBA_PID}\n";
1970         my $out = $title;
1971
1972         open(LOG, "<$envvars->{SAMBA_TEST_LOG}");
1973
1974         seek(LOG, $envvars->{SAMBA_TEST_LOG_POS}, SEEK_SET);
1975         while (<LOG>) {
1976                 $out .= $_;
1977         }
1978         $envvars->{SAMBA_TEST_LOG_POS} = tell(LOG);
1979         close(LOG);
1980
1981         return "" if $out eq $title;
1982
1983         return $out;
1984 }
1985
1986 sub check_env($$)
1987 {
1988         my ($self, $envvars) = @_;
1989         my $samba_pid = $envvars->{SAMBA_PID};
1990
1991         if (not defined($samba_pid)) {
1992             return 0;
1993         } elsif ($samba_pid > 0) {
1994             my $childpid = Samba::cleanup_child($samba_pid, "samba");
1995
1996             if ($childpid == 0) {
1997                 return 1;
1998             }
1999             return 0;
2000         } else {
2001             return 1;
2002         }
2003
2004 }
2005
2006 sub setup_env($$$)
2007 {
2008         my ($self, $envname, $path) = @_;
2009         my $target3 = $self->{target3};
2010
2011         $ENV{ENVNAME} = $envname;
2012
2013         if (defined($self->{vars}->{$envname})) {
2014                 return $self->{vars}->{$envname};
2015         }
2016
2017         if ($envname eq "ad_dc_ntvfs") {
2018                 return $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2019         } elsif ($envname eq "fl2000dc") {
2020                 return $self->setup_fl2000dc("$path/fl2000dc");
2021         } elsif ($envname eq "vampire_2000_dc") {
2022                 if (not defined($self->{vars}->{fl2000dc})) {
2023                         $self->setup_fl2000dc("$path/fl2000dc");
2024                 }
2025                 return $self->setup_vampire_dc("$path/vampire_2000_dc", $self->{vars}->{fl2000dc}, "2000");
2026         } elsif ($envname eq "fl2003dc") {
2027                 if (not defined($self->{vars}->{ad_dc})) {
2028                         $self->setup_ad_dc("$path/ad_dc");
2029                 }
2030                 return $self->setup_fl2003dc("$path/fl2003dc", $self->{vars}->{ad_dc});
2031         } elsif ($envname eq "fl2008r2dc") {
2032                 if (not defined($self->{vars}->{ad_dc})) {
2033                         $self->setup_ad_dc("$path/ad_dc");
2034                 }
2035                 return $self->setup_fl2008r2dc("$path/fl2008r2dc", $self->{vars}->{ad_dc});
2036         } elsif ($envname eq "rpc_proxy") {
2037                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2038                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2039                 }
2040                 return $self->setup_rpc_proxy("$path/rpc_proxy", $self->{vars}->{ad_dc_ntvfs});
2041         } elsif ($envname eq "vampire_dc") {
2042                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2043                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2044                 }
2045                 return $self->setup_vampire_dc("$path/vampire_dc", $self->{vars}->{ad_dc_ntvfs}, "2008");
2046         } elsif ($envname eq "promoted_dc") {
2047                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2048                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2049                 }
2050                 return $self->setup_promoted_dc("$path/promoted_dc", $self->{vars}->{ad_dc_ntvfs});
2051         } elsif ($envname eq "subdom_dc") {
2052                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2053                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2054                 }
2055                 return $self->setup_subdom_dc("$path/subdom_dc", $self->{vars}->{ad_dc_ntvfs});
2056         } elsif ($envname eq "s4member_dflt_domain") {
2057                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2058                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2059                 }
2060                 return $self->setup_s4member_dflt_domain("$path/s4member_dflt_domain", $self->{vars}->{ad_dc_ntvfs});
2061         } elsif ($envname eq "s4member") {
2062                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2063                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2064                 }
2065                 return $self->setup_s4member("$path/s4member", $self->{vars}->{ad_dc_ntvfs});
2066         } elsif ($envname eq "rodc") {
2067                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2068                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2069                 }
2070                 return $self->setup_rodc("$path/rodc", $self->{vars}->{ad_dc_ntvfs});
2071         } elsif ($envname eq "chgdcpass") {
2072                 return $self->setup_chgdcpass("$path/chgdcpass", $self->{vars}->{chgdcpass});
2073         } elsif ($envname eq "ad_member") {
2074                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2075                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2076                 }
2077                 return $target3->setup_admember("$path/ad_member", $self->{vars}->{ad_dc_ntvfs}, 29);
2078         } elsif ($envname eq "ad_dc") {
2079                 return $self->setup_ad_dc("$path/ad_dc");
2080         } elsif ($envname eq "ad_dc_no_nss") {
2081                 return $self->setup_ad_dc("$path/ad_dc_no_nss", "no_nss");
2082         } elsif ($envname eq "ad_member_rfc2307") {
2083                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
2084                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
2085                 }
2086                 return $target3->setup_admember_rfc2307("$path/ad_member_rfc2307",
2087                                                         $self->{vars}->{ad_dc_ntvfs}, 34);
2088         } elsif ($envname eq "none") {
2089                 return $self->setup_none("$path/none");
2090         } else {
2091                 return "UNKNOWN";
2092         }
2093 }
2094
2095 sub setup_s4member($$$)
2096 {
2097         my ($self, $path, $dc_vars) = @_;
2098
2099         my $env = $self->provision_s4member($path, $dc_vars, "s4member");
2100
2101         if (defined $env) {
2102                 if (not defined($self->check_or_start($env, "standard"))) {
2103                         return undef;
2104                 }
2105
2106                 $self->{vars}->{s4member} = $env;
2107         }
2108
2109         return $env;
2110 }
2111
2112 sub setup_s4member_dflt_domain($$$)
2113 {
2114         my ($self, $path, $dc_vars) = @_;
2115
2116         my $env = $self->provision_s4member($path, $dc_vars, "s4member_dflt",
2117                                             "winbind use default domain = yes");
2118
2119         if (defined $env) {
2120                 if (not defined($self->check_or_start($env, "standard"))) {
2121                         return undef;
2122                 }
2123
2124                 $self->{vars}->{s4member_dflt_domain} = $env;
2125         }
2126
2127         return $env;
2128 }
2129
2130 sub setup_rpc_proxy($$$)
2131 {
2132         my ($self, $path, $dc_vars) = @_;
2133
2134         my $env = $self->provision_rpc_proxy($path, $dc_vars);
2135
2136         if (defined $env) {
2137                 if (not defined($self->check_or_start($env, "standard"))) {
2138                         return undef;
2139                 }
2140
2141                 $self->{vars}->{rpc_proxy} = $env;
2142         }
2143         return $env;
2144 }
2145
2146 sub setup_ad_dc_ntvfs($$)
2147 {
2148         my ($self, $path) = @_;
2149
2150         my $env = $self->provision_ad_dc_ntvfs($path);
2151         if (defined $env) {
2152                 if (not defined($self->check_or_start($env, "standard"))) {
2153                     warn("Failed to start ad_dc_ntvfs");
2154                         return undef;
2155                 }
2156
2157                 $self->{vars}->{ad_dc_ntvfs} = $env;
2158         }
2159         return $env;
2160 }
2161
2162 sub setup_chgdcpass($$)
2163 {
2164         my ($self, $path) = @_;
2165
2166         my $env = $self->provision_chgdcpass($path);
2167         if (defined $env) {
2168                 if (not defined($self->check_or_start($env, "standard"))) {
2169                         return undef;
2170                 }
2171
2172                 $self->{vars}->{chgdcpass} = $env;
2173         }
2174         return $env;
2175 }
2176
2177 sub setup_fl2000dc($$)
2178 {
2179         my ($self, $path) = @_;
2180
2181         my $env = $self->provision_fl2000dc($path);
2182         if (defined $env) {
2183                 if (not defined($self->check_or_start($env, "standard"))) {
2184                         return undef;
2185                 }
2186
2187                 $self->{vars}->{fl2000dc} = $env;
2188         }
2189
2190         return $env;
2191 }
2192
2193 sub setup_fl2003dc($$$)
2194 {
2195         my ($self, $path, $dc_vars) = @_;
2196
2197         my $env = $self->provision_fl2003dc($path);
2198
2199         if (defined $env) {
2200                 if (not defined($self->check_or_start($env, "standard"))) {
2201                         return undef;
2202                 }
2203
2204                 $env = $self->setup_trust($env, $dc_vars, "external", "--no-aes-keys");
2205
2206                 $self->{vars}->{fl2003dc} = $env;
2207         }
2208         return $env;
2209 }
2210
2211 sub setup_fl2008r2dc($$$)
2212 {
2213         my ($self, $path, $dc_vars) = @_;
2214
2215         my $env = $self->provision_fl2008r2dc($path);
2216
2217         if (defined $env) {
2218                 if (not defined($self->check_or_start($env, "standard"))) {
2219                         return undef;
2220                 }
2221
2222                 my $upn_array = ["$env->{REALM}.upn"];
2223                 my $spn_array = ["$env->{REALM}.spn"];
2224
2225                 $self->setup_namespaces($env, $upn_array, $spn_array);
2226
2227                 $env = $self->setup_trust($env, $dc_vars, "forest", "");
2228
2229                 $self->{vars}->{fl2008r2dc} = $env;
2230         }
2231
2232         return $env;
2233 }
2234
2235 sub setup_vampire_dc($$$$)
2236 {
2237         my ($self, $path, $dc_vars, $fl) = @_;
2238
2239         my $env = $self->provision_vampire_dc($path, $dc_vars, $fl);
2240
2241         if (defined $env) {
2242                 if (not defined($self->check_or_start($env, "single"))) {
2243                         return undef;
2244                 }
2245
2246                 $self->{vars}->{vampire_dc} = $env;
2247
2248                 # force replicated DC to update repsTo/repsFrom
2249                 # for vampired partitions
2250                 my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2251                 my $cmd = "";
2252                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
2253                 if (defined($env->{RESOLV_WRAPPER_CONF})) {
2254                         $cmd .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
2255                 } else {
2256                         $cmd .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
2257                 }
2258                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2259                 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2260                 $cmd .= " $samba_tool drs kcc -k no $env->{DC_SERVER}";
2261                 $cmd .= " $env->{CONFIGURATION}";
2262                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2263                 unless (system($cmd) == 0) {
2264                         warn("Failed to exec kcc on remote DC\n$cmd");
2265                         return undef;
2266                 }
2267
2268                 # as 'vampired' dc may add data in its local replica
2269                 # we need to synchronize data between DCs
2270                 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2271                 $cmd = "";
2272                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
2273                 if (defined($env->{RESOLV_WRAPPER_CONF})) {
2274                         $cmd .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
2275                 } else {
2276                         $cmd .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
2277                 }
2278                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2279                 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2280                 $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}";
2281                 $cmd .= " $dc_vars->{CONFIGURATION}";
2282                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2283                 # replicate Configuration NC
2284                 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\"";
2285                 unless(system($cmd_repl) == 0) {
2286                         warn("Failed to replicate\n$cmd_repl");
2287                         return undef;
2288                 }
2289                 # replicate Default NC
2290                 $cmd_repl = "$cmd \"$base_dn\"";
2291                 unless(system($cmd_repl) == 0) {
2292                         warn("Failed to replicate\n$cmd_repl");
2293                         return undef;
2294                 }
2295
2296                 # Pull in a full set of changes from the main DC
2297                 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2298                 $cmd = "";
2299                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
2300                 if (defined($env->{RESOLV_WRAPPER_CONF})) {
2301                         $cmd .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
2302                 } else {
2303                         $cmd .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
2304                 }
2305                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2306                 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2307                 $cmd .= " $samba_tool drs replicate $env->{SERVER} $env->{DC_SERVER}";
2308                 $cmd .= " $dc_vars->{CONFIGURATION}";
2309                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2310                 # replicate Configuration NC
2311                 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\"";
2312                 unless(system($cmd_repl) == 0) {
2313                         warn("Failed to replicate\n$cmd_repl");
2314                         return undef;
2315                 }
2316                 # replicate Default NC
2317                 $cmd_repl = "$cmd \"$base_dn\"";
2318                 unless(system($cmd_repl) == 0) {
2319                         warn("Failed to replicate\n$cmd_repl");
2320                         return undef;
2321                 }
2322         }
2323
2324         return $env;
2325 }
2326
2327 sub setup_promoted_dc($$$)
2328 {
2329         my ($self, $path, $dc_vars) = @_;
2330
2331         my $env = $self->provision_promoted_dc($path, $dc_vars);
2332
2333         if (defined $env) {
2334                 if (not defined($self->check_or_start($env, "single"))) {
2335                         return undef;
2336                 }
2337
2338                 $self->{vars}->{promoted_dc} = $env;
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 = "";
2344                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2345                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2346                 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2347                 $cmd .= " $samba_tool drs kcc $env->{DC_SERVER}";
2348                 $cmd .= " $env->{CONFIGURATION}";
2349                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2350                 unless (system($cmd) == 0) {
2351                         warn("Failed to exec kcc on remote DC\n$cmd");
2352                         return undef;
2353                 }
2354
2355                 my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2356                 my $cmd = "";
2357                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2358                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2359                 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2360                 $cmd .= " $samba_tool drs kcc $env->{SERVER}";
2361                 $cmd .= " $env->{CONFIGURATION}";
2362                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2363                 unless (system($cmd) == 0) {
2364                         warn("Failed to exec kcc on promoted DC\n$cmd");
2365                         return undef;
2366                 }
2367
2368                 # as 'vampired' dc may add data in its local replica
2369                 # we need to synchronize data between DCs
2370                 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2371                 $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2372                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2373                 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2374                 $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}";
2375                 $cmd .= " $dc_vars->{CONFIGURATION}";
2376                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2377                 # replicate Configuration NC
2378                 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\"";
2379                 unless(system($cmd_repl) == 0) {
2380                         warn("Failed to replicate\n$cmd_repl");
2381                         return undef;
2382                 }
2383                 # replicate Default NC
2384                 $cmd_repl = "$cmd \"$base_dn\"";
2385                 unless(system($cmd_repl) == 0) {
2386                         warn("Failed to replicate\n$cmd_repl");
2387                         return undef;
2388                 }
2389         }
2390
2391         return $env;
2392 }
2393
2394 sub setup_subdom_dc($$$)
2395 {
2396         my ($self, $path, $dc_vars) = @_;
2397
2398         my $env = $self->provision_subdom_dc($path, $dc_vars);
2399
2400         if (defined $env) {
2401                 if (not defined($self->check_or_start($env, "single"))) {
2402                         return undef;
2403                 }
2404
2405                 $self->{vars}->{subdom_dc} = $env;
2406
2407                 # force replicated DC to update repsTo/repsFrom
2408                 # for primary domain partitions
2409                 my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2410                 my $cmd = "";
2411                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2412                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2413                 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2414                 $cmd .= " $samba_tool drs kcc $env->{DC_SERVER}";
2415                 $cmd .= " $env->{CONFIGURATION}";
2416                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD} --realm=$dc_vars->{DC_REALM}";
2417                 unless (system($cmd) == 0) {
2418                         warn("Failed to exec kcc on remote DC\n$cmd");
2419                         return undef;
2420                 }
2421
2422                 # as 'subdomain' dc may add data in its local replica
2423                 # we need to synchronize data between DCs
2424                 my $base_dn = "DC=".join(",DC=", split(/\./, $env->{REALM}));
2425                 my $config_dn = "CN=Configuration,DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2426                 $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2427                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2428                 $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2429                 $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SUBDOM_DC_SERVER}";
2430                 $cmd .= " $dc_vars->{CONFIGURATION}";
2431                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD} --realm=$dc_vars->{DC_REALM}";
2432                 # replicate Configuration NC
2433                 my $cmd_repl = "$cmd \"$config_dn\"";
2434                 unless(system($cmd_repl) == 0) {
2435                         warn("Failed to replicate\n$cmd_repl");
2436                         return undef;
2437                 }
2438                 # replicate Default NC
2439                 $cmd_repl = "$cmd \"$base_dn\"";
2440                 unless(system($cmd_repl) == 0) {
2441                         warn("Failed to replicate\n$cmd_repl");
2442                         return undef;
2443                 }
2444         }
2445
2446         return $env;
2447 }
2448
2449 sub setup_rodc($$$)
2450 {
2451         my ($self, $path, $dc_vars) = @_;
2452
2453         my $env = $self->provision_rodc($path, $dc_vars);
2454
2455         unless ($env) {
2456                 return undef;
2457         }
2458
2459         if (not defined($self->check_or_start($env, "single"))) {
2460             return undef;
2461         }
2462
2463         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2464         my $cmd = "";
2465
2466         my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2467         $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2468         $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2469         $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
2470         $cmd .= " $samba_tool drs replicate $env->{SERVER} $env->{DC_SERVER}";
2471         $cmd .= " $dc_vars->{CONFIGURATION}";
2472         $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2473         # replicate Configuration NC
2474         my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\"";
2475         unless(system($cmd_repl) == 0) {
2476             warn("Failed to replicate\n$cmd_repl");
2477             return undef;
2478         }
2479         # replicate Default NC
2480         $cmd_repl = "$cmd \"$base_dn\"";
2481         unless(system($cmd_repl) == 0) {
2482             warn("Failed to replicate\n$cmd_repl");
2483             return undef;
2484         }
2485
2486         $self->{vars}->{rodc} = $env;
2487
2488         return $env;
2489 }
2490
2491 sub setup_ad_dc($$)
2492 {
2493         my ($self, $path, $no_nss) = @_;
2494
2495         # If we didn't build with ADS, pretend this env was never available
2496         if (not $self->{target3}->have_ads()) {
2497                return "UNKNOWN";
2498         }
2499
2500         my $env = $self->provision_ad_dc($path);
2501         unless ($env) {
2502                 return undef;
2503         }
2504
2505         if (defined($no_nss) and $no_nss) {
2506                 $env->{NSS_WRAPPER_MODULE_SO_PATH} = undef;
2507                 $env->{NSS_WRAPPER_MODULE_FN_PREFIX} = undef;
2508         }
2509
2510         if (not defined($self->check_or_start($env, "single"))) {
2511             return undef;
2512         }
2513
2514         my $upn_array = ["$env->{REALM}.upn"];
2515         my $spn_array = ["$env->{REALM}.spn"];
2516
2517         $self->setup_namespaces($env, $upn_array, $spn_array);
2518
2519         $self->{vars}->{ad_dc} = $env;
2520         return $env;
2521 }
2522
2523 sub setup_none($$)
2524 {
2525         my ($self, $path) = @_;
2526
2527         my $ret = {
2528                 KRB5_CONFIG => abs_path($path) . "/no_krb5.conf",
2529                 SAMBA_PID => -1,
2530         }
2531 }
2532
2533 1;