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