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