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