CVE-2016-2113: selftest: use "tls verify peer = no_check"
[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         tls verify peer = no_check
542         panic action = $RealBin/gdb_backtrace \%d
543         wins support = yes
544         server role = $ctx->{server_role}
545         server services = +echo +smb -s3fs
546         dcerpc endpoint servers = +winreg +srvsvc
547         notify:inotify = false
548         ldb:nosync = true
549         ldap server require strong auth = yes
550 #We don't want to pass our self-tests if the PAC code is wrong
551         gensec:require_pac = true
552         log file = $ctx->{logdir}/log.\%m
553         log level = $ctx->{server_loglevel}
554         lanman auth = Yes
555         rndc command = true
556         dns update command = $ctx->{samba_dnsupdate}
557         spn update command = $ENV{SRCDIR_ABS}/source4/scripting/bin/samba_spnupdate -s $ctx->{smb_conf}
558         dreplsrv:periodic_startup_interval = 0
559         dsdb:schema update allowed = yes
560
561         vfs objects = dfs_samba4 acl_xattr fake_acls xattr_tdb streams_depot
562
563         # remove this again, when our smb2 client library
564         # supports signin on compound related requests
565         server signing = on
566
567         idmap_ldb:use rfc2307=yes
568         winbind enum users = yes
569         winbind enum groups = yes
570 ";
571
572         print CONFFILE "
573
574         # Begin extra options
575         $ctx->{smb_conf_extra_options}
576         # End extra options
577 ";
578         close(CONFFILE);
579
580         #Default the KDC IP to the server's IP
581         if (not defined($ctx->{kdc_ipv4})) {
582                 $ctx->{kdc_ipv4} = $ctx->{ipv4};
583         }
584         if (not defined($ctx->{kdc_ipv6})) {
585                 $ctx->{kdc_ipv6} = $ctx->{ipv6};
586         }
587
588         Samba::mk_krb5_conf($ctx);
589
590         open(PWD, ">$ctx->{nsswrap_passwd}");
591         if ($ctx->{unix_uid} != 0) {
592                 print PWD "root:x:0:0:root gecos:$ctx->{prefix_abs}:/bin/false\n";
593         }
594         print PWD "$ctx->{unix_name}:x:$ctx->{unix_uid}:65531:$ctx->{unix_name} gecos:$ctx->{prefix_abs}:/bin/false\n";
595         print PWD "nobody:x:65534:65533:nobody gecos:$ctx->{prefix_abs}:/bin/false
596 pdbtest:x:65533:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false
597 pdbtest2:x:65532:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false
598 pdbtest3:x:65531:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false
599 pdbtest4:x:65530:65533:pdbtest gecos:$ctx->{prefix_abs}:/bin/false
600 ";
601         close(PWD);
602         my $uid_rfc2307test = 65533;
603
604         open(GRP, ">$ctx->{nsswrap_group}");
605         if ($ctx->{unix_gid} != 0) {
606                 print GRP "root:x:0:\n";
607         }
608         print GRP "$ctx->{unix_name}:x:$ctx->{unix_gid}:\n";
609         print GRP "wheel:x:10:
610 users:x:65531:
611 nobody:x:65533:
612 nogroup:x:65534:nobody
613 ";
614         close(GRP);
615         my $gid_rfc2307test = 65532;
616
617         my $hostname = lc($ctx->{hostname});
618         open(HOSTS, ">>$ctx->{nsswrap_hosts}");
619         if ($hostname eq "localdc") {
620                 print HOSTS "$ctx->{ipv4} ${hostname}.$ctx->{dnsname} $ctx->{dnsname} ${hostname}\n";
621                 print HOSTS "$ctx->{ipv6} ${hostname}.$ctx->{dnsname} $ctx->{dnsname} ${hostname}\n";
622         } else {
623                 print HOSTS "$ctx->{ipv4} ${hostname}.$ctx->{dnsname} ${hostname}\n";
624                 print HOSTS "$ctx->{ipv6} ${hostname}.$ctx->{dnsname} ${hostname}\n";
625         }
626         close(HOSTS);
627
628         if (defined($ctx->{resolv_conf})) {
629                 open(RESOLV_CONF, ">$ctx->{resolv_conf}");
630                 print RESOLV_CONF "nameserver $ctx->{kdc_ipv4}\n";
631                 print RESOLV_CONF "nameserver $ctx->{kdc_ipv6}\n";
632                 close(RESOLV_CONF);
633         }
634
635         my $configuration = "--configfile=$ctx->{smb_conf}";
636
637 #Ensure the config file is valid before we start
638         my $testparm = Samba::bindir_path($self, "samba-tool") . " testparm";
639         if (system("$testparm $configuration -v --suppress-prompt >/dev/null 2>&1") != 0) {
640                 system("$testparm -v --suppress-prompt $configuration >&2");
641                 warn("Failed to create a valid smb.conf configuration $testparm!");
642                 return undef;
643         }
644         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) {
645                 warn("Failed to create a valid smb.conf configuration! $testparm $configuration -v --suppress-prompt --parameter-name=\"netbios name\" --section-name=global");
646                 return undef;
647         }
648
649         my $ret = {
650                 KRB5_CONFIG => $ctx->{krb5_conf},
651                 PIDDIR => $ctx->{piddir},
652                 SERVER => $ctx->{hostname},
653                 SERVER_IP => $ctx->{ipv4},
654                 SERVER_IPV6 => $ctx->{ipv6},
655                 NETBIOSNAME => $ctx->{netbiosname},
656                 DOMAIN => $ctx->{domain},
657                 USERNAME => $ctx->{username},
658                 REALM => $ctx->{realm},
659                 PASSWORD => $ctx->{password},
660                 LDAPDIR => $ctx->{ldapdir},
661                 LDAP_INSTANCE => $ctx->{ldap_instance},
662                 SELFTEST_WINBINDD_SOCKET_DIR => $ctx->{winbindd_socket_dir},
663                 NCALRPCDIR => $ctx->{ncalrpcdir},
664                 LOCKDIR => $ctx->{lockdir},
665                 STATEDIR => $ctx->{statedir},
666                 CACHEDIR => $ctx->{cachedir},
667                 PRIVATEDIR => $ctx->{privatedir},
668                 SERVERCONFFILE => $ctx->{smb_conf},
669                 CONFIGURATION => $configuration,
670                 SOCKET_WRAPPER_DEFAULT_IFACE => $ctx->{swiface},
671                 NSS_WRAPPER_PASSWD => $ctx->{nsswrap_passwd},
672                 NSS_WRAPPER_GROUP => $ctx->{nsswrap_group},
673                 NSS_WRAPPER_HOSTS => $ctx->{nsswrap_hosts},
674                 SAMBA_TEST_FIFO => "$ctx->{prefix}/samba_test.fifo",
675                 SAMBA_TEST_LOG => "$ctx->{prefix}/samba_test.log",
676                 SAMBA_TEST_LOG_POS => 0,
677                 NSS_WRAPPER_MODULE_SO_PATH => Samba::nss_wrapper_winbind_so_path($self),
678                 NSS_WRAPPER_MODULE_FN_PREFIX => "winbind",
679                 LOCAL_PATH => $ctx->{share},
680                 UID_RFC2307TEST => $uid_rfc2307test,
681                 GID_RFC2307TEST => $gid_rfc2307test,
682                 SERVER_ROLE => $ctx->{server_role}
683         };
684
685         if (defined($ctx->{resolv_conf})) {
686                 $ret->{RESOLV_WRAPPER_CONF} = $ctx->{resolv_conf};
687         } else {
688                 $ret->{RESOLV_WRAPPER_HOSTS} = $ctx->{dns_host_file};
689         }
690
691         return $ret;
692 }
693
694 #
695 # Step2 runs the provision script
696 #
697 sub provision_raw_step2($$$)
698 {
699         my ($self, $ctx, $ret) = @_;
700
701         my $provision_cmd = join(" ", @{$ctx->{provision_options}});
702         unless (system($provision_cmd) == 0) {
703                 warn("Unable to provision: \n$provision_cmd\n");
704                 return undef;
705         }
706
707         my $testallowed_account = "testallowed";
708         my $samba_tool_cmd = "";
709         $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
710         $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool")
711             . " user add --configfile=$ctx->{smb_conf} $testallowed_account $ctx->{password}";
712         unless (system($samba_tool_cmd) == 0) {
713                 warn("Unable to add testallowed user: \n$samba_tool_cmd\n");
714                 return undef;
715         }
716
717         my $ldbmodify = "";
718         $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
719         $ldbmodify .= Samba::bindir_path($self, "ldbmodify");
720         my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm}));
721
722         if ($ctx->{server_role} ne "domain controller") {
723                 $base_dn = "DC=$ctx->{netbiosname}";
724         }
725
726         my $user_dn = "cn=$testallowed_account,cn=users,$base_dn";
727         $testallowed_account = "testallowed account";
728         open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb");
729         print LDIF "dn: $user_dn
730 changetype: modify
731 replace: samAccountName
732 samAccountName: $testallowed_account
733 -
734 ";
735         close(LDIF);
736
737         open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb");
738         print LDIF "dn: $user_dn
739 changetype: modify
740 replace: userPrincipalName
741 userPrincipalName: testallowed upn\@$ctx->{realm}
742 replace: servicePrincipalName
743 servicePrincipalName: host/testallowed
744 -           
745 ";
746         close(LDIF);
747
748         $samba_tool_cmd = "";
749         $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
750         $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool")
751             . " user add --configfile=$ctx->{smb_conf} testdenied $ctx->{password}";
752         unless (system($samba_tool_cmd) == 0) {
753                 warn("Unable to add testdenied user: \n$samba_tool_cmd\n");
754                 return undef;
755         }
756
757         my $user_dn = "cn=testdenied,cn=users,$base_dn";
758         open(LDIF, "|$ldbmodify -H $ctx->{privatedir}/sam.ldb");
759         print LDIF "dn: $user_dn
760 changetype: modify
761 replace: userPrincipalName
762 userPrincipalName: testdenied_upn\@$ctx->{realm}.upn
763 -           
764 ";
765         close(LDIF);
766
767         $samba_tool_cmd = "";
768         $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
769         $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool")
770             . " group addmembers --configfile=$ctx->{smb_conf} 'Allowed RODC Password Replication Group' '$testallowed_account'";
771         unless (system($samba_tool_cmd) == 0) {
772                 warn("Unable to add '$testallowed_account' user to 'Allowed RODC Password Replication Group': \n$samba_tool_cmd\n");
773                 return undef;
774         }
775
776         return $ret;
777 }
778
779 sub provision($$$$$$$$$$)
780 {
781         my ($self, $prefix, $server_role, $hostname,
782             $domain, $realm, $functional_level,
783             $password, $kdc_ipv4, $kdc_ipv6, $extra_smbconf_options, $extra_smbconf_shares,
784             $extra_provision_options) = @_;
785
786         my $ctx = $self->provision_raw_prepare($prefix, $server_role,
787                                                $hostname,
788                                                $domain, $realm, $functional_level,
789                                                $password, $kdc_ipv4, $kdc_ipv6);
790
791         if (defined($extra_provision_options)) {
792                 push (@{$ctx->{provision_options}}, @{$extra_provision_options});
793         } else {
794                 push (@{$ctx->{provision_options}}, "--use-ntvfs");
795         }
796
797         $ctx->{share} = "$ctx->{prefix_abs}/share";
798         push(@{$ctx->{directories}}, "$ctx->{share}");
799         push(@{$ctx->{directories}}, "$ctx->{share}/test1");
800         push(@{$ctx->{directories}}, "$ctx->{share}/test2");
801
802         # precreate directories for printer drivers
803         push(@{$ctx->{directories}}, "$ctx->{share}/W32X86");
804         push(@{$ctx->{directories}}, "$ctx->{share}/x64");
805         push(@{$ctx->{directories}}, "$ctx->{share}/WIN40");
806
807         my $msdfs = "no";
808         $msdfs = "yes" if ($server_role eq "domain controller");
809         $ctx->{smb_conf_extra_options} = "
810
811         max xmit = 32K
812         server max protocol = SMB2
813         host msdfs = $msdfs
814         lanman auth = yes
815         allow nt4 crypto = yes
816
817         # fruit:copyfile is a global option
818         fruit:copyfile = yes
819
820         $extra_smbconf_options
821
822 [tmp]
823         path = $ctx->{share}
824         read only = no
825         posix:sharedelay = 100000
826         posix:oplocktimeout = 3
827         posix:writetimeupdatedelay = 500000
828
829 [xcopy_share]
830         path = $ctx->{share}
831         read only = no
832         posix:sharedelay = 100000
833         posix:oplocktimeout = 3
834         posix:writetimeupdatedelay = 500000
835         create mask = 777
836         force create mode = 777
837
838 [posix_share]
839         path = $ctx->{share}
840         read only = no
841         create mask = 0777
842         force create mode = 0
843         directory mask = 0777
844         force directory mode = 0
845
846 [test1]
847         path = $ctx->{share}/test1
848         read only = no
849         posix:sharedelay = 100000
850         posix:oplocktimeout = 3
851         posix:writetimeupdatedelay = 500000
852
853 [test2]
854         path = $ctx->{share}/test2
855         read only = no
856         posix:sharedelay = 100000
857         posix:oplocktimeout = 3
858         posix:writetimeupdatedelay = 500000
859
860 [cifs]
861         path = $ctx->{share}/_ignore_cifs_
862         read only = no
863         ntvfs handler = cifs
864         cifs:server = $ctx->{netbiosname}
865         cifs:share = tmp
866         cifs:use-s4u2proxy = yes
867         # There is no username specified here, instead the client is expected
868         # to log in with kerberos, and the serverwill use delegated credentials.
869         # Or the server tries s4u2self/s4u2proxy to impersonate the client
870
871 [simple]
872         path = $ctx->{share}
873         read only = no
874         ntvfs handler = simple
875
876 [sysvol]
877         path = $ctx->{statedir}/sysvol
878         read only = no
879
880 [netlogon]
881         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
882         read only = no
883
884 [cifsposix]
885         copy = simple
886         ntvfs handler = cifsposix
887
888 [vfs_fruit]
889         path = $ctx->{share}
890         vfs objects = catia fruit streams_xattr acl_xattr
891         ea support = yes
892         fruit:ressource = file
893         fruit:metadata = netatalk
894         fruit:locking = netatalk
895         fruit:encoding = native
896
897 $extra_smbconf_shares
898 ";
899
900         if (defined($self->{ldap})) {
901                 $ctx->{ldapdir} = "$ctx->{privatedir}/ldap";
902                 push(@{$ctx->{directories}}, "$ctx->{ldapdir}");
903
904                 my $ldap_uri= "$ctx->{ldapdir}/ldapi";
905                 $ldap_uri =~ s|/|%2F|g;
906                 $ldap_uri = "ldapi://$ldap_uri";
907                 $ctx->{ldap_uri} = $ldap_uri;
908
909                 $ctx->{ldap_instance} = lc($ctx->{netbiosname});
910         }
911
912         my $ret = $self->provision_raw_step1($ctx);
913         unless (defined $ret) {
914                 return undef;
915         }
916
917         if (defined($self->{ldap})) {
918                 $ret->{LDAP_URI} = $ctx->{ldap_uri};
919                 push (@{$ctx->{provision_options}}, "--ldap-backend-type=" . $self->{ldap});
920                 push (@{$ctx->{provision_options}}, "--ldap-backend-nosync");
921                 if ($self->{ldap} eq "openldap") {
922                         push (@{$ctx->{provision_options}}, "--slapd-path=" . $ENV{OPENLDAP_SLAPD});
923                         ($ret->{SLAPD_CONF_D}, $ret->{OPENLDAP_PIDFILE}) = $self->mk_openldap($ctx) or die("Unable to create openldap directories");
924
925                 } elsif ($self->{ldap} eq "fedora-ds") {
926                         push (@{$ctx->{provision_options}}, "--slapd-path=" . "$ENV{FEDORA_DS_ROOT}/sbin/ns-slapd");
927                         push (@{$ctx->{provision_options}}, "--setup-ds-path=" . "$ENV{FEDORA_DS_ROOT}/sbin/setup-ds.pl");
928                         ($ret->{FEDORA_DS_DIR}, $ret->{FEDORA_DS_PIDFILE}) = $self->mk_fedora_ds($ctx) or die("Unable to create fedora ds directories");
929                 }
930
931         }
932
933         return $self->provision_raw_step2($ctx, $ret);
934 }
935
936 sub provision_s4member($$$)
937 {
938         my ($self, $prefix, $dcvars) = @_;
939         print "PROVISIONING MEMBER...";
940         my $extra_smb_conf = "
941         passdb backend = samba_dsdb
942 winbindd:use external pipes = true
943
944 rpc_server:default = external
945 rpc_server:svcctl = embedded
946 rpc_server:srvsvc = embedded
947 rpc_server:eventlog = embedded
948 rpc_server:ntsvcs = embedded
949 rpc_server:winreg = embedded
950 rpc_server:spoolss = embedded
951 rpc_daemon:spoolssd = embedded
952 rpc_server:tcpip = no
953 ";
954         my $ret = $self->provision($prefix,
955                                    "member server",
956                                    "s4member",
957                                    "SAMBADOMAIN",
958                                    "samba.example.com",
959                                    "2008",
960                                    "locMEMpass3",
961                                    $dcvars->{SERVER_IP},
962                                    $dcvars->{SERVER_IPV6},
963                                    $extra_smb_conf, "", undef);
964         unless ($ret) {
965                 return undef;
966         }
967
968         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
969         my $cmd = "";
970         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
971         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
972                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
973         } else {
974                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
975         }
976         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
977         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} member";
978         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
979         $cmd .= " --machinepass=machine$ret->{PASSWORD}";
980
981         unless (system($cmd) == 0) {
982                 warn("Join failed\n$cmd");
983                 return undef;
984         }
985
986         $ret->{MEMBER_SERVER} = $ret->{SERVER};
987         $ret->{MEMBER_SERVER_IP} = $ret->{SERVER_IP};
988         $ret->{MEMBER_SERVER_IPV6} = $ret->{SERVER_IPV6};
989         $ret->{MEMBER_NETBIOSNAME} = $ret->{NETBIOSNAME};
990         $ret->{MEMBER_USERNAME} = $ret->{USERNAME};
991         $ret->{MEMBER_PASSWORD} = $ret->{PASSWORD};
992
993         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
994         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
995         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
996         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
997         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
998         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
999
1000         return $ret;
1001 }
1002
1003 sub provision_rpc_proxy($$$)
1004 {
1005         my ($self, $prefix, $dcvars) = @_;
1006         print "PROVISIONING RPC PROXY...";
1007
1008         my $extra_smbconf_options = "
1009         passdb backend = samba_dsdb
1010
1011         # rpc_proxy
1012         dcerpc_remote:binding = ncacn_ip_tcp:$dcvars->{SERVER}
1013         dcerpc endpoint servers = epmapper, remote
1014         dcerpc_remote:interfaces = rpcecho
1015
1016 [cifs_to_dc]
1017         path = /tmp/_ignore_cifs_to_dc_/_none_
1018         read only = no
1019         ntvfs handler = cifs
1020         cifs:server = $dcvars->{SERVER}
1021         cifs:share = cifs
1022         cifs:use-s4u2proxy = yes
1023         # There is no username specified here, instead the client is expected
1024         # to log in with kerberos, and the serverwill use delegated credentials.
1025         # Or the server tries s4u2self/s4u2proxy to impersonate the client
1026
1027 ";
1028
1029         my $ret = $self->provision($prefix,
1030                                    "member server",
1031                                    "localrpcproxy",
1032                                    "SAMBADOMAIN",
1033                                    "samba.example.com",
1034                                    "2008",
1035                                    "locRPCproxypass4",
1036                                    $dcvars->{SERVER_IP},
1037                                    $dcvars->{SERVER_IPV6},
1038                                    $extra_smbconf_options, "", undef);
1039
1040         unless ($ret) {
1041                 return undef;
1042         }
1043
1044         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1045
1046         # The joind runs in the context of the rpc_proxy/member for now
1047         my $cmd = "";
1048         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1049         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1050                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1051         } else {
1052                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1053         }
1054         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1055         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} member";
1056         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1057         $cmd .= " --machinepass=machine$ret->{PASSWORD}";
1058
1059         unless (system($cmd) == 0) {
1060                 warn("Join failed\n$cmd");
1061                 return undef;
1062         }
1063
1064         # Setting up delegation runs in the context of the DC for now
1065         $cmd = "";
1066         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$dcvars->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1067         $cmd .= "KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" ";
1068         $cmd .= "$samba_tool delegation for-any-protocol '$ret->{NETBIOSNAME}\$' on";
1069         $cmd .= " $dcvars->{CONFIGURATION}";
1070         print $cmd;
1071
1072         unless (system($cmd) == 0) {
1073                 warn("Delegation failed\n$cmd");
1074                 return undef;
1075         }
1076
1077         # Setting up delegation runs in the context of the DC for now
1078         $cmd = "";
1079         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$dcvars->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1080         $cmd .= "KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" ";
1081         $cmd .= "$samba_tool delegation add-service '$ret->{NETBIOSNAME}\$' cifs/$dcvars->{SERVER}";
1082         $cmd .= " $dcvars->{CONFIGURATION}";
1083
1084         unless (system($cmd) == 0) {
1085                 warn("Delegation failed\n$cmd");
1086                 return undef;
1087         }
1088
1089         $ret->{RPC_PROXY_SERVER} = $ret->{SERVER};
1090         $ret->{RPC_PROXY_SERVER_IP} = $ret->{SERVER_IP};
1091         $ret->{RPC_PROXY_SERVER_IPV6} = $ret->{SERVER_IPV6};
1092         $ret->{RPC_PROXY_NETBIOSNAME} = $ret->{NETBIOSNAME};
1093         $ret->{RPC_PROXY_USERNAME} = $ret->{USERNAME};
1094         $ret->{RPC_PROXY_PASSWORD} = $ret->{PASSWORD};
1095
1096         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1097         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1098         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1099         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1100         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1101         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1102
1103         return $ret;
1104 }
1105
1106 sub provision_promoted_dc($$$)
1107 {
1108         my ($self, $prefix, $dcvars) = @_;
1109         print "PROVISIONING PROMOTED DC...";
1110
1111         # We do this so that we don't run the provision.  That's the job of 'samba-tool domain dcpromo'.
1112         my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
1113                                                "promotedvdc",
1114                                                "SAMBADOMAIN",
1115                                                "samba.example.com",
1116                                                "2008",
1117                                                $dcvars->{PASSWORD},
1118                                                $dcvars->{SERVER_IP},
1119                                                $dcvars->{SERVER_IPV6});
1120
1121         push (@{$ctx->{provision_options}}, "--use-ntvfs");
1122
1123         $ctx->{smb_conf_extra_options} = "
1124         max xmit = 32K
1125         server max protocol = SMB2
1126
1127 [sysvol]
1128         path = $ctx->{statedir}/sysvol
1129         read only = yes
1130
1131 [netlogon]
1132         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
1133         read only = no
1134
1135 ";
1136
1137         my $ret = $self->provision_raw_step1($ctx);
1138         unless ($ret) {
1139                 return undef;
1140         }
1141
1142         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1143         my $cmd = "";
1144         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1145         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1146                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1147         } else {
1148                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1149         }
1150         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1151         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} MEMBER --realm=$dcvars->{REALM}";
1152         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1153         $cmd .= " --machinepass=machine$ret->{PASSWORD}";
1154
1155         unless (system($cmd) == 0) {
1156                 warn("Join failed\n$cmd");
1157                 return undef;
1158         }
1159
1160         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1161         my $cmd = "";
1162         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1163         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1164         $cmd .= "$samba_tool domain dcpromo $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}";
1165         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1166         $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs --dns-backend=BIND9_DLZ";
1167
1168         unless (system($cmd) == 0) {
1169                 warn("Join failed\n$cmd");
1170                 return undef;
1171         }
1172
1173         $ret->{PROMOTED_DC_SERVER} = $ret->{SERVER};
1174         $ret->{PROMOTED_DC_SERVER_IP} = $ret->{SERVER_IP};
1175         $ret->{PROMOTED_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1176         $ret->{PROMOTED_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1177
1178         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1179         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1180         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1181         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1182         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1183         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1184
1185         return $ret;
1186 }
1187
1188 sub provision_vampire_dc($$$)
1189 {
1190         my ($self, $prefix, $dcvars) = @_;
1191         print "PROVISIONING VAMPIRE DC...";
1192
1193         # We do this so that we don't run the provision.  That's the job of 'net vampire'.
1194         my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
1195                                                "localvampiredc",
1196                                                "SAMBADOMAIN",
1197                                                "samba.example.com",
1198                                                "2008",
1199                                                $dcvars->{PASSWORD},
1200                                                $dcvars->{SERVER_IP},
1201                                                $dcvars->{SERVER_IPV6});
1202
1203         push (@{$ctx->{provision_options}}, "--use-ntvfs");
1204
1205         $ctx->{smb_conf_extra_options} = "
1206         max xmit = 32K
1207         server max protocol = SMB2
1208
1209 [sysvol]
1210         path = $ctx->{statedir}/sysvol
1211         read only = yes
1212
1213 [netlogon]
1214         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
1215         read only = no
1216
1217 ";
1218
1219         my $ret = $self->provision_raw_step1($ctx);
1220         unless ($ret) {
1221                 return undef;
1222         }
1223
1224         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1225         my $cmd = "";
1226         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1227         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1228                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1229         } else {
1230                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1231         }
1232         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1233         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}";
1234         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD} --domain-critical-only";
1235         $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs";
1236
1237         unless (system($cmd) == 0) {
1238                 warn("Join failed\n$cmd");
1239                 return undef;
1240         }
1241
1242         $ret->{VAMPIRE_DC_SERVER} = $ret->{SERVER};
1243         $ret->{VAMPIRE_DC_SERVER_IP} = $ret->{SERVER_IP};
1244         $ret->{VAMPIRE_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1245         $ret->{VAMPIRE_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1246
1247         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1248         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1249         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1250         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1251         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1252         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1253         $ret->{DC_REALM} = $dcvars->{DC_REALM};
1254
1255         return $ret;
1256 }
1257
1258 sub provision_subdom_dc($$$)
1259 {
1260         my ($self, $prefix, $dcvars) = @_;
1261         print "PROVISIONING SUBDOMAIN DC...";
1262
1263         # We do this so that we don't run the provision.  That's the job of 'net vampire'.
1264         my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
1265                                                "localsubdc",
1266                                                "SAMBASUBDOM",
1267                                                "sub.samba.example.com",
1268                                                "2008",
1269                                                $dcvars->{PASSWORD},
1270                                                undef);
1271
1272         push (@{$ctx->{provision_options}}, "--use-ntvfs");
1273
1274         $ctx->{smb_conf_extra_options} = "
1275         max xmit = 32K
1276         server max protocol = SMB2
1277
1278 [sysvol]
1279         path = $ctx->{statedir}/sysvol
1280         read only = yes
1281
1282 [netlogon]
1283         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
1284         read only = no
1285
1286 ";
1287
1288         my $ret = $self->provision_raw_step1($ctx);
1289         unless ($ret) {
1290                 return undef;
1291         }
1292
1293         Samba::mk_krb5_conf($ctx);
1294
1295         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1296         my $cmd = "";
1297         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1298         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1299                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1300         } else {
1301                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1302         }
1303         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1304         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $ctx->{dnsname} subdomain ";
1305         $cmd .= "--parent-domain=$dcvars->{REALM} -U$dcvars->{DC_USERNAME}\@$dcvars->{REALM}\%$dcvars->{DC_PASSWORD}";
1306         $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs";
1307         $cmd .= " --adminpass=$ret->{PASSWORD}";
1308
1309         unless (system($cmd) == 0) {
1310                 warn("Join failed\n$cmd");
1311                 return undef;
1312         }
1313
1314         $ret->{SUBDOM_DC_SERVER} = $ret->{SERVER};
1315         $ret->{SUBDOM_DC_SERVER_IP} = $ret->{SERVER_IP};
1316         $ret->{SUBDOM_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1317         $ret->{SUBDOM_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1318
1319         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1320         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1321         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1322         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1323         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1324         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1325
1326         return $ret;
1327 }
1328
1329 sub provision_ad_dc_ntvfs($$)
1330 {
1331         my ($self, $prefix) = @_;
1332
1333         # We keep the old 'winbind' name here in server services to
1334         # ensure upgrades which used that name still work with the now
1335         # alias.
1336
1337         print "PROVISIONING AD DC (NTVFS)...";
1338         my $extra_conf_options = "netbios aliases = localDC1-a
1339         server services = +winbind -winbindd
1340         ldap server require strong auth = allow_sasl_over_tls
1341         ";
1342         my $ret = $self->provision($prefix,
1343                                    "domain controller",
1344                                    "localdc",
1345                                    "SAMBADOMAIN",
1346                                    "samba.example.com",
1347                                    "2008",
1348                                    "locDCpass1",
1349                                    undef,
1350                                    undef,
1351                                    $extra_conf_options,
1352                                    "",
1353                                    undef);
1354
1355         return undef unless(defined $ret);
1356         unless($self->add_wins_config("$prefix/private")) {
1357                 warn("Unable to add wins configuration");
1358                 return undef;
1359         }
1360         $ret->{NETBIOSALIAS} = "localdc1-a";
1361         $ret->{DC_SERVER} = $ret->{SERVER};
1362         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1363         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1364         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1365         $ret->{DC_USERNAME} = $ret->{USERNAME};
1366         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1367         $ret->{DC_REALM} = $ret->{REALM};
1368
1369         return $ret;
1370 }
1371
1372 sub provision_fl2000dc($$)
1373 {
1374         my ($self, $prefix) = @_;
1375
1376         print "PROVISIONING DC WITH FOREST LEVEL 2000...";
1377         my $ret = $self->provision($prefix,
1378                                    "domain controller",
1379                                    "dc5",
1380                                    "SAMBA2000",
1381                                    "samba2000.example.com",
1382                                    "2000",
1383                                    "locDCpass5",
1384                                    undef,
1385                                    undef,
1386                                    "",
1387                                    "",
1388                                    undef);
1389
1390         unless($self->add_wins_config("$prefix/private")) {
1391                 warn("Unable to add wins configuration");
1392                 return undef;
1393         }
1394
1395         return $ret;
1396 }
1397
1398 sub provision_fl2003dc($$$)
1399 {
1400         my ($self, $prefix, $dcvars) = @_;
1401
1402         print "PROVISIONING DC WITH FOREST LEVEL 2003...";
1403         my $extra_conf_options = "allow dns updates = nonsecure and secure";
1404         my $ret = $self->provision($prefix,
1405                                    "domain controller",
1406                                    "dc6",
1407                                    "SAMBA2003",
1408                                    "samba2003.example.com",
1409                                    "2003",
1410                                    "locDCpass6",
1411                                    undef,
1412                                    undef,
1413                                    $extra_conf_options,
1414                                    "",
1415                                    undef);
1416
1417         unless (defined $ret) {
1418                 return undef;
1419         }
1420
1421         $ret->{DC_SERVER} = $ret->{SERVER};
1422         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1423         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1424         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1425         $ret->{DC_USERNAME} = $ret->{USERNAME};
1426         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1427
1428         my @samba_tool_options;
1429         push (@samba_tool_options, Samba::bindir_path($self, "samba-tool"));
1430         push (@samba_tool_options, "domain");
1431         push (@samba_tool_options, "passwordsettings");
1432         push (@samba_tool_options, "set");
1433         push (@samba_tool_options, "--configfile=$ret->{SERVERCONFFILE}");
1434         push (@samba_tool_options, "--min-pwd-age=0");
1435         push (@samba_tool_options, "--history-length=1");
1436
1437         my $samba_tool_cmd = join(" ", @samba_tool_options);
1438
1439         unless (system($samba_tool_cmd) == 0) {
1440                 warn("Unable to set min password age to 0: \n$samba_tool_cmd\n");
1441                 return undef;
1442         }
1443
1444         return $ret;
1445
1446         unless($self->add_wins_config("$prefix/private")) {
1447                 warn("Unable to add wins configuration");
1448                 return undef;
1449         }
1450
1451         return $ret;
1452 }
1453
1454 sub provision_fl2008r2dc($$$)
1455 {
1456         my ($self, $prefix, $dcvars) = @_;
1457
1458         print "PROVISIONING DC WITH FOREST LEVEL 2008r2...";
1459         my $extra_conf_options = "ldap server require strong auth = no";
1460         my $ret = $self->provision($prefix,
1461                                    "domain controller",
1462                                    "dc7",
1463                                    "SAMBA2008R2",
1464                                    "samba2008R2.example.com",
1465                                    "2008_R2",
1466                                    "locDCpass7",
1467                                    undef,
1468                                    undef,
1469                                    $extra_conf_options,
1470                                    "",
1471                                    undef);
1472
1473         unless ($self->add_wins_config("$prefix/private")) {
1474                 warn("Unable to add wins configuration");
1475                 return undef;
1476         }
1477
1478         return $ret;
1479 }
1480
1481
1482 sub provision_rodc($$$)
1483 {
1484         my ($self, $prefix, $dcvars) = @_;
1485         print "PROVISIONING RODC...";
1486
1487         # We do this so that we don't run the provision.  That's the job of 'net join RODC'.
1488         my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
1489                                                "rodc",
1490                                                "SAMBADOMAIN",
1491                                                "samba.example.com",
1492                                                "2008",
1493                                                $dcvars->{PASSWORD},
1494                                                $dcvars->{SERVER_IP},
1495                                                $dcvars->{SERVER_IPV6});
1496         unless ($ctx) {
1497                 return undef;
1498         }
1499
1500         push (@{$ctx->{provision_options}}, "--use-ntvfs");
1501
1502         $ctx->{share} = "$ctx->{prefix_abs}/share";
1503         push(@{$ctx->{directories}}, "$ctx->{share}");
1504
1505         $ctx->{smb_conf_extra_options} = "
1506         max xmit = 32K
1507         server max protocol = SMB2
1508
1509 [sysvol]
1510         path = $ctx->{statedir}/sysvol
1511         read only = yes
1512
1513 [netlogon]
1514         path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
1515         read only = yes
1516
1517 [tmp]
1518         path = $ctx->{share}
1519         read only = no
1520         posix:sharedelay = 10000
1521         posix:oplocktimeout = 3
1522         posix:writetimeupdatedelay = 50000
1523
1524 ";
1525
1526         my $ret = $self->provision_raw_step1($ctx);
1527         unless ($ret) {
1528                 return undef;
1529         }
1530
1531         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
1532         my $cmd = "";
1533         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1534         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1535                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1536         } else {
1537                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1538         }
1539         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1540         $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} RODC";
1541         $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
1542         $cmd .= " --server=$dcvars->{DC_SERVER} --use-ntvfs";
1543
1544         unless (system($cmd) == 0) {
1545                 warn("RODC join failed\n$cmd");
1546                 return undef;
1547         }
1548
1549         # This ensures deterministic behaviour for tests that want to have the 'testallowed account'
1550         # user password verified on the RODC
1551         my $testallowed_account = "testallowed account";
1552         $cmd = "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1553         $cmd .= "$samba_tool rodc preload '$testallowed_account' $ret->{CONFIGURATION}";
1554         $cmd .= " --server=$dcvars->{DC_SERVER}";
1555
1556         unless (system($cmd) == 0) {
1557                 warn("RODC join failed\n$cmd");
1558                 return undef;
1559         }
1560
1561         # we overwrite the kdc after the RODC join
1562         # so that use the RODC as kdc and test
1563         # the proxy code
1564         $ctx->{kdc_ipv4} = $ret->{SERVER_IP};
1565         $ctx->{kdc_ipv6} = $ret->{SERVER_IPV6};
1566         Samba::mk_krb5_conf($ctx);
1567
1568         $ret->{RODC_DC_SERVER} = $ret->{SERVER};
1569         $ret->{RODC_DC_SERVER_IP} = $ret->{SERVER_IP};
1570         $ret->{RODC_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1571         $ret->{RODC_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1572
1573         $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
1574         $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
1575         $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
1576         $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
1577         $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
1578         $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
1579
1580         return $ret;
1581 }
1582
1583 sub provision_ad_dc($$)
1584 {
1585         my ($self, $prefix) = @_;
1586
1587         my $prefix_abs = abs_path($prefix);
1588
1589         my $bindir_abs = abs_path($self->{bindir});
1590         my $lockdir="$prefix_abs/lockdir";
1591         my $conffile="$prefix_abs/etc/smb.conf";
1592
1593         my $require_mutexes = "dbwrap_tdb_require_mutexes:* = yes";
1594         $require_mutexes = "" if ($ENV{SELFTEST_DONT_REQUIRE_TDB_MUTEX_SUPPORT} eq "1");
1595
1596         my $extra_smbconf_options = "
1597         server services = -smb +s3fs
1598         xattr_tdb:file = $prefix_abs/statedir/xattr.tdb
1599
1600         dbwrap_tdb_mutexes:* = yes
1601         ${require_mutexes}
1602
1603         kernel oplocks = no
1604         kernel change notify = no
1605
1606         logging = file
1607         printing = bsd
1608         printcap name = /dev/null
1609
1610         max protocol = SMB3
1611         read only = no
1612         server signing = auto
1613
1614         smbd:sharedelay = 100000
1615         smbd:writetimeupdatedelay = 500000
1616         create mask = 755
1617         dos filemode = yes
1618
1619         dcerpc endpoint servers = -winreg -srvsvc
1620
1621         printcap name = /dev/null
1622
1623         addprinter command = $ENV{SRCDIR_ABS}/source3/script/tests/printing/modprinter.pl -a -s $conffile --
1624         deleteprinter command = $ENV{SRCDIR_ABS}/source3/script/tests/printing/modprinter.pl -d -s $conffile --
1625
1626         printing = vlp
1627         print command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb print %p %s
1628         lpq command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpq %p
1629         lp rm command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lprm %p %j
1630         lp pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lppause %p %j
1631         lp resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpresume %p %j
1632         queue pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queuepause %p
1633         queue resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queueresume %p
1634         lpq cache time = 0
1635         print notify backchannel = yes
1636 ";
1637
1638         my $extra_smbconf_shares = "
1639
1640 [tmpenc]
1641         copy = tmp
1642         smb encrypt = required
1643
1644 [tmpcase]
1645         copy = tmp
1646         case sensitive = yes
1647
1648 [tmpguest]
1649         copy = tmp
1650         guest ok = yes
1651
1652 [hideunread]
1653         copy = tmp
1654         hide unreadable = yes
1655
1656 [durable]
1657         copy = tmp
1658         kernel share modes = no
1659         kernel oplocks = no
1660         posix locking = no
1661
1662 [print\$]
1663         copy = tmp
1664
1665 [print1]
1666         copy = tmp
1667         printable = yes
1668
1669 [print2]
1670         copy = print1
1671 [print3]
1672         copy = print1
1673 [lp]
1674         copy = print1
1675 ";
1676
1677         print "PROVISIONING AD DC...";
1678         my $ret = $self->provision($prefix,
1679                                    "domain controller",
1680                                    "addc",
1681                                    "ADDOMAIN",
1682                                    "addom.samba.example.com",
1683                                    "2008",
1684                                    "locDCpass1",
1685                                    undef,
1686                                    undef,
1687                                    $extra_smbconf_options,
1688                                    $extra_smbconf_shares,
1689                                    undef);
1690
1691         return undef unless(defined $ret);
1692         unless($self->add_wins_config("$prefix/private")) {
1693                 warn("Unable to add wins configuration");
1694                 return undef;
1695         }
1696
1697         $ret->{DC_SERVER} = $ret->{SERVER};
1698         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1699         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1700         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1701         $ret->{DC_USERNAME} = $ret->{USERNAME};
1702         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1703
1704         return $ret;
1705 }
1706
1707 sub provision_chgdcpass($$)
1708 {
1709         my ($self, $prefix) = @_;
1710
1711         print "PROVISIONING CHGDCPASS...";
1712         my $extra_provision_options = undef;
1713         push (@{$extra_provision_options}, "--dns-backend=BIND9_DLZ");
1714         my $ret = $self->provision($prefix,
1715                                    "domain controller",
1716                                    "chgdcpass",
1717                                    "CHDCDOMAIN",
1718                                    "chgdcpassword.samba.example.com",
1719                                    "2008",
1720                                    "chgDCpass1",
1721                                    undef,
1722                                    undef,
1723                                    "",
1724                                    "",
1725                                    $extra_provision_options);
1726
1727         return undef unless(defined $ret);
1728         unless($self->add_wins_config("$prefix/private")) {
1729                 warn("Unable to add wins configuration");
1730                 return undef;
1731         }
1732         
1733         # Remove secrets.tdb from this environment to test that we
1734         # still start up on systems without the new matching
1735         # secrets.tdb records.
1736         unless (unlink("$ret->{PRIVATEDIR}/secrets.tdb") || unlink("$ret->{PRIVATEDIR}/secrets.ntdb")) {
1737                 warn("Unable to remove $ret->{PRIVATEDIR}/secrets.tdb added during provision");
1738                 return undef;
1739         }
1740             
1741         $ret->{DC_SERVER} = $ret->{SERVER};
1742         $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
1743         $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
1744         $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
1745         $ret->{DC_USERNAME} = $ret->{USERNAME};
1746         $ret->{DC_PASSWORD} = $ret->{PASSWORD};
1747
1748         return $ret;
1749 }
1750
1751 sub teardown_env($$)
1752 {
1753         my ($self, $envvars) = @_;
1754         my $pid;
1755
1756         # This should cause samba to terminate gracefully
1757         close($envvars->{STDIN_PIPE});
1758
1759         $pid = $envvars->{SAMBA_PID};
1760         my $count = 0;
1761         my $childpid;
1762
1763         # This should give it time to write out the gcov data
1764         until ($count > 30) {
1765             if (Samba::cleanup_child($pid, "samba") == -1) {
1766                 last;
1767             }
1768             sleep(1);
1769             $count++;
1770         }
1771
1772         if ($count > 30 || kill(0, $pid)) {
1773             kill "TERM", $pid;
1774
1775             until ($count > 40) {
1776                 if (Samba::cleanup_child($pid, "samba") == -1) {
1777                     last;
1778                 }
1779                 sleep(1);
1780                 $count++;
1781             }
1782             # If it is still around, kill it
1783             warn "server process $pid took more than $count seconds to exit, killing\n";
1784             kill 9, $pid;
1785         }
1786
1787         $self->slapd_stop($envvars) if ($self->{ldap});
1788
1789         print $self->getlog_env($envvars);
1790
1791         return;
1792 }
1793
1794 sub getlog_env($$)
1795 {
1796         my ($self, $envvars) = @_;
1797         my $title = "SAMBA LOG of: $envvars->{NETBIOSNAME}\n";
1798         my $out = $title;
1799
1800         open(LOG, "<$envvars->{SAMBA_TEST_LOG}");
1801
1802         seek(LOG, $envvars->{SAMBA_TEST_LOG_POS}, SEEK_SET);
1803         while (<LOG>) {
1804                 $out .= $_;
1805         }
1806         $envvars->{SAMBA_TEST_LOG_POS} = tell(LOG);
1807         close(LOG);
1808
1809         return "" if $out eq $title;
1810
1811         return $out;
1812 }
1813
1814 sub check_env($$)
1815 {
1816         my ($self, $envvars) = @_;
1817         my $samba_pid = $envvars->{SAMBA_PID};
1818
1819         if (not defined($samba_pid)) {
1820             return 0;
1821         } elsif ($samba_pid > 0) {
1822             my $childpid = Samba::cleanup_child($samba_pid, "samba");
1823
1824             if ($childpid == 0) {
1825                 return 1;
1826             }
1827             return 0;
1828         } else {
1829             return 1;
1830         }
1831
1832 }
1833
1834 sub setup_env($$$)
1835 {
1836         my ($self, $envname, $path) = @_;
1837         my $target3 = $self->{target3};
1838
1839         $ENV{ENVNAME} = $envname;
1840
1841         if (defined($self->{vars}->{$envname})) {
1842                 return $self->{vars}->{$envname};
1843         }
1844
1845         if ($envname eq "ad_dc_ntvfs") {
1846                 return $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1847         } elsif ($envname eq "fl2000dc") {
1848                 return $self->setup_fl2000dc("$path/fl2000dc");
1849         } elsif ($envname eq "fl2003dc") {
1850                 if (not defined($self->{vars}->{ad_dc})) {
1851                         $self->setup_ad_dc("$path/ad_dc");
1852                 }
1853                 return $self->setup_fl2003dc("$path/fl2003dc", $self->{vars}->{ad_dc});
1854         } elsif ($envname eq "fl2008r2dc") {
1855                 if (not defined($self->{vars}->{ad_dc})) {
1856                         $self->setup_ad_dc("$path/ad_dc");
1857                 }
1858                 return $self->setup_fl2008r2dc("$path/fl2008r2dc", $self->{vars}->{ad_dc});
1859         } elsif ($envname eq "rpc_proxy") {
1860                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
1861                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1862                 }
1863                 return $self->setup_rpc_proxy("$path/rpc_proxy", $self->{vars}->{ad_dc_ntvfs});
1864         } elsif ($envname eq "vampire_dc") {
1865                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
1866                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1867                 }
1868                 return $self->setup_vampire_dc("$path/vampire_dc", $self->{vars}->{ad_dc_ntvfs});
1869         } elsif ($envname eq "promoted_dc") {
1870                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
1871                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1872                 }
1873                 return $self->setup_promoted_dc("$path/promoted_dc", $self->{vars}->{ad_dc_ntvfs});
1874         } elsif ($envname eq "subdom_dc") {
1875                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
1876                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1877                 }
1878                 return $self->setup_subdom_dc("$path/subdom_dc", $self->{vars}->{ad_dc_ntvfs});
1879         } elsif ($envname eq "s4member") {
1880                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
1881                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1882                 }
1883                 return $self->setup_s4member("$path/s4member", $self->{vars}->{ad_dc_ntvfs});
1884         } elsif ($envname eq "rodc") {
1885                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
1886                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1887                 }
1888                 return $self->setup_rodc("$path/rodc", $self->{vars}->{ad_dc_ntvfs});
1889         } elsif ($envname eq "chgdcpass") {
1890                 return $self->setup_chgdcpass("$path/chgdcpass", $self->{vars}->{chgdcpass});
1891         } elsif ($envname eq "ad_member") {
1892                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
1893                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1894                 }
1895                 return $target3->setup_admember("$path/ad_member", $self->{vars}->{ad_dc_ntvfs}, 29);
1896         } elsif ($envname eq "ad_dc") {
1897                 return $self->setup_ad_dc("$path/ad_dc");
1898         } elsif ($envname eq "ad_dc_no_nss") {
1899                 return $self->setup_ad_dc("$path/ad_dc_no_nss", "no_nss");
1900         } elsif ($envname eq "ad_member_rfc2307") {
1901                 if (not defined($self->{vars}->{ad_dc_ntvfs})) {
1902                         $self->setup_ad_dc_ntvfs("$path/ad_dc_ntvfs");
1903                 }
1904                 return $target3->setup_admember_rfc2307("$path/ad_member_rfc2307",
1905                                                         $self->{vars}->{ad_dc_ntvfs}, 34);
1906         } elsif ($envname eq "none") {
1907                 return $self->setup_none("$path/none");
1908         } else {
1909                 return "UNKNOWN";
1910         }
1911 }
1912
1913 sub setup_s4member($$$)
1914 {
1915         my ($self, $path, $dc_vars) = @_;
1916
1917         my $env = $self->provision_s4member($path, $dc_vars);
1918
1919         if (defined $env) {
1920                 if (not defined($self->check_or_start($env, "standard"))) {
1921                         return undef;
1922                 }
1923
1924                 $self->{vars}->{s4member} = $env;
1925         }
1926
1927         return $env;
1928 }
1929
1930 sub setup_rpc_proxy($$$)
1931 {
1932         my ($self, $path, $dc_vars) = @_;
1933
1934         my $env = $self->provision_rpc_proxy($path, $dc_vars);
1935
1936         if (defined $env) {
1937                 if (not defined($self->check_or_start($env, "standard"))) {
1938                         return undef;
1939                 }
1940
1941                 $self->{vars}->{rpc_proxy} = $env;
1942         }
1943         return $env;
1944 }
1945
1946 sub setup_ad_dc_ntvfs($$)
1947 {
1948         my ($self, $path) = @_;
1949
1950         my $env = $self->provision_ad_dc_ntvfs($path);
1951         if (defined $env) {
1952                 if (not defined($self->check_or_start($env, "standard"))) {
1953                     warn("Failed to start ad_dc_ntvfs");
1954                         return undef;
1955                 }
1956
1957                 $self->{vars}->{ad_dc_ntvfs} = $env;
1958         }
1959         return $env;
1960 }
1961
1962 sub setup_chgdcpass($$)
1963 {
1964         my ($self, $path) = @_;
1965
1966         my $env = $self->provision_chgdcpass($path);
1967         if (defined $env) {
1968                 if (not defined($self->check_or_start($env, "standard"))) {
1969                         return undef;
1970                 }
1971
1972                 $self->{vars}->{chgdcpass} = $env;
1973         }
1974         return $env;
1975 }
1976
1977 sub setup_fl2000dc($$)
1978 {
1979         my ($self, $path) = @_;
1980
1981         my $env = $self->provision_fl2000dc($path);
1982         if (defined $env) {
1983                 if (not defined($self->check_or_start($env, "standard"))) {
1984                         return undef;
1985                 }
1986
1987                 $self->{vars}->{fl2000dc} = $env;
1988         }
1989
1990         return $env;
1991 }
1992
1993 sub setup_fl2003dc($$$)
1994 {
1995         my ($self, $path, $dc_vars) = @_;
1996
1997         my $env = $self->provision_fl2003dc($path);
1998
1999         if (defined $env) {
2000                 if (not defined($self->check_or_start($env, "standard"))) {
2001                         return undef;
2002                 }
2003
2004                 $env = $self->setup_trust($env, $dc_vars, "external", "--no-aes-keys");
2005
2006                 $self->{vars}->{fl2003dc} = $env;
2007         }
2008         return $env;
2009 }
2010
2011 sub setup_fl2008r2dc($$$)
2012 {
2013         my ($self, $path, $dc_vars) = @_;
2014
2015         my $env = $self->provision_fl2008r2dc($path);
2016
2017         if (defined $env) {
2018                 if (not defined($self->check_or_start($env, "standard"))) {
2019                         return undef;
2020                 }
2021
2022                 my $upn_array = ["$env->{REALM}.upn"];
2023                 my $spn_array = ["$env->{REALM}.spn"];
2024
2025                 $self->setup_namespaces($env, $upn_array, $spn_array);
2026
2027                 $env = $self->setup_trust($env, $dc_vars, "forest", "");
2028
2029                 $self->{vars}->{fl2008r2dc} = $env;
2030         }
2031
2032         return $env;
2033 }
2034
2035 sub setup_vampire_dc($$$)
2036 {
2037         my ($self, $path, $dc_vars) = @_;
2038
2039         my $env = $self->provision_vampire_dc($path, $dc_vars);
2040
2041         if (defined $env) {
2042                 if (not defined($self->check_or_start($env, "single"))) {
2043                         return undef;
2044                 }
2045
2046                 $self->{vars}->{vampire_dc} = $env;
2047
2048                 # force replicated DC to update repsTo/repsFrom
2049                 # for vampired partitions
2050                 my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2051                 my $cmd = "";
2052                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
2053                 if (defined($env->{RESOLV_WRAPPER_CONF})) {
2054                         $cmd .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
2055                 } else {
2056                         $cmd .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
2057                 }
2058                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2059                 $cmd .= " $samba_tool drs kcc -k no $env->{DC_SERVER}";
2060                 $cmd .= " $env->{CONFIGURATION}";
2061                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2062                 unless (system($cmd) == 0) {
2063                         warn("Failed to exec kcc\n$cmd");
2064                         return undef;
2065                 }
2066
2067                 # as 'vampired' dc may add data in its local replica
2068                 # we need to synchronize data between DCs
2069                 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2070                 $cmd = "";
2071                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
2072                 if (defined($env->{RESOLV_WRAPPER_CONF})) {
2073                         $cmd .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
2074                 } else {
2075                         $cmd .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
2076                 }
2077                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2078                 $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}";
2079                 $cmd .= " $dc_vars->{CONFIGURATION}";
2080                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2081                 # replicate Configuration NC
2082                 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\"";
2083                 unless(system($cmd_repl) == 0) {
2084                         warn("Failed to replicate\n$cmd_repl");
2085                         return undef;
2086                 }
2087                 # replicate Default NC
2088                 $cmd_repl = "$cmd \"$base_dn\"";
2089                 unless(system($cmd_repl) == 0) {
2090                         warn("Failed to replicate\n$cmd_repl");
2091                         return undef;
2092                 }
2093         }
2094
2095         return $env;
2096 }
2097
2098 sub setup_promoted_dc($$$)
2099 {
2100         my ($self, $path, $dc_vars) = @_;
2101
2102         my $env = $self->provision_promoted_dc($path, $dc_vars);
2103
2104         if (defined $env) {
2105                 if (not defined($self->check_or_start($env, "single"))) {
2106                         return undef;
2107                 }
2108
2109                 $self->{vars}->{promoted_dc} = $env;
2110
2111                 # force source and replicated DC to update repsTo/repsFrom
2112                 # for vampired partitions
2113                 my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2114                 my $cmd = "";
2115                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2116                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2117                 $cmd .= " $samba_tool drs kcc $env->{DC_SERVER}";
2118                 $cmd .= " $env->{CONFIGURATION}";
2119                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2120                 unless (system($cmd) == 0) {
2121                         warn("Failed to exec kcc\n$cmd");
2122                         return undef;
2123                 }
2124
2125                 my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2126                 my $cmd = "";
2127                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2128                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2129                 $cmd .= " $samba_tool drs kcc $env->{SERVER}";
2130                 $cmd .= " $env->{CONFIGURATION}";
2131                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2132                 unless (system($cmd) == 0) {
2133                         warn("Failed to exec kcc\n$cmd");
2134                         return undef;
2135                 }
2136
2137                 # as 'vampired' dc may add data in its local replica
2138                 # we need to synchronize data between DCs
2139                 my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2140                 $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2141                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2142                 $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}";
2143                 $cmd .= " $dc_vars->{CONFIGURATION}";
2144                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2145                 # replicate Configuration NC
2146                 my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\"";
2147                 unless(system($cmd_repl) == 0) {
2148                         warn("Failed to replicate\n$cmd_repl");
2149                         return undef;
2150                 }
2151                 # replicate Default NC
2152                 $cmd_repl = "$cmd \"$base_dn\"";
2153                 unless(system($cmd_repl) == 0) {
2154                         warn("Failed to replicate\n$cmd_repl");
2155                         return undef;
2156                 }
2157         }
2158
2159         return $env;
2160 }
2161
2162 sub setup_subdom_dc($$$)
2163 {
2164         my ($self, $path, $dc_vars) = @_;
2165
2166         my $env = $self->provision_subdom_dc($path, $dc_vars);
2167
2168         if (defined $env) {
2169                 if (not defined($self->check_or_start($env, "single"))) {
2170                         return undef;
2171                 }
2172
2173                 $self->{vars}->{subdom_dc} = $env;
2174
2175                 # force replicated DC to update repsTo/repsFrom
2176                 # for primary domain partitions
2177                 my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2178                 my $cmd = "";
2179                 $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2180                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2181                 $cmd .= " $samba_tool drs kcc $env->{DC_SERVER}";
2182                 $cmd .= " $env->{CONFIGURATION}";
2183                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD} --realm=$dc_vars->{DC_REALM}";
2184                 unless (system($cmd) == 0) {
2185                         warn("Failed to exec kcc\n$cmd");
2186                         return undef;
2187                 }
2188
2189                 # as 'subdomain' dc may add data in its local replica
2190                 # we need to synchronize data between DCs
2191                 my $base_dn = "DC=".join(",DC=", split(/\./, $env->{REALM}));
2192                 my $config_dn = "CN=Configuration,DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2193                 $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2194                 $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2195                 $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SUBDOM_DC_SERVER}";
2196                 $cmd .= " $dc_vars->{CONFIGURATION}";
2197                 $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD} --realm=$dc_vars->{DC_REALM}";
2198                 # replicate Configuration NC
2199                 my $cmd_repl = "$cmd \"$config_dn\"";
2200                 unless(system($cmd_repl) == 0) {
2201                         warn("Failed to replicate\n$cmd_repl");
2202                         return undef;
2203                 }
2204                 # replicate Default NC
2205                 $cmd_repl = "$cmd \"$base_dn\"";
2206                 unless(system($cmd_repl) == 0) {
2207                         warn("Failed to replicate\n$cmd_repl");
2208                         return undef;
2209                 }
2210         }
2211
2212         return $env;
2213 }
2214
2215 sub setup_rodc($$$)
2216 {
2217         my ($self, $path, $dc_vars) = @_;
2218
2219         my $env = $self->provision_rodc($path, $dc_vars);
2220
2221         unless ($env) {
2222                 return undef;
2223         }
2224
2225         if (not defined($self->check_or_start($env, "single"))) {
2226             return undef;
2227         }
2228
2229         # force source and replicated DC to update repsTo/repsFrom
2230         # for vampired partitions
2231         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2232         my $cmd = "";
2233         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2234         $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2235         $cmd .= " $samba_tool drs kcc -k no $env->{DC_SERVER}";
2236         $cmd .= " $env->{CONFIGURATION}";
2237         $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2238         unless (system($cmd) == 0) {
2239             warn("Failed to exec kcc\n$cmd");
2240             return undef;
2241         }
2242
2243         my $samba_tool =  Samba::bindir_path($self, "samba-tool");
2244         my $cmd = "";
2245         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2246         $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2247         $cmd .= " $samba_tool drs kcc -k no $env->{SERVER}";
2248         $cmd .= " $env->{CONFIGURATION}";
2249         $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2250         unless (system($cmd) == 0) {
2251             warn("Failed to exec kcc\n$cmd");
2252             return undef;
2253         }
2254
2255         my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
2256         $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
2257         $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
2258         $cmd .= " $samba_tool drs replicate $env->{SERVER} $env->{DC_SERVER}";
2259         $cmd .= " $dc_vars->{CONFIGURATION}";
2260         $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
2261         # replicate Configuration NC
2262         my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\"";
2263         unless(system($cmd_repl) == 0) {
2264             warn("Failed to replicate\n$cmd_repl");
2265             return undef;
2266         }
2267         # replicate Default NC
2268         $cmd_repl = "$cmd \"$base_dn\"";
2269         unless(system($cmd_repl) == 0) {
2270             warn("Failed to replicate\n$cmd_repl");
2271             return undef;
2272         }
2273
2274         $self->{vars}->{rodc} = $env;
2275
2276         return $env;
2277 }
2278
2279 sub setup_ad_dc($$)
2280 {
2281         my ($self, $path, $no_nss) = @_;
2282
2283         # If we didn't build with ADS, pretend this env was never available
2284         if (not $self->{target3}->have_ads()) {
2285                return "UNKNOWN";
2286         }
2287
2288         my $env = $self->provision_ad_dc($path);
2289         unless ($env) {
2290                 return undef;
2291         }
2292
2293         if (defined($no_nss) and $no_nss) {
2294                 $env->{NSS_WRAPPER_MODULE_SO_PATH} = undef;
2295                 $env->{NSS_WRAPPER_MODULE_FN_PREFIX} = undef;
2296         }
2297
2298         if (not defined($self->check_or_start($env, "single"))) {
2299             return undef;
2300         }
2301
2302         my $upn_array = ["$env->{REALM}.upn"];
2303         my $spn_array = ["$env->{REALM}.spn"];
2304
2305         $self->setup_namespaces($env, $upn_array, $spn_array);
2306
2307         $self->{vars}->{ad_dc} = $env;
2308         return $env;
2309 }
2310
2311 sub setup_none($$)
2312 {
2313         my ($self, $path) = @_;
2314
2315         my $ret = {
2316                 KRB5_CONFIG => abs_path($path) . "/no_krb5.conf",
2317                 SAMBA_PID => -1,
2318         }
2319 }
2320
2321 1;