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