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