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