tests/krb5: Add RodcPacEncryptionKey type allowing for RODC PAC signatures
[samba.git] / selftest / target / Samba3.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 # NOTE: Refer to the README for more details about the various testenvs,
7 # and tips about adding new testenvs.
8
9 package Samba3;
10
11 use strict;
12 use warnings;
13 use Cwd qw(abs_path);
14 use FindBin qw($RealBin);
15 use POSIX;
16 use target::Samba;
17 use File::Path 'remove_tree';
18
19 sub return_alias_env
20 {
21         my ($self, $path, $env) = @_;
22
23         # just an alias
24         return $env;
25 }
26
27 sub have_ads($) {
28         my ($self) = @_;
29         my $found_ads = 0;
30         my $smbd_build_options = Samba::bindir_path($self, "smbd") . " --configfile=/dev/null -b|";
31         open(IN, $smbd_build_options) or die("Unable to run $smbd_build_options: $!");
32
33         while (<IN>) {
34                 if (/WITH_ADS/) {
35                        $found_ads = 1;
36                 }
37         }
38         close IN;
39
40         # If we were not built with ADS support, pretend we were never even available
41         print "smbd does not have ADS support\n" unless $found_ads;
42         return $found_ads;
43 }
44
45 # return smb.conf parameters applicable to @path, based on the underlying
46 # filesystem type
47 sub get_fs_specific_conf($$)
48 {
49         my ($self, $path) = @_;
50         my $mods = "";
51         my $stat_out = `stat --file-system $path` or return "";
52
53         if ($stat_out =~ m/Type:\s+btrfs/) {
54                 $mods .= "streams_xattr btrfs";
55         }
56
57         if ($mods) {
58                 return "vfs objects = $mods";
59         }
60
61         return '';
62 }
63
64 sub new($$) {
65         my ($classname, $SambaCtx, $bindir, $srcdir, $server_maxtime) = @_;
66         my $self = { vars => {},
67                      SambaCtx => $SambaCtx,
68                      bindir => $bindir,
69                      srcdir => $srcdir,
70                      server_maxtime => $server_maxtime
71         };
72         bless $self;
73         return $self;
74 }
75
76 sub teardown_env($$)
77 {
78         my ($self, $envvars) = @_;
79
80         if (defined($envvars->{CTDB_PREFIX})) {
81                 $self->teardown_env_ctdb($envvars);
82         } else {
83                 $self->teardown_env_samba($envvars);
84         }
85
86         return;
87 }
88
89 sub teardown_env_samba($$)
90 {
91         my ($self, $envvars) = @_;
92         my $count = 0;
93
94         # This should cause smbd to terminate gracefully
95         close($envvars->{STDIN_PIPE});
96
97         my $smbdpid = $envvars->{SMBD_TL_PID};
98         my $nmbdpid = $envvars->{NMBD_TL_PID};
99         my $winbinddpid = $envvars->{WINBINDD_TL_PID};
100
101         # This should give it time to write out the gcov data
102         until ($count > 20) {
103             my $smbdchild = Samba::cleanup_child($smbdpid, "smbd");
104             my $nmbdchild = Samba::cleanup_child($nmbdpid, "nmbd");
105             my $winbinddchild = Samba::cleanup_child($winbinddpid, "winbindd");
106             if ($smbdchild == -1
107                 && $nmbdchild == -1
108                 && $winbinddchild == -1) {
109                 last;
110             }
111             sleep(1);
112             $count++;
113         }
114
115         if ($count <= 20 && kill(0, $smbdpid, $nmbdpid, $winbinddpid) == 0) {
116             return;
117         }
118
119         $self->stop_sig_term($smbdpid);
120         $self->stop_sig_term($nmbdpid);
121         $self->stop_sig_term($winbinddpid);
122
123         $count = 0;
124         until ($count > 10) {
125             my $smbdchild = Samba::cleanup_child($smbdpid, "smbd");
126             my $nmbdchild = Samba::cleanup_child($nmbdpid, "nmbd");
127             my $winbinddchild = Samba::cleanup_child($winbinddpid, "winbindd");
128             if ($smbdchild == -1
129                 && $nmbdchild == -1
130                 && $winbinddchild == -1) {
131                 last;
132             }
133             sleep(1);
134             $count++;
135         }
136
137         if ($count <= 10 && kill(0, $smbdpid, $nmbdpid, $winbinddpid) == 0) {
138             return;
139         }
140
141         warn("timelimit process did not quit on SIGTERM, sending SIGKILL");
142         $self->stop_sig_kill($smbdpid);
143         $self->stop_sig_kill($nmbdpid);
144         $self->stop_sig_kill($winbinddpid);
145
146         return 0;
147 }
148
149 sub teardown_env_ctdb($$)
150 {
151         my ($self, $data) = @_;
152
153         if (defined($data->{SAMBA_NODES})) {
154                 my $num_nodes = $data->{NUM_NODES};
155                 my $nodes = $data->{SAMBA_NODES};
156
157                 for (my $i = 0; $i < $num_nodes; $i++) {
158                         if (defined($nodes->[$i])) {
159                                 $self->teardown_env_samba($nodes->[$i]);
160                         }
161                 }
162         }
163
164         close($data->{CTDB_STDIN_PIPE});
165
166         if (not defined($data->{SAMBA_NODES})) {
167                 # Give waiting children time to exit
168                 sleep(5);
169         }
170
171         return 0;
172 }
173
174 sub getlog_env_app($$$)
175 {
176         my ($self, $envvars, $name) = @_;
177
178         my $title = "$name LOG of: $envvars->{NETBIOSNAME}\n";
179         my $out = $title;
180
181         open(LOG, "<".$envvars->{$name."_TEST_LOG"});
182
183         seek(LOG, $envvars->{$name."_TEST_LOG_POS"}, SEEK_SET);
184         while (<LOG>) {
185                 $out .= $_;
186         }
187         $envvars->{$name."_TEST_LOG_POS"} = tell(LOG);
188         close(LOG);
189
190         return "" if $out eq $title;
191  
192         return $out;
193 }
194
195 sub getlog_env($$)
196 {
197         my ($self, $envvars) = @_;
198         my $ret = "";
199
200         $ret .= $self->getlog_env_app($envvars, "SMBD");
201         $ret .= $self->getlog_env_app($envvars, "NMBD");
202         $ret .= $self->getlog_env_app($envvars, "WINBINDD");
203
204         return $ret;
205 }
206
207 sub check_env($$)
208 {
209         my ($self, $envvars) = @_;
210
211         my $childpid = waitpid(-1, WNOHANG);
212
213         # TODO ...
214         return 1;
215 }
216
217 # Declare the environments Samba3 makes available.
218 # To be set up, they will be called as
219 #   samba3->setup_$envname($self, $path, $dep_1_vars, $dep_2_vars, ...)
220 %Samba3::ENV_DEPS = (
221         # name              => [dep_1, dep_2, ...],
222         nt4_dc              => [],
223         nt4_dc_smb1         => [],
224         nt4_dc_smb1_done    => ["nt4_dc_smb1"],
225         nt4_dc_schannel     => [],
226
227         simpleserver        => [],
228         fileserver          => [],
229         fileserver_smb1     => [],
230         fileserver_smb1_done => ["fileserver_smb1"],
231         maptoguest          => [],
232         ktest               => [],
233
234         nt4_member          => ["nt4_dc"],
235
236         ad_member           => ["ad_dc", "fl2008r2dc", "fl2003dc"],
237         ad_member_rfc2307   => ["ad_dc_ntvfs"],
238         ad_member_idmap_rid => ["ad_dc"],
239         ad_member_idmap_ad  => ["fl2008r2dc"],
240         ad_member_fips      => ["ad_dc_fips"],
241         ad_member_offlogon  => ["ad_dc"],
242         ad_member_oneway    => ["fl2000dc"],
243
244         clusteredmember => ["nt4_dc"],
245 );
246
247 %Samba3::ENV_DEPS_POST = ();
248
249 sub setup_nt4_dc
250 {
251         my ($self, $path, $more_conf, $server) = @_;
252
253         print "PROVISIONING NT4 DC...";
254
255         my $nt4_dc_options = "
256         domain master = yes
257         domain logons = yes
258         lanman auth = yes
259         ntlm auth = yes
260         raw NTLMv2 auth = yes
261         server schannel = auto
262
263         rpc_server:epmapper = external
264         rpc_server:spoolss = external
265         rpc_server:lsarpc = external
266         rpc_server:samr = external
267         rpc_server:netlogon = external
268         rpc_server:register_embedded_np = yes
269         rpc_server:FssagentRpc = external
270
271         rpc_daemon:epmd = fork
272         rpc_daemon:spoolssd = fork
273         rpc_daemon:lsasd = fork
274         rpc_daemon:fssd = fork
275         fss: sequence timeout = 1
276         check parent directory delete on close = yes
277 ";
278
279         if (defined($more_conf)) {
280                 $nt4_dc_options = $nt4_dc_options . $more_conf;
281         }
282         if (!defined($server)) {
283                 $server = "LOCALNT4DC2";
284         }
285         my $vars = $self->provision(
286             prefix => $path,
287             domain => "SAMBA-TEST",
288             server => $server,
289             password => "localntdc2pass",
290             extra_options => $nt4_dc_options);
291
292         $vars or return undef;
293
294         if (not $self->check_or_start(
295                 env_vars => $vars,
296                 nmbd => "yes",
297                 winbindd => "yes",
298                 smbd => "yes")) {
299                return undef;
300         }
301
302         $vars->{DOMSID} = $vars->{SAMSID};
303         $vars->{DC_SERVER} = $vars->{SERVER};
304         $vars->{DC_SERVER_IP} = $vars->{SERVER_IP};
305         $vars->{DC_SERVER_IPV6} = $vars->{SERVER_IPV6};
306         $vars->{DC_NETBIOSNAME} = $vars->{NETBIOSNAME};
307         $vars->{DC_USERNAME} = $vars->{USERNAME};
308         $vars->{DC_PASSWORD} = $vars->{PASSWORD};
309
310         return $vars;
311 }
312
313 sub setup_nt4_dc_smb1
314 {
315         my ($self, $path) = @_;
316         my $conf = "
317 [global]
318         client min protocol = CORE
319         server min protocol = LANMAN1
320 ";
321         return $self->setup_nt4_dc($path, $conf, "LCLNT4DC2SMB1");
322 }
323
324 sub setup_nt4_dc_smb1_done
325 {
326         my ($self, $path, $dep_env) = @_;
327         return $self->return_alias_env($path, $dep_env);
328 }
329
330 sub setup_nt4_dc_schannel
331 {
332         my ($self, $path) = @_;
333
334         print "PROVISIONING NT4 DC WITH SERVER SCHANNEL ...";
335
336         my $pdc_options = "
337         domain master = yes
338         domain logons = yes
339         lanman auth = yes
340
341         rpc_server:epmapper = external
342         rpc_server:spoolss = external
343         rpc_server:lsarpc = external
344         rpc_server:samr = external
345         rpc_server:netlogon = external
346         rpc_server:register_embedded_np = yes
347
348         rpc_daemon:epmd = fork
349         rpc_daemon:spoolssd = fork
350         rpc_daemon:lsasd = fork
351
352         server schannel = yes
353         # used to reproduce bug #12772
354         server max protocol = SMB2_02
355 ";
356
357         my $vars = $self->provision(
358             prefix => $path,
359             domain => "NT4SCHANNEL",
360             server => "LOCALNT4DC9",
361             password => "localntdc9pass",
362             extra_options => $pdc_options);
363
364         $vars or return undef;
365
366         if (not $self->check_or_start(
367                 env_vars => $vars,
368                 nmbd => "yes",
369                 winbindd => "yes",
370                 smbd => "yes")) {
371                return undef;
372         }
373
374         $vars->{DOMSID} = $vars->{SAMSID};
375         $vars->{DC_SERVER} = $vars->{SERVER};
376         $vars->{DC_SERVER_IP} = $vars->{SERVER_IP};
377         $vars->{DC_SERVER_IPV6} = $vars->{SERVER_IPV6};
378         $vars->{DC_NETBIOSNAME} = $vars->{NETBIOSNAME};
379         $vars->{DC_USERNAME} = $vars->{USERNAME};
380         $vars->{DC_PASSWORD} = $vars->{PASSWORD};
381
382         return $vars;
383 }
384
385 sub setup_nt4_member
386 {
387         my ($self, $prefix, $nt4_dc_vars) = @_;
388         my $count = 0;
389         my $rc;
390
391         print "PROVISIONING MEMBER...";
392
393         my $require_mutexes = "dbwrap_tdb_require_mutexes:* = yes";
394         if ($ENV{SELFTEST_DONT_REQUIRE_TDB_MUTEX_SUPPORT} // '' eq "1") {
395                 $require_mutexes = "";
396         }
397
398         my $member_options = "
399         security = domain
400         dbwrap_tdb_mutexes:* = yes
401         ${require_mutexes}
402 ";
403         my $ret = $self->provision(
404             prefix => $prefix,
405             domain => $nt4_dc_vars->{DOMAIN},
406             server => "LOCALNT4MEMBER3",
407             password => "localnt4member3pass",
408             extra_options => $member_options);
409
410         $ret or return undef;
411
412         my $nmblookup = Samba::bindir_path($self, "nmblookup");
413         do {
414                 print "Waiting for the LOGON SERVER registration ...\n";
415                 $rc = system("$nmblookup $ret->{CONFIGURATION} $ret->{DOMAIN}\#1c");
416                 if ($rc != 0) {
417                         sleep(1);
418                 }
419                 $count++;
420         } while ($rc != 0 && $count < 10);
421         if ($count == 10) {
422                 print "NMBD not reachable after 10 retries\n";
423                 teardown_env($self, $ret);
424                 return 0;
425         }
426
427         my $net = Samba::bindir_path($self, "net");
428         # Add hosts file for name lookups
429         my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
430         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
431         $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
432         $cmd .= "$net rpc join $ret->{CONFIGURATION} $nt4_dc_vars->{DOMAIN} member";
433         $cmd .= " -U$nt4_dc_vars->{USERNAME}\%$nt4_dc_vars->{PASSWORD}";
434
435         if (system($cmd) != 0) {
436             warn("Join failed\n$cmd");
437             return undef;
438         }
439
440         # Add hosts file for name lookups
441         $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
442         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
443         $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
444         $cmd .= "$net $ret->{CONFIGURATION} primarytrust dumpinfo | grep -q 'REDACTED SECRET VALUES'";
445
446         if (system($cmd) != 0) {
447             warn("check failed\n$cmd");
448             return undef;
449         }
450
451         if (not $self->check_or_start(
452                 env_vars => $ret,
453                 nmbd => "yes",
454                 winbindd => "yes",
455                 smbd => "yes")) {
456                return undef;
457         }
458
459         $ret->{DOMSID} = $nt4_dc_vars->{DOMSID};
460         $ret->{DC_SERVER} = $nt4_dc_vars->{SERVER};
461         $ret->{DC_SERVER_IP} = $nt4_dc_vars->{SERVER_IP};
462         $ret->{DC_SERVER_IPV6} = $nt4_dc_vars->{SERVER_IPV6};
463         $ret->{DC_NETBIOSNAME} = $nt4_dc_vars->{NETBIOSNAME};
464         $ret->{DC_USERNAME} = $nt4_dc_vars->{USERNAME};
465         $ret->{DC_PASSWORD} = $nt4_dc_vars->{PASSWORD};
466
467         return $ret;
468 }
469
470 sub setup_clusteredmember
471 {
472         my ($self, $prefix, $nt4_dc_vars) = @_;
473         my $count = 0;
474         my $rc;
475         my @retvals = ();
476         my $ret;
477
478         print "PROVISIONING CLUSTEREDMEMBER...\n";
479
480         my $prefix_abs = abs_path($prefix);
481         mkdir($prefix_abs, 0777);
482
483         my $server_name = "CLUSTEREDMEMBER";
484
485         my $ctdb_data = $self->setup_ctdb($prefix);
486
487         if (not $ctdb_data) {
488                 print "No ctdb data\n";
489                 return undef;
490         }
491
492         print "PROVISIONING CLUSTERED SAMBA...\n";
493
494         my $num_nodes = $ctdb_data->{NUM_NODES};
495         my $nodes = $ctdb_data->{CTDB_NODES};
496
497         # Enable cleanup of earlier nodes if a later node fails
498         $ctdb_data->{SAMBA_NODES} = \@retvals;
499
500         for (my $i = 0; $i < $num_nodes; $i++) {
501                 my $node = $nodes->[$i];
502                 my $socket = $node->{SOCKET_FILE};
503                 my $server_name = $node->{SERVER_NAME};
504                 my $pub_iface = $node->{SOCKET_WRAPPER_DEFAULT_IFACE};
505                 my $node_prefix = $node->{NODE_PREFIX};
506
507                 print "NODE_PREFIX=${node_prefix}\n";
508                 print "SOCKET=${socket}\n";
509
510                 my $require_mutexes = "dbwrap_tdb_require_mutexes:* = yes";
511                 if ($ENV{SELFTEST_DONT_REQUIRE_TDB_MUTEX_SUPPORT} // '' eq "1") {
512                         $require_mutexes = "" ;
513                 }
514
515                 my $member_options = "
516        security = domain
517        server signing = on
518        clustering = yes
519        ctdbd socket = ${socket}
520        include = registry
521        dbwrap_tdb_mutexes:* = yes
522        ${require_mutexes}
523 ";
524
525                 my $node_ret = $self->provision(
526                     prefix => "$node_prefix",
527                     domain => $nt4_dc_vars->{DOMAIN},
528                     server => "$server_name",
529                     password => "clustermember8pass",
530                     netbios_name => "CLUSTEREDMEMBER",
531                     share_dir => "${prefix_abs}/shared",
532                     extra_options => $member_options,
533                     no_delete_prefix => 1);
534                 if (not $node_ret) {
535                         print "Provision node $i failed\n";
536                         teardown_env($self, $ctdb_data);
537                         return undef;
538                 }
539
540                 my $nmblookup = Samba::bindir_path($self, "nmblookup");
541                 do {
542                         print "Waiting for the LOGON SERVER registration ...\n";
543                         $rc = system("$nmblookup $node_ret->{CONFIGURATION} " .
544                                      "$node_ret->{DOMAIN}\#1c");
545                         if ($rc != 0) {
546                                 sleep(1);
547                         }
548                         $count++;
549                 } while ($rc != 0 && $count < 10);
550
551                 if ($count == 10) {
552                         print "NMBD not reachable after 10 retries\n";
553                         teardown_env($self, $node_ret);
554                         teardown_env($self, $ctdb_data);
555                         return undef;
556                 }
557
558                 push(@retvals, $node_ret);
559         }
560
561         $ret = {%$ctdb_data, %{$retvals[0]}};
562
563         my $net = Samba::bindir_path($self, "net");
564         my $cmd = "";
565         $cmd .= "UID_WRAPPER_ROOT=1 ";
566         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
567         $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
568         $cmd .= "$net join $ret->{CONFIGURATION} $nt4_dc_vars->{DOMAIN} member";
569         $cmd .= " -U$nt4_dc_vars->{USERNAME}\%$nt4_dc_vars->{PASSWORD}";
570
571         if (system($cmd) != 0) {
572                 warn("Join failed\n$cmd");
573                 teardown_env($self, $ret);
574                 return undef;
575         }
576
577         for (my $i=0; $i<@retvals; $i++) {
578                 my $node_provision = $retvals[$i];
579                 my $ok;
580                 $ok = $self->check_or_start(
581                     env_vars => $node_provision,
582                     winbindd => "yes",
583                     smbd => "yes",
584                     child_cleanup => sub {
585                         map {
586                             my $fh = $_->{STDIN_PIPE};
587                             close($fh) if defined($fh);
588                         } @retvals });
589                 if (not $ok) {
590                         teardown_env($self, $ret);
591                         return undef;
592                 }
593         }
594
595         #
596         # Build a unclist for every share
597         #
598         unless (open(NODES, "<$ret->{CTDB_NODES_FILE}")) {
599                 warn("Unable to open CTDB nodes file");
600                 teardown_env($self, $ret);
601                 return undef;
602         }
603         my @nodes = <NODES>;
604         close(NODES);
605         chomp @nodes;
606
607         my $conffile = $ret->{SERVERCONFFILE};
608         $cmd = "";
609         $cmd .= 'sed -n -e \'s|^\[\(.*\)\]$|\1|p\'';
610         $cmd .= " \"$conffile\"";
611         $cmd .= " | grep -vx 'global'";
612
613         my @shares = `$cmd`;
614         $rc = $?;
615         if ($rc != 0) {
616                 warn("Listing shares failed\n$cmd");
617                 teardown_env($self, $ret);
618                 return undef;
619         }
620         chomp @shares;
621
622         my $unclistdir = "${prefix_abs}/unclists";
623         mkdir($unclistdir, 0777);
624         foreach my $share (@shares) {
625                 my $l = "${unclistdir}/${share}.txt";
626                 unless (open(UNCLIST, ">${l}")) {
627                         warn("Unable to open UNC list ${l}");
628                         teardown_env($self, $ret);
629                         return undef;
630                 }
631                 foreach my $node (@nodes) {
632                         print UNCLIST "//${node}/${share}\n";
633                 }
634                 close(UNCLIST);
635         }
636
637         $ret->{DOMSID} = $nt4_dc_vars->{DOMSID};
638         $ret->{DC_SERVER} = $nt4_dc_vars->{SERVER};
639         $ret->{DC_SERVER_IP} = $nt4_dc_vars->{SERVER_IP};
640         $ret->{DC_SERVER_IPV6} = $nt4_dc_vars->{SERVER_IPV6};
641         $ret->{DC_NETBIOSNAME} = $nt4_dc_vars->{NETBIOSNAME};
642         $ret->{DC_USERNAME} = $nt4_dc_vars->{USERNAME};
643         $ret->{DC_PASSWORD} = $nt4_dc_vars->{PASSWORD};
644
645         return $ret;
646 }
647
648 sub provision_ad_member
649 {
650         my ($self,
651             $prefix,
652             $machine_account,
653             $dcvars,
654             $trustvars_f,
655             $trustvars_e,
656             $force_fips_mode,
657             $offline_logon) = @_;
658
659         my $prefix_abs = abs_path($prefix);
660         my @dirs = ();
661
662         mkdir($prefix_abs, 0777);
663
664         my $share_dir="$prefix_abs/share";
665         push(@dirs, $share_dir);
666
667         my $substitution_path = "$share_dir/D_$dcvars->{DOMAIN}";
668         push(@dirs, $substitution_path);
669
670         $substitution_path = "$share_dir/D_$dcvars->{DOMAIN}/U_alice";
671         push(@dirs, $substitution_path);
672
673         $substitution_path = "$share_dir/D_$dcvars->{DOMAIN}/U_alice/G_domain users";
674         push(@dirs, $substitution_path);
675
676         # Using '/' as the winbind separator is a bad idea ...
677         $substitution_path = "$share_dir/D_$dcvars->{DOMAIN}/u_$dcvars->{DOMAIN}";
678         push(@dirs, $substitution_path);
679
680         $substitution_path = "$share_dir/D_$dcvars->{DOMAIN}/u_$dcvars->{DOMAIN}/alice";
681         push(@dirs, $substitution_path);
682
683         $substitution_path = "$share_dir/D_$dcvars->{DOMAIN}/u_$dcvars->{DOMAIN}/alice/g_$dcvars->{DOMAIN}";
684         push(@dirs, $substitution_path);
685
686         $substitution_path = "$share_dir/D_$dcvars->{DOMAIN}/u_$dcvars->{DOMAIN}/alice/g_$dcvars->{DOMAIN}/domain users";
687         push(@dirs, $substitution_path);
688
689         my $option_offline_logon = "no";
690         if (defined($offline_logon)) {
691                 $option_offline_logon = "yes";
692         }
693
694         my $netbios_aliases = "";
695         if ($machine_account eq "LOCALADMEMBER") {
696                 $netbios_aliases = "netbios aliases = foo bar";
697         }
698
699         my $member_options = "
700         security = ads
701         workgroup = $dcvars->{DOMAIN}
702         realm = $dcvars->{REALM}
703         $netbios_aliases
704         template homedir = /home/%D/%G/%U
705         auth event notification = true
706         password server = $dcvars->{SERVER}
707         winbind scan trusted domains = no
708         winbind offline logon = $option_offline_logon
709
710         allow dcerpc auth level connect:lsarpc = yes
711         dcesrv:max auth states = 8
712
713         rpc_server:epmapper = external
714         rpc_server:lsarpc = external
715         rpc_server:samr = external
716         rpc_server:netlogon = disabled
717         rpc_server:register_embedded_np = yes
718
719         rpc_daemon:epmd = fork
720         rpc_daemon:lsasd = fork
721
722 [sub_dug]
723         path = $share_dir/D_%D/U_%U/G_%G
724         writeable = yes
725
726 [sub_dug2]
727         path = $share_dir/D_%D/u_%u/g_%g
728         writeable = yes
729
730 [sub_valid_users]
731         path = $share_dir
732         valid users = ADDOMAIN/%U
733
734 [sub_valid_users_domain]
735     path = $share_dir
736     valid users = %D/%U
737
738 [sub_valid_users_group]
739     path = $share_dir
740     valid users = \@$dcvars->{DOMAIN}/%G
741
742 [valid_users]
743     path = $share_dir
744     valid users = $dcvars->{DOMAIN}/$dcvars->{DC_USERNAME}
745
746 [valid_users_group]
747     path = $share_dir
748     valid users = \"\@$dcvars->{DOMAIN}/domain users\"
749
750 [valid_users_unix_group]
751     path = $share_dir
752     valid users = \"+$dcvars->{DOMAIN}/domain users\"
753
754 [valid_users_unix_nis_group]
755     path = $share_dir
756     valid users = \"+&$dcvars->{DOMAIN}/domain users\"
757
758 [valid_users_nis_unix_group]
759     path = $share_dir
760     valid users = \"&+$dcvars->{DOMAIN}/domain users\"
761
762 [invalid_users]
763     path = $share_dir
764     invalid users = $dcvars->{DOMAIN}/$dcvars->{DC_USERNAME}
765
766 [valid_and_invalid_users]
767     path = $share_dir
768     valid users = $dcvars->{DOMAIN}/$dcvars->{DC_USERNAME} $dcvars->{DOMAIN}/alice
769     invalid users = $dcvars->{DOMAIN}/$dcvars->{DC_USERNAME}
770 ";
771
772         my $ret = $self->provision(
773             prefix => $prefix,
774             domain => $dcvars->{DOMAIN},
775             realm => $dcvars->{REALM},
776             server => $machine_account,
777             password => "loCalMemberPass",
778             extra_options => $member_options,
779             resolv_conf => $dcvars->{RESOLV_CONF});
780
781         $ret or return undef;
782
783         mkdir($_, 0777) foreach(@dirs);
784
785         close(USERMAP);
786         $ret->{DOMAIN} = $dcvars->{DOMAIN};
787         $ret->{REALM} = $dcvars->{REALM};
788         $ret->{DOMSID} = $dcvars->{DOMSID};
789
790         my $ctx;
791         $ctx = {};
792         $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
793         $ctx->{domain} = $dcvars->{DOMAIN};
794         $ctx->{realm} = $dcvars->{REALM};
795         $ctx->{dnsname} = lc($dcvars->{REALM});
796         $ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
797         $ctx->{kdc_ipv6} = $dcvars->{SERVER_IPV6};
798         $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
799         Samba::mk_krb5_conf($ctx, "");
800
801         $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
802
803         if (defined($force_fips_mode)) {
804                 $ret->{GNUTLS_FORCE_FIPS_MODE} = "1";
805                 $ret->{OPENSSL_FORCE_FIPS_MODE} = "1";
806         }
807
808         my $net = Samba::bindir_path($self, "net");
809         # Add hosts file for name lookups
810         my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
811         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
812         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
813                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
814         } else {
815                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
816         }
817         if (defined($force_fips_mode)) {
818                 $cmd .= "GNUTLS_FORCE_FIPS_MODE=1 ";
819                 $cmd .= "OPENSSL_FORCE_FIPS_MODE=1 ";
820         }
821         $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
822         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
823         $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
824         $cmd .= "$net join $ret->{CONFIGURATION}";
825         $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD} --use-kerberos=required";
826
827         if (system($cmd) != 0) {
828             warn("Join failed\n$cmd");
829             return undef;
830         }
831
832         # We need world access to this share, as otherwise the domain
833         # administrator from the AD domain provided by Samba4 can't
834         # access the share for tests.
835         chmod 0777, "$prefix/share";
836
837         if (defined($offline_logon)) {
838                 my $wbinfo = Samba::bindir_path($self, "wbinfo");
839
840                 if (not $self->check_or_start(
841                         env_vars => $ret,
842                         winbindd => "yes")) {
843                         return undef;
844                 }
845
846                 # Fill samlogoncache for alice
847                 $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
848                 $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
849                 $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
850                 $cmd .= "$wbinfo --pam-logon=ADDOMAIN/alice%Secret007";
851                 if (system($cmd) != 0) {
852                         warn("Filling the cache failed\n$cmd");
853                         return undef;
854                 }
855
856                 $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
857                 $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
858                 $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
859                 $cmd .= "$wbinfo --ccache-save=ADDOMAIN/alice%Secret007";
860                 if (system($cmd) != 0) {
861                         warn("Filling the cache failed\n$cmd");
862                         return undef;
863                 }
864
865                 # Fill samlogoncache for bob
866                 $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
867                 $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
868                 $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
869                 $cmd .= "$wbinfo --pam-logon=ADDOMAIN/bob%Secret007";
870                 if (system($cmd) != 0) {
871                         warn("Filling the cache failed\n$cmd");
872                         return undef;
873                 }
874
875                 $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
876                 $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
877                 $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
878                 $cmd .= "$wbinfo --ccache-save=ADDOMAIN/bob%Secret007";
879                 if (system($cmd) != 0) {
880                         warn("Filling the cache failed\n$cmd");
881                         return undef;
882                 }
883
884                 # Set windindd offline
885                 my $smbcontrol = Samba::bindir_path($self, "smbcontrol");
886                 $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
887                 $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
888                 $cmd .= "UID_WRAPPER_ROOT='1' ";
889                 $cmd .= "$smbcontrol $ret->{CONFIGURATION} winbindd offline";
890                 if (system($cmd) != 0) {
891                         warn("Setting winbindd offline failed\n$cmd");
892                         return undef;
893                 }
894
895                 # Validate the offline cache
896                 $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
897                 $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
898                 $cmd .= "UID_WRAPPER_ROOT='1' ";
899                 $cmd .= "$smbcontrol $ret->{CONFIGURATION} winbindd validate-cache";
900                 if (system($cmd) != 0) {
901                         warn("Validation of winbind credential cache failed\n$cmd");
902                         teardown_env($self, $ret);
903                         return undef;
904                 }
905
906                 # Shut down winbindd
907                 teardown_env($self, $ret);
908
909                 ### Change SOCKET_WRAPPER_DIR so it can't connect to AD
910                 my $swrap_env = $ENV{SOCKET_WRAPPER_DIR};
911                 $ENV{SOCKET_WRAPPER_DIR} = "$prefix_abs";
912
913                 # Start winbindd in offline mode
914                 if (not $self->check_or_start(
915                         env_vars => $ret,
916                         winbindd => "yes",
917                         skip_wait => 1)) {
918                         return undef;
919                 }
920
921                 # Set socket dir again
922                 $ENV{SOCKET_WRAPPER_DIR} = $swrap_env;
923
924                 print "checking for winbindd\n";
925                 my $count = 0;
926                 my $rc = 0;
927                 $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
928                 $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
929                 $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
930                 $cmd .= "$wbinfo --ping";
931
932                 do {
933                         $rc = system($cmd);
934                         if ($rc != 0) {
935                                 sleep(1);
936                         }
937                         $count++;
938                 } while ($rc != 0 && $count < 20);
939                 if ($count == 20) {
940                         print "WINBINDD not reachable after 20 seconds\n";
941                         teardown_env($self, $ret);
942                         return undef;
943                 }
944         } else {
945                 if (not $self->check_or_start(
946                         env_vars => $ret,
947                         nmbd => "yes",
948                         winbindd => "yes",
949                         smbd => "yes")) {
950                         return undef;
951                 }
952         }
953
954         $ret->{DC_SERVER} = $dcvars->{SERVER};
955         $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
956         $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6};
957         $ret->{DC_SERVERCONFFILE} = $dcvars->{SERVERCONFFILE};
958         $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
959         $ret->{DC_USERNAME} = $dcvars->{USERNAME};
960         $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
961
962         # forest trust
963         $ret->{TRUST_F_BOTH_SERVER} = $trustvars_f->{SERVER};
964         $ret->{TRUST_F_BOTH_SERVER_IP} = $trustvars_f->{SERVER_IP};
965         $ret->{TRUST_F_BOTH_SERVER_IPV6} = $trustvars_f->{SERVER_IPV6};
966         $ret->{TRUST_F_BOTH_NETBIOSNAME} = $trustvars_f->{NETBIOSNAME};
967         $ret->{TRUST_F_BOTH_USERNAME} = $trustvars_f->{USERNAME};
968         $ret->{TRUST_F_BOTH_PASSWORD} = $trustvars_f->{PASSWORD};
969         $ret->{TRUST_F_BOTH_DOMAIN} = $trustvars_f->{DOMAIN};
970         $ret->{TRUST_F_BOTH_REALM} = $trustvars_f->{REALM};
971
972         # external trust
973         $ret->{TRUST_E_BOTH_SERVER} = $trustvars_e->{SERVER};
974         $ret->{TRUST_E_BOTH_SERVER_IP} = $trustvars_e->{SERVER_IP};
975         $ret->{TRUST_E_BOTH_SERVER_IPV6} = $trustvars_e->{SERVER_IPV6};
976         $ret->{TRUST_E_BOTH_NETBIOSNAME} = $trustvars_e->{NETBIOSNAME};
977         $ret->{TRUST_E_BOTH_USERNAME} = $trustvars_e->{USERNAME};
978         $ret->{TRUST_E_BOTH_PASSWORD} = $trustvars_e->{PASSWORD};
979         $ret->{TRUST_E_BOTH_DOMAIN} = $trustvars_e->{DOMAIN};
980         $ret->{TRUST_E_BOTH_REALM} = $trustvars_e->{REALM};
981
982         return $ret;
983 }
984
985 sub setup_ad_member
986 {
987         my ($self,
988             $prefix,
989             $dcvars,
990             $trustvars_f,
991             $trustvars_e) = @_;
992
993         # If we didn't build with ADS, pretend this env was never available
994         if (not $self->have_ads()) {
995                 return "UNKNOWN";
996         }
997
998         print "PROVISIONING AD MEMBER...";
999
1000         return $self->provision_ad_member($prefix,
1001                                           "LOCALADMEMBER",
1002                                           $dcvars,
1003                                           $trustvars_f,
1004                                           $trustvars_e);
1005 }
1006
1007 sub setup_ad_member_rfc2307
1008 {
1009         my ($self, $prefix, $dcvars) = @_;
1010
1011         # If we didn't build with ADS, pretend this env was never available
1012         if (not $self->have_ads()) {
1013                 return "UNKNOWN";
1014         }
1015
1016         print "PROVISIONING S3 AD MEMBER WITH idmap_rfc2307 config...";
1017
1018         my $member_options = "
1019         security = ads
1020         workgroup = $dcvars->{DOMAIN}
1021         realm = $dcvars->{REALM}
1022         idmap cache time = 0
1023         idmap negative cache time = 0
1024         idmap config * : backend = autorid
1025         idmap config * : range = 1000000-1999999
1026         idmap config * : rangesize = 100000
1027         idmap config $dcvars->{DOMAIN} : backend = rfc2307
1028         idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
1029         idmap config $dcvars->{DOMAIN} : ldap_server = ad
1030         idmap config $dcvars->{DOMAIN} : bind_path_user = ou=idmap,dc=samba,dc=example,dc=com
1031         idmap config $dcvars->{DOMAIN} : bind_path_group = ou=idmap,dc=samba,dc=example,dc=com
1032
1033         password server = $dcvars->{SERVER}
1034 ";
1035
1036         my $ret = $self->provision(
1037             prefix => $prefix,
1038             domain => $dcvars->{DOMAIN},
1039             realm => $dcvars->{REALM},
1040             server => "RFC2307MEMBER",
1041             password => "loCalMemberPass",
1042             extra_options => $member_options,
1043             resolv_conf => $dcvars->{RESOLV_CONF});
1044
1045         $ret or return undef;
1046
1047         close(USERMAP);
1048         $ret->{DOMAIN} = $dcvars->{DOMAIN};
1049         $ret->{REALM} = $dcvars->{REALM};
1050         $ret->{DOMSID} = $dcvars->{DOMSID};
1051
1052         my $ctx;
1053         my $prefix_abs = abs_path($prefix);
1054         $ctx = {};
1055         $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
1056         $ctx->{domain} = $dcvars->{DOMAIN};
1057         $ctx->{realm} = $dcvars->{REALM};
1058         $ctx->{dnsname} = lc($dcvars->{REALM});
1059         $ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
1060         $ctx->{kdc_ipv6} = $dcvars->{SERVER_IPV6};
1061         $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
1062         Samba::mk_krb5_conf($ctx, "");
1063
1064         $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
1065
1066         my $net = Samba::bindir_path($self, "net");
1067         # Add hosts file for name lookups
1068         my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
1069         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1070         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1071                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1072         } else {
1073                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1074         }
1075         $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
1076         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1077         $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
1078         $cmd .= "$net join $ret->{CONFIGURATION}";
1079         $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
1080
1081         if (system($cmd) != 0) {
1082             warn("Join failed\n$cmd");
1083             return undef;
1084         }
1085
1086         # We need world access to this share, as otherwise the domain
1087         # administrator from the AD domain provided by Samba4 can't
1088         # access the share for tests.
1089         chmod 0777, "$prefix/share";
1090
1091         if (not $self->check_or_start(
1092                 env_vars => $ret,
1093                 nmbd => "yes",
1094                 winbindd => "yes",
1095                 smbd => "yes")) {
1096                 return undef;
1097         }
1098
1099         $ret->{DC_SERVER} = $dcvars->{SERVER};
1100         $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
1101         $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6};
1102         $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
1103         $ret->{DC_USERNAME} = $dcvars->{USERNAME};
1104         $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
1105
1106         return $ret;
1107 }
1108
1109 sub setup_ad_member_idmap_rid
1110 {
1111         my ($self, $prefix, $dcvars) = @_;
1112
1113         # If we didn't build with ADS, pretend this env was never available
1114         if (not $self->have_ads()) {
1115                 return "UNKNOWN";
1116         }
1117
1118         print "PROVISIONING S3 AD MEMBER WITH idmap_rid config...";
1119
1120         my $member_options = "
1121         security = ads
1122         workgroup = $dcvars->{DOMAIN}
1123         realm = $dcvars->{REALM}
1124         idmap config * : backend = tdb
1125         idmap config * : range = 1000000-1999999
1126         idmap config $dcvars->{DOMAIN} : backend = rid
1127         idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
1128         # Prevent overridding the provisioned lib/krb5.conf which sets certain
1129         # values required for tests to succeed
1130         create krb5 conf = no
1131         map to guest = bad user
1132 ";
1133
1134         my $ret = $self->provision(
1135             prefix => $prefix,
1136             domain => $dcvars->{DOMAIN},
1137             realm => $dcvars->{REALM},
1138             server => "IDMAPRIDMEMBER",
1139             password => "loCalMemberPass",
1140             extra_options => $member_options,
1141             resolv_conf => $dcvars->{RESOLV_CONF});
1142
1143         $ret or return undef;
1144
1145         close(USERMAP);
1146         $ret->{DOMAIN} = $dcvars->{DOMAIN};
1147         $ret->{REALM} = $dcvars->{REALM};
1148         $ret->{DOMSID} = $dcvars->{DOMSID};
1149
1150         my $ctx;
1151         my $prefix_abs = abs_path($prefix);
1152         $ctx = {};
1153         $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
1154         $ctx->{domain} = $dcvars->{DOMAIN};
1155         $ctx->{realm} = $dcvars->{REALM};
1156         $ctx->{dnsname} = lc($dcvars->{REALM});
1157         $ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
1158         $ctx->{kdc_ipv6} = $dcvars->{SERVER_IPV6};
1159         $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
1160         Samba::mk_krb5_conf($ctx, "");
1161
1162         $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
1163
1164         my $net = Samba::bindir_path($self, "net");
1165         # Add hosts file for name lookups
1166         my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
1167         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1168         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1169                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1170         } else {
1171                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1172         }
1173         $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
1174         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1175         $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
1176         $cmd .= "$net join $ret->{CONFIGURATION}";
1177         $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
1178
1179         if (system($cmd) != 0) {
1180             warn("Join failed\n$cmd");
1181             return undef;
1182         }
1183
1184         # We need world access to this share, as otherwise the domain
1185         # administrator from the AD domain provided by Samba4 can't
1186         # access the share for tests.
1187         chmod 0777, "$prefix/share";
1188
1189         if (not $self->check_or_start(
1190                 env_vars => $ret,
1191                 nmbd => "yes",
1192                 winbindd => "yes",
1193                 smbd => "yes")) {
1194                 return undef;
1195         }
1196
1197         $ret->{DC_SERVER} = $dcvars->{SERVER};
1198         $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
1199         $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6};
1200         $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
1201         $ret->{DC_USERNAME} = $dcvars->{USERNAME};
1202         $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
1203
1204         return $ret;
1205 }
1206
1207 sub setup_ad_member_idmap_ad
1208 {
1209         my ($self, $prefix, $dcvars) = @_;
1210
1211         # If we didn't build with ADS, pretend this env was never available
1212         if (not $self->have_ads()) {
1213                 return "UNKNOWN";
1214         }
1215
1216         print "PROVISIONING S3 AD MEMBER WITH idmap_ad config...";
1217
1218         my $member_options = "
1219         security = ads
1220         workgroup = $dcvars->{DOMAIN}
1221         realm = $dcvars->{REALM}
1222         password server = $dcvars->{SERVER}
1223         idmap config * : backend = tdb
1224         idmap config * : range = 1000000-1999999
1225         idmap config $dcvars->{DOMAIN} : backend = ad
1226         idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
1227         idmap config $dcvars->{DOMAIN} : unix_primary_group = yes
1228         idmap config $dcvars->{DOMAIN} : unix_nss_info = yes
1229         idmap config $dcvars->{TRUST_DOMAIN} : backend = ad
1230         idmap config $dcvars->{TRUST_DOMAIN} : range = 2000000-2999999
1231         gensec_gssapi:requested_life_time = 5
1232 ";
1233
1234         my $ret = $self->provision(
1235             prefix => $prefix,
1236             domain => $dcvars->{DOMAIN},
1237             realm => $dcvars->{REALM},
1238             server => "IDMAPADMEMBER",
1239             password => "loCalMemberPass",
1240             extra_options => $member_options,
1241             resolv_conf => $dcvars->{RESOLV_CONF});
1242
1243         $ret or return undef;
1244
1245         close(USERMAP);
1246         $ret->{DOMAIN} = $dcvars->{DOMAIN};
1247         $ret->{REALM} = $dcvars->{REALM};
1248         $ret->{DOMSID} = $dcvars->{DOMSID};
1249
1250         my $ctx;
1251         my $prefix_abs = abs_path($prefix);
1252         $ctx = {};
1253         $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
1254         $ctx->{domain} = $dcvars->{DOMAIN};
1255         $ctx->{realm} = $dcvars->{REALM};
1256         $ctx->{dnsname} = lc($dcvars->{REALM});
1257         $ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
1258         $ctx->{kdc_ipv6} = $dcvars->{SERVER_IPV6};
1259         $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
1260         Samba::mk_krb5_conf($ctx, "");
1261
1262         $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
1263
1264         my $net = Samba::bindir_path($self, "net");
1265         # Add hosts file for name lookups
1266         my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
1267         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1268         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1269                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1270         } else {
1271                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1272         }
1273         $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
1274         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1275         $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
1276         $cmd .= "$net join $ret->{CONFIGURATION}";
1277         $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
1278
1279         if (system($cmd) != 0) {
1280             warn("Join failed\n$cmd");
1281             return undef;
1282         }
1283
1284         # We need world access to this share, as otherwise the domain
1285         # administrator from the AD domain provided by Samba4 can't
1286         # access the share for tests.
1287         chmod 0777, "$prefix/share";
1288
1289         if (not $self->check_or_start(
1290                 env_vars => $ret,
1291                 nmbd => "yes",
1292                 winbindd => "yes",
1293                 smbd => "yes")) {
1294                 return undef;
1295         }
1296
1297         $ret->{DC_SERVER} = $dcvars->{SERVER};
1298         $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
1299         $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6};
1300         $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
1301         $ret->{DC_USERNAME} = $dcvars->{USERNAME};
1302         $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
1303
1304         $ret->{TRUST_SERVER} = $dcvars->{TRUST_SERVER};
1305         $ret->{TRUST_USERNAME} = $dcvars->{TRUST_USERNAME};
1306         $ret->{TRUST_PASSWORD} = $dcvars->{TRUST_PASSWORD};
1307         $ret->{TRUST_DOMAIN} = $dcvars->{TRUST_DOMAIN};
1308         $ret->{TRUST_REALM} = $dcvars->{TRUST_REALM};
1309         $ret->{TRUST_DOMSID} = $dcvars->{TRUST_DOMSID};
1310
1311         return $ret;
1312 }
1313
1314 sub setup_ad_member_oneway
1315 {
1316         my ($self, $prefix, $dcvars) = @_;
1317
1318         # If we didn't build with ADS, pretend this env was never available
1319         if (not $self->have_ads()) {
1320                 return "UNKNOWN";
1321         }
1322
1323         print "PROVISIONING S3 AD MEMBER WITH one-way trust...";
1324
1325         my $member_options = "
1326         security = ads
1327         workgroup = $dcvars->{DOMAIN}
1328         realm = $dcvars->{REALM}
1329         password server = $dcvars->{SERVER}
1330         idmap config * : backend = tdb
1331         idmap config * : range = 1000000-1999999
1332         gensec_gssapi:requested_life_time = 5
1333 ";
1334
1335         my $ret = $self->provision(
1336             prefix => $prefix,
1337             domain => $dcvars->{DOMAIN},
1338             server => "S2KMEMBER",
1339             password => "loCalS2KMemberPass",
1340             extra_options => $member_options,
1341             resolv_conf => $dcvars->{RESOLV_CONF});
1342
1343         $ret or return undef;
1344
1345         close(USERMAP);
1346         $ret->{DOMAIN} = $dcvars->{DOMAIN};
1347         $ret->{REALM} = $dcvars->{REALM};
1348         $ret->{DOMSID} = $dcvars->{DOMSID};
1349
1350         my $ctx;
1351         my $prefix_abs = abs_path($prefix);
1352         $ctx = {};
1353         $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
1354         $ctx->{domain} = $dcvars->{DOMAIN};
1355         $ctx->{realm} = $dcvars->{REALM};
1356         $ctx->{dnsname} = lc($dcvars->{REALM});
1357         $ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
1358         $ctx->{kdc_ipv6} = $dcvars->{SERVER_IPV6};
1359         $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
1360         Samba::mk_krb5_conf($ctx, "");
1361
1362         $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
1363
1364         my $net = Samba::bindir_path($self, "net");
1365         # Add hosts file for name lookups
1366         my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
1367         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
1368         if (defined($ret->{RESOLV_WRAPPER_CONF})) {
1369                 $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
1370         } else {
1371                 $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
1372         }
1373         $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
1374         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
1375         $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
1376         $cmd .= "$net join $ret->{CONFIGURATION}";
1377         $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
1378
1379         if (system($cmd) != 0) {
1380             warn("Join failed\n$cmd");
1381             return undef;
1382         }
1383
1384         if (not $self->check_or_start(
1385                 env_vars => $ret,
1386                 winbindd => "yes")) {
1387                 return undef;
1388         }
1389
1390         $ret->{DC_SERVER} = $dcvars->{SERVER};
1391         $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
1392         $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6};
1393         $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
1394         $ret->{DC_USERNAME} = $dcvars->{USERNAME};
1395         $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
1396
1397         $ret->{TRUST_SERVER} = $dcvars->{TRUST_SERVER};
1398         $ret->{TRUST_USERNAME} = $dcvars->{TRUST_USERNAME};
1399         $ret->{TRUST_PASSWORD} = $dcvars->{TRUST_PASSWORD};
1400         $ret->{TRUST_DOMAIN} = $dcvars->{TRUST_DOMAIN};
1401         $ret->{TRUST_REALM} = $dcvars->{TRUST_REALM};
1402         $ret->{TRUST_DOMSID} = $dcvars->{TRUST_DOMSID};
1403
1404         return $ret;
1405 }
1406
1407 sub setup_ad_member_fips
1408 {
1409         my ($self,
1410             $prefix,
1411             $dcvars,
1412             $trustvars_f,
1413             $trustvars_e) = @_;
1414
1415         # If we didn't build with ADS, pretend this env was never available
1416         if (not $self->have_ads()) {
1417                 return "UNKNOWN";
1418         }
1419
1420         print "PROVISIONING AD FIPS MEMBER...";
1421
1422         return $self->provision_ad_member($prefix,
1423                                           "FIPSADMEMBER",
1424                                           $dcvars,
1425                                           $trustvars_f,
1426                                           $trustvars_e,
1427                                           1);
1428 }
1429
1430 sub setup_ad_member_offlogon
1431 {
1432         my ($self,
1433             $prefix,
1434             $dcvars,
1435             $trustvars_f,
1436             $trustvars_e) = @_;
1437
1438         # If we didn't build with ADS, pretend this env was never available
1439         if (not $self->have_ads()) {
1440                 return "UNKNOWN";
1441         }
1442
1443         print "PROVISIONING AD MEMBER OFFLINE LOGON...";
1444
1445         return $self->provision_ad_member($prefix,
1446                                           "OFFLINEADMEM",
1447                                           $dcvars,
1448                                           $trustvars_f,
1449                                           $trustvars_e,
1450                                           undef,
1451                                           1);
1452 }
1453
1454 sub setup_simpleserver
1455 {
1456         my ($self, $path) = @_;
1457
1458         print "PROVISIONING simple server...";
1459
1460         my $prefix_abs = abs_path($path);
1461
1462         my $simpleserver_options = "
1463         lanman auth = yes
1464         ntlm auth = yes
1465         vfs objects = xattr_tdb streams_depot
1466         change notify = no
1467         server smb encrypt = off
1468
1469 [vfs_aio_pthread]
1470         path = $prefix_abs/share
1471         read only = no
1472         vfs objects = aio_pthread
1473         aio_pthread:aio open = yes
1474         smbd async dosmode = no
1475
1476 [vfs_aio_pthread_async_dosmode_default1]
1477         path = $prefix_abs/share
1478         read only = no
1479         vfs objects = aio_pthread
1480         store dos attributes = yes
1481         aio_pthread:aio open = yes
1482         smbd async dosmode = yes
1483
1484 [vfs_aio_pthread_async_dosmode_default2]
1485         path = $prefix_abs/share
1486         read only = no
1487         vfs objects = aio_pthread xattr_tdb
1488         store dos attributes = yes
1489         aio_pthread:aio open = yes
1490         smbd async dosmode = yes
1491
1492 [vfs_aio_pthread_async_dosmode_force_sync1]
1493         path = $prefix_abs/share
1494         read only = no
1495         vfs objects = aio_pthread
1496         store dos attributes = yes
1497         aio_pthread:aio open = yes
1498         smbd async dosmode = yes
1499         # This simulates non linux systems
1500         smbd:force sync user path safe threadpool = yes
1501         smbd:force sync user chdir safe threadpool = yes
1502         smbd:force sync root path safe threadpool = yes
1503         smbd:force sync root chdir safe threadpool = yes
1504
1505 [vfs_aio_pthread_async_dosmode_force_sync2]
1506         path = $prefix_abs/share
1507         read only = no
1508         vfs objects = aio_pthread xattr_tdb
1509         store dos attributes = yes
1510         aio_pthread:aio open = yes
1511         smbd async dosmode = yes
1512         # This simulates non linux systems
1513         smbd:force sync user path safe threadpool = yes
1514         smbd:force sync user chdir safe threadpool = yes
1515         smbd:force sync root path safe threadpool = yes
1516         smbd:force sync root chdir safe threadpool = yes
1517
1518 [vfs_aio_fork]
1519         path = $prefix_abs/share
1520         vfs objects = aio_fork
1521         read only = no
1522         vfs_aio_fork:erratic_testing_mode=yes
1523
1524 [dosmode]
1525         path = $prefix_abs/share
1526         vfs objects =
1527         store dos attributes = yes
1528         hide files = /hidefile/
1529         hide dot files = yes
1530
1531 [hidenewfiles]
1532         path = $prefix_abs/share
1533         hide new files timeout = 5
1534 ";
1535
1536         my $vars = $self->provision(
1537             prefix => $path,
1538             domain => "WORKGROUP",
1539             server => "LOCALSHARE4",
1540             password => "local4pass",
1541             extra_options => $simpleserver_options);
1542
1543         $vars or return undef;
1544
1545         if (not $self->check_or_start(
1546                 env_vars => $vars,
1547                 nmbd => "yes",
1548                 smbd => "yes")) {
1549                return undef;
1550         }
1551
1552         return $vars;
1553 }
1554
1555 sub create_file_chmod($$)
1556 {
1557     my ($name, $mode) = @_;
1558     my $fh;
1559
1560     unless (open($fh, '>', $name)) {
1561         warn("Unable to open $name");
1562         return undef;
1563     }
1564     chmod($mode, $fh);
1565 }
1566
1567 sub setup_fileserver
1568 {
1569         my ($self, $path, $more_conf, $server) = @_;
1570         my $prefix_abs = abs_path($path);
1571         my $srcdir_abs = abs_path($self->{srcdir});
1572
1573         print "PROVISIONING file server ...\n";
1574
1575         my @dirs = ();
1576
1577         mkdir($prefix_abs, 0777);
1578
1579         my $usershare_dir="$prefix_abs/lib/usershare";
1580
1581         mkdir("$prefix_abs/lib", 0755);
1582         remove_tree($usershare_dir);
1583         mkdir($usershare_dir, 01770);
1584
1585         my $share_dir="$prefix_abs/share";
1586
1587         # Create share directory structure
1588         my $lower_case_share_dir="$share_dir/lower-case";
1589         push(@dirs, $lower_case_share_dir);
1590
1591         my $lower_case_share_dir_30000="$share_dir/lower-case-30000";
1592         push(@dirs, $lower_case_share_dir_30000);
1593
1594         my $dfree_share_dir="$share_dir/dfree";
1595         push(@dirs, $dfree_share_dir);
1596         push(@dirs, "$dfree_share_dir/subdir1");
1597         push(@dirs, "$dfree_share_dir/subdir2");
1598         push(@dirs, "$dfree_share_dir/subdir3");
1599
1600         my $quotadir_dir="$share_dir/quota";
1601         push(@dirs, $quotadir_dir);
1602
1603         my $valid_users_sharedir="$share_dir/valid_users";
1604         push(@dirs,$valid_users_sharedir);
1605
1606         my $offline_sharedir="$share_dir/offline";
1607         push(@dirs,$offline_sharedir);
1608
1609         my $force_user_valid_users_dir = "$share_dir/force_user_valid_users";
1610         push(@dirs, $force_user_valid_users_dir);
1611
1612         my $smbget_sharedir="$share_dir/smbget";
1613         push(@dirs,$smbget_sharedir);
1614
1615         my $tarmode_sharedir="$share_dir/tarmode";
1616         push(@dirs,$tarmode_sharedir);
1617
1618         my $tarmode2_sharedir="$share_dir/tarmode2";
1619         push(@dirs,$tarmode2_sharedir);
1620
1621         my $smbcacls_sharedir="$share_dir/smbcacls";
1622         push(@dirs,$smbcacls_sharedir);
1623
1624         my $usershare_sharedir="$share_dir/usershares";
1625         push(@dirs,$usershare_sharedir);
1626
1627         my $dropbox_sharedir="$share_dir/dropbox";
1628         push(@dirs,$dropbox_sharedir);
1629
1630         my $bad_iconv_sharedir="$share_dir/bad_iconv";
1631         push(@dirs, $bad_iconv_sharedir);
1632
1633         my $ip4 = Samba::get_ipv4_addr("FILESERVER");
1634         my $fileserver_options = "
1635         kernel change notify = yes
1636         rpc_server:mdssvc = embedded
1637         spotlight backend = elasticsearch
1638         elasticsearch:address = $ip4
1639         elasticsearch:port = 8080
1640         elasticsearch:mappings = $srcdir_abs/source3/rpc_server/mdssvc/elasticsearch_mappings.json
1641
1642         usershare path = $usershare_dir
1643         usershare max shares = 10
1644         usershare allow guests = yes
1645         usershare prefix allow list = $usershare_sharedir
1646
1647         get quota command = $prefix_abs/getset_quota.py
1648         set quota command = $prefix_abs/getset_quota.py
1649 [tarmode]
1650         path = $tarmode_sharedir
1651         comment = tar test share
1652         xattr_tdb:file = $prefix_abs/tarmode-xattr.tdb
1653 [tarmode2]
1654         path = $tarmode2_sharedir
1655         comment = tar test share
1656         xattr_tdb:file = $prefix_abs/tarmode2-xattr.tdb
1657 [spotlight]
1658         path = $share_dir
1659         spotlight = yes
1660         read only = no
1661 [no_spotlight]
1662         path = $share_dir
1663         spotlight = no
1664         read only = no
1665 [lowercase]
1666         path = $lower_case_share_dir
1667         comment = smb username is [%U]
1668         case sensitive = True
1669         default case = lower
1670         preserve case = no
1671         short preserve case = no
1672 [lowercase-30000]
1673         path = $lower_case_share_dir_30000
1674         comment = smb username is [%U]
1675         case sensitive = True
1676         default case = lower
1677         preserve case = no
1678         short preserve case = no
1679 [dfree]
1680         path = $dfree_share_dir
1681         comment = smb username is [%U]
1682         dfree command = $srcdir_abs/testprogs/blackbox/dfree.sh
1683 [valid-users-access]
1684         path = $valid_users_sharedir
1685         valid users = +userdup
1686 [offline]
1687         path = $offline_sharedir
1688         vfs objects = offline
1689
1690 # BUG: https://bugzilla.samba.org/show_bug.cgi?id=9878
1691 # RH BUG: https://bugzilla.redhat.com/show_bug.cgi?id=1077651
1692 [force_user_valid_users]
1693         path = $force_user_valid_users_dir
1694         comment = force user with valid users combination test share
1695         valid users = +force_user
1696         force user = force_user
1697         force group = everyone
1698         write list = force_user
1699
1700 [smbget]
1701         path = $smbget_sharedir
1702         comment = smb username is [%U]
1703         guest ok = yes
1704 [ign_sysacls]
1705         path = $share_dir
1706         comment = ignore system acls
1707         acl_xattr:ignore system acls = yes
1708 [inherit_owner]
1709         path = $share_dir
1710         comment = inherit owner
1711         inherit owner = yes
1712 [inherit_owner_u]
1713         path = $share_dir
1714         comment = inherit only unix owner
1715         inherit owner = unix only
1716         acl_xattr:ignore system acls = yes
1717 # BUG: https://bugzilla.samba.org/show_bug.cgi?id=13690
1718 [force_group_test]
1719         path = $share_dir
1720         comment = force group test
1721 #       force group = everyone
1722
1723 [create_mode_664]
1724         path = $share_dir
1725         comment = smb username is [%U]
1726         create mask = 0644
1727         force create mode = 0664
1728         vfs objects = dirsort
1729
1730 [dropbox]
1731         path = $dropbox_sharedir
1732         comment = smb username is [%U]
1733         writeable = yes
1734         vfs objects =
1735
1736 [bad_iconv]
1737         path = $bad_iconv_sharedir
1738         comment = smb username is [%U]
1739         vfs objects =
1740
1741 [homes]
1742         comment = Home directories
1743         browseable = No
1744         read only = No
1745 ";
1746
1747         if (defined($more_conf)) {
1748                 $fileserver_options = $fileserver_options . $more_conf;
1749         }
1750         if (!defined($server)) {
1751                 $server = "FILESERVER";
1752         }
1753
1754         my $vars = $self->provision(
1755             prefix => $path,
1756             domain => "WORKGROUP",
1757             server => $server,
1758             password => "fileserver",
1759             extra_options => $fileserver_options,
1760             no_delete_prefix => 1);
1761
1762         $vars or return undef;
1763
1764         if (not $self->check_or_start(
1765                 env_vars => $vars,
1766                 nmbd => "yes",
1767                 smbd => "yes")) {
1768                return undef;
1769         }
1770
1771
1772         mkdir($_, 0777) foreach(@dirs);
1773
1774         ## Create case sensitive lower case share dir
1775         foreach my $file ('a'..'z') {
1776                 my $full_path = $lower_case_share_dir . '/' . $file;
1777                 open my $fh, '>', $full_path;
1778                 # Add some content to file
1779                 print $fh $full_path;
1780                 close $fh;
1781         }
1782
1783         for (my $file = 1; $file < 51; ++$file) {
1784                 my $full_path = $lower_case_share_dir . '/' . $file;
1785                 open my $fh, '>', $full_path;
1786                 # Add some content to file
1787                 print $fh $full_path;
1788                 close $fh;
1789         }
1790
1791         # Create content for 30000 share
1792         foreach my $file ('a'..'z') {
1793                 my $full_path = $lower_case_share_dir_30000 . '/' . $file;
1794                 open my $fh, '>', $full_path;
1795                 # Add some content to file
1796                 print $fh $full_path;
1797                 close $fh;
1798         }
1799
1800         for (my $file = 1; $file < 30001; ++$file) {
1801                 my $full_path = $lower_case_share_dir_30000 . '/' . $file;
1802                 open my $fh, '>', $full_path;
1803                 # Add some content to file
1804                 print $fh $full_path;
1805                 close $fh;
1806         }
1807
1808         ##
1809         ## create a listable file in valid_users_share
1810         ##
1811         create_file_chmod("$valid_users_sharedir/foo", 0644) or return undef;
1812
1813         ##
1814         ## create a valid utf8 filename which is invalid as a CP850 conversion
1815         ##
1816         create_file_chmod("$bad_iconv_sharedir/\xED\x9F\xBF", 0644) or return undef;
1817
1818         return $vars;
1819 }
1820
1821 sub setup_fileserver_smb1
1822 {
1823         my ($self, $path) = @_;
1824         my $prefix_abs = abs_path($path);
1825         my $conf = "
1826 [global]
1827         client min protocol = CORE
1828         server min protocol = LANMAN1
1829
1830 [hidenewfiles]
1831         path = $prefix_abs/share
1832         hide new files timeout = 5
1833 [vfs_aio_pthread]
1834         path = $prefix_abs/share
1835         read only = no
1836         vfs objects = aio_pthread
1837         aio_pthread:aio open = yes
1838         smbd async dosmode = no
1839
1840 [vfs_aio_pthread_async_dosmode_default1]
1841         path = $prefix_abs/share
1842         read only = no
1843         vfs objects = aio_pthread
1844         store dos attributes = yes
1845         aio_pthread:aio open = yes
1846         smbd async dosmode = yes
1847
1848 [vfs_aio_pthread_async_dosmode_default2]
1849         path = $prefix_abs/share
1850         read only = no
1851         vfs objects = aio_pthread xattr_tdb
1852         store dos attributes = yes
1853         aio_pthread:aio open = yes
1854         smbd async dosmode = yes
1855
1856 [vfs_aio_pthread_async_dosmode_force_sync1]
1857         path = $prefix_abs/share
1858         read only = no
1859         vfs objects = aio_pthread
1860         store dos attributes = yes
1861         aio_pthread:aio open = yes
1862         smbd async dosmode = yes
1863         # This simulates non linux systems
1864         smbd:force sync user path safe threadpool = yes
1865         smbd:force sync user chdir safe threadpool = yes
1866         smbd:force sync root path safe threadpool = yes
1867         smbd:force sync root chdir safe threadpool = yes
1868
1869 [vfs_aio_pthread_async_dosmode_force_sync2]
1870         path = $prefix_abs/share
1871         read only = no
1872         vfs objects = aio_pthread xattr_tdb
1873         store dos attributes = yes
1874         aio_pthread:aio open = yes
1875         smbd async dosmode = yes
1876         # This simulates non linux systems
1877         smbd:force sync user path safe threadpool = yes
1878         smbd:force sync user chdir safe threadpool = yes
1879         smbd:force sync root path safe threadpool = yes
1880         smbd:force sync root chdir safe threadpool = yes
1881
1882 [vfs_aio_fork]
1883         path = $prefix_abs/share
1884         vfs objects = aio_fork
1885         read only = no
1886         vfs_aio_fork:erratic_testing_mode=yes
1887 ";
1888         return $self->setup_fileserver($path, $conf, "FILESERVERSMB1");
1889 }
1890
1891 sub setup_fileserver_smb1_done
1892 {
1893         my ($self, $path, $dep_env) = @_;
1894         return $self->return_alias_env($path, $dep_env);
1895 }
1896
1897 sub setup_ktest
1898 {
1899         my ($self, $prefix) = @_;
1900
1901         # If we didn't build with ADS, pretend this env was never available
1902         if (not $self->have_ads()) {
1903                 return "UNKNOWN";
1904         }
1905
1906         print "PROVISIONING server with security=ads...";
1907
1908         my $ktest_options = "
1909         workgroup = KTEST
1910         realm = ktest.samba.example.com
1911         security = ads
1912         username map = $prefix/lib/username.map
1913         server signing = required
1914         server min protocol = SMB3_00
1915         client max protocol = SMB3
1916
1917         # This disables NTLM auth against the local SAM, which
1918         # we use can then test this setting by.
1919         ntlm auth = disabled
1920 ";
1921
1922         my $ret = $self->provision(
1923             prefix => $prefix,
1924             domain => "KTEST",
1925             server => "LOCALKTEST6",
1926             password => "localktest6pass",
1927             extra_options => $ktest_options);
1928
1929         $ret or return undef;
1930
1931         my $ctx;
1932         my $prefix_abs = abs_path($prefix);
1933         $ctx = {};
1934         $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
1935         $ctx->{domain} = "KTEST";
1936         $ctx->{realm} = "KTEST.SAMBA.EXAMPLE.COM";
1937         $ctx->{dnsname} = lc($ctx->{realm});
1938         $ctx->{kdc_ipv4} = "0.0.0.0";
1939         $ctx->{kdc_ipv6} = "::";
1940         $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
1941         Samba::mk_krb5_conf($ctx, "");
1942
1943         $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
1944
1945         open(USERMAP, ">$prefix/lib/username.map") or die("Unable to open $prefix/lib/username.map");
1946         print USERMAP "
1947 $ret->{USERNAME} = KTEST\\Administrator
1948 ";
1949         close(USERMAP);
1950
1951 #This is the secrets.tdb created by 'net ads join' from Samba3 to a
1952 #Samba4 DC with the same parameters as are being used here.  The
1953 #domain SID is S-1-5-21-1071277805-689288055-3486227160
1954         $ret->{SAMSID} = "S-1-5-21-1911091480-1468226576-2729736297";
1955         $ret->{DOMSID} = "S-1-5-21-1071277805-689288055-3486227160";
1956
1957         system("cp $self->{srcdir}/source3/selftest/ktest-secrets.tdb $prefix/private/secrets.tdb");
1958         chmod 0600, "$prefix/private/secrets.tdb";
1959
1960 #Make sure there's no old ntdb file.
1961         system("rm -f $prefix/private/secrets.ntdb");
1962
1963 #This uses a pre-calculated krb5 credentials cache, obtained by running Samba4 with:
1964 # "--option=kdc:service ticket lifetime=239232" "--option=kdc:user ticket lifetime=239232" "--option=kdc:renewal lifetime=239232"
1965 #
1966 #and having in krb5.conf:
1967 # ticket_lifetime = 799718400
1968 # renew_lifetime = 799718400
1969 #
1970 # The commands for the -2 keytab where were:
1971 # kinit administrator@KTEST.SAMBA.EXAMPLE.COM
1972 # kvno host/localktest6@KTEST.SAMBA.EXAMPLE.COM
1973 # kvno cifs/localktest6@KTEST.SAMBA.EXAMPLE.COM
1974 # kvno host/LOCALKTEST6@KTEST.SAMBA.EXAMPLE.COM
1975 # kvno cifs/LOCALKTEST6@KTEST.SAMBA.EXAMPLE.COM
1976 #
1977 # and then for the -3 keytab, I did
1978 #
1979 # net changetrustpw; kdestroy and the same again.
1980 #
1981 # This creates a credential cache with a very long lifetime (2036 at
1982 # at 2011-04), and shows that running 'net changetrustpw' does not
1983 # break existing logins (for the secrets.tdb method at least).
1984 #
1985
1986         $ret->{KRB5_CCACHE}="FILE:$prefix/krb5_ccache";
1987
1988         system("cp $self->{srcdir}/source3/selftest/ktest-krb5_ccache-2 $prefix/krb5_ccache-2");
1989         chmod 0600, "$prefix/krb5_ccache-2";
1990
1991         system("cp $self->{srcdir}/source3/selftest/ktest-krb5_ccache-3 $prefix/krb5_ccache-3");
1992         chmod 0600, "$prefix/krb5_ccache-3";
1993
1994         # We need world access to this share, as otherwise the domain
1995         # administrator from the AD domain provided by ktest can't
1996         # access the share for tests.
1997         chmod 0777, "$prefix/share";
1998
1999         if (not $self->check_or_start(
2000                 env_vars => $ret,
2001                 nmbd => "yes",
2002                 smbd => "yes")) {
2003                return undef;
2004         }
2005         return $ret;
2006 }
2007
2008 sub setup_maptoguest
2009 {
2010         my ($self, $path) = @_;
2011         my $prefix_abs = abs_path($path);
2012         my $libdir="$prefix_abs/lib";
2013         my $share_dir="$prefix_abs/share";
2014         my $errorinjectconf="$libdir/error_inject.conf";
2015
2016         print "PROVISIONING maptoguest...";
2017
2018         my $options = "
2019 map to guest = bad user
2020 ntlm auth = yes
2021
2022 [force_user_error_inject]
2023         path = $share_dir
2024         vfs objects = acl_xattr fake_acls xattr_tdb error_inject
2025         force user = user1
2026         include = $errorinjectconf
2027 ";
2028
2029         my $vars = $self->provision(
2030             prefix => $path,
2031             domain => "WORKGROUP",
2032             server => "maptoguest",
2033             password => "maptoguestpass",
2034             extra_options => $options);
2035
2036         $vars or return undef;
2037
2038         if (not $self->check_or_start(
2039                 env_vars => $vars,
2040                 nmbd => "yes",
2041                 smbd => "yes")) {
2042                return undef;
2043         }
2044
2045         return $vars;
2046 }
2047
2048 sub stop_sig_term($$) {
2049         my ($self, $pid) = @_;
2050         kill("USR1", $pid) or kill("ALRM", $pid) or warn("Unable to kill $pid: $!");
2051 }
2052
2053 sub stop_sig_kill($$) {
2054         my ($self, $pid) = @_;
2055         kill("ALRM", $pid) or warn("Unable to kill $pid: $!");
2056 }
2057
2058 sub write_pid($$$)
2059 {
2060         my ($env_vars, $app, $pid) = @_;
2061
2062         open(PID, ">$env_vars->{PIDDIR}/timelimit.$app.pid");
2063         print PID $pid;
2064         close(PID);
2065 }
2066
2067 sub read_pid($$)
2068 {
2069         my ($env_vars, $app) = @_;
2070
2071         open(PID, "<$env_vars->{PIDDIR}/timelimit.$app.pid");
2072         my $pid = <PID>;
2073         close(PID);
2074         return $pid;
2075 }
2076
2077 # builds up the cmd args to run an s3 binary (i.e. smbd, nmbd, etc)
2078 sub make_bin_cmd
2079 {
2080         my ($self, $binary, $env_vars, $options, $valgrind, $dont_log_stdout) = @_;
2081
2082         my @optargs = ("-d0");
2083         if (defined($options)) {
2084                 @optargs = split(/ /, $options);
2085         }
2086         my @preargs = (Samba::bindir_path($self, "timelimit"), $self->{server_maxtime});
2087
2088         if (defined($valgrind)) {
2089                 @preargs = split(/ /, $valgrind);
2090         }
2091         my @args = ("-F", "--no-process-group",
2092                     "--configfile=$env_vars->{SERVERCONFFILE}",
2093                     "-l", $env_vars->{LOGDIR});
2094
2095         if (not defined($dont_log_stdout)) {
2096                 push(@args, "--debug-stdout");
2097         }
2098         return (@preargs, $binary, @args, @optargs);
2099 }
2100
2101 sub check_or_start($$) {
2102         my ($self, %args) = @_;
2103         my $env_vars = $args{env_vars};
2104         my $nmbd = $args{nmbd} // "no";
2105         my $winbindd = $args{winbindd} // "no";
2106         my $smbd = $args{smbd} // "no";
2107         my $child_cleanup = $args{child_cleanup};
2108         my $skip_wait = $args{skip_wait} // 0;
2109
2110         my $STDIN_READER;
2111
2112         # use a pipe for stdin in the child processes. This allows
2113         # those processes to monitor the pipe for EOF to ensure they
2114         # exit when the test script exits
2115         pipe($STDIN_READER, $env_vars->{STDIN_PIPE});
2116
2117         my $binary = Samba::bindir_path($self, "nmbd");
2118         my @full_cmd = $self->make_bin_cmd($binary, $env_vars,
2119                                            $ENV{NMBD_OPTIONS}, $ENV{NMBD_VALGRIND},
2120                                            $ENV{NMBD_DONT_LOG_STDOUT});
2121         my $nmbd_envs = Samba::get_env_for_process("nmbd", $env_vars);
2122         delete $nmbd_envs->{RESOLV_WRAPPER_CONF};
2123         delete $nmbd_envs->{RESOLV_WRAPPER_HOSTS};
2124
2125         # fork and exec() nmbd in the child process
2126         my $daemon_ctx = {
2127                 NAME => "nmbd",
2128                 BINARY_PATH => $binary,
2129                 FULL_CMD => [ @full_cmd ],
2130                 LOG_FILE => $env_vars->{NMBD_TEST_LOG},
2131                 PCAP_FILE => "env-$ENV{ENVNAME}-nmbd",
2132                 ENV_VARS => $nmbd_envs,
2133         };
2134         if ($nmbd ne "yes") {
2135                 $daemon_ctx->{SKIP_DAEMON} = 1;
2136         }
2137         my $pid = Samba::fork_and_exec(
2138             $self, $env_vars, $daemon_ctx, $STDIN_READER, $child_cleanup);
2139
2140         $env_vars->{NMBD_TL_PID} = $pid;
2141         write_pid($env_vars, "nmbd", $pid);
2142
2143         $binary = Samba::bindir_path($self, "winbindd");
2144         @full_cmd = $self->make_bin_cmd($binary, $env_vars,
2145                                          $ENV{WINBINDD_OPTIONS},
2146                                          $ENV{WINBINDD_VALGRIND},
2147                                          $ENV{WINBINDD_DONT_LOG_STDOUT});
2148
2149         # fork and exec() winbindd in the child process
2150         $daemon_ctx = {
2151                 NAME => "winbindd",
2152                 BINARY_PATH => $binary,
2153                 FULL_CMD => [ @full_cmd ],
2154                 LOG_FILE => $env_vars->{WINBINDD_TEST_LOG},
2155                 PCAP_FILE => "env-$ENV{ENVNAME}-winbindd",
2156         };
2157         if ($winbindd ne "yes") {
2158                 $daemon_ctx->{SKIP_DAEMON} = 1;
2159         }
2160
2161         $pid = Samba::fork_and_exec(
2162             $self, $env_vars, $daemon_ctx, $STDIN_READER, $child_cleanup);
2163
2164         $env_vars->{WINBINDD_TL_PID} = $pid;
2165         write_pid($env_vars, "winbindd", $pid);
2166
2167         $binary = Samba::bindir_path($self, "smbd");
2168         @full_cmd = $self->make_bin_cmd($binary, $env_vars,
2169                                          $ENV{SMBD_OPTIONS}, $ENV{SMBD_VALGRIND},
2170                                          $ENV{SMBD_DONT_LOG_STDOUT});
2171
2172         # fork and exec() smbd in the child process
2173         $daemon_ctx = {
2174                 NAME => "smbd",
2175                 BINARY_PATH => $binary,
2176                 FULL_CMD => [ @full_cmd ],
2177                 LOG_FILE => $env_vars->{SMBD_TEST_LOG},
2178                 PCAP_FILE => "env-$ENV{ENVNAME}-smbd",
2179         };
2180         if ($smbd ne "yes") {
2181                 $daemon_ctx->{SKIP_DAEMON} = 1;
2182         }
2183
2184         $pid = Samba::fork_and_exec(
2185             $self, $env_vars, $daemon_ctx, $STDIN_READER, $child_cleanup);
2186
2187         $env_vars->{SMBD_TL_PID} = $pid;
2188         write_pid($env_vars, "smbd", $pid);
2189
2190         # close the parent's read-end of the pipe
2191         close($STDIN_READER);
2192
2193         if ($skip_wait) {
2194                 return 1;
2195         }
2196
2197         return $self->wait_for_start($env_vars, $nmbd, $winbindd, $smbd);
2198 }
2199
2200 sub createuser($$$$$)
2201 {
2202         my ($self, $username, $password, $conffile, $env) = @_;
2203         my $cmd = "UID_WRAPPER_ROOT=1 " . Samba::bindir_path($self, "smbpasswd")." -c $conffile -L -s -a $username > /dev/null";
2204
2205         keys %$env;
2206         while(my($var, $val) = each %$env) {
2207                 $cmd = "$var=\"$val\" $cmd";
2208         }
2209
2210         unless (open(PWD, "|$cmd")) {
2211             warn("Unable to set password for $username account\n$cmd");
2212             return undef;
2213         }
2214         print PWD "$password\n$password\n";
2215         unless (close(PWD)) {
2216             warn("Unable to set password for $username account\n$cmd");
2217             return undef;
2218         }
2219 }
2220
2221 sub provision($$)
2222 {
2223         my ($self, %args) = @_;
2224
2225         my $prefix = $args{prefix};
2226         my $domain = $args{domain};
2227         my $realm = $args{realm};
2228         my $server = $args{server};
2229         my $password = $args{password};
2230         my $extra_options = $args{extra_options};
2231         my $resolv_conf = $args{resolv_conf};
2232         my $no_delete_prefix= $args{no_delete_prefix};
2233         my $netbios_name = $args{netbios_name} // $server;
2234         my $server_log_level = $ENV{SERVER_LOG_LEVEL} || 1;
2235
2236         ##
2237         ## setup the various environment variables we need
2238         ##
2239
2240         my $samsid = Samba::random_domain_sid();
2241         my $swiface = Samba::get_interface($server);
2242         my %ret = ();
2243         my %createuser_env = ();
2244         my $server_ip = Samba::get_ipv4_addr($server);
2245         my $server_ipv6 = Samba::get_ipv6_addr($server);
2246         my $dns_domain;
2247         if (defined($realm)) {
2248             $dns_domain = lc($realm);
2249         } else {
2250             $dns_domain = "samba.example.com";
2251         }
2252
2253         my $unix_name = ($ENV{USER} or $ENV{LOGNAME} or `PATH=/usr/ucb:$ENV{PATH} whoami`);
2254         chomp $unix_name;
2255         my $unix_uid = $>;
2256         my $unix_gids_str = $);
2257         my @unix_gids = split(" ", $unix_gids_str);
2258
2259         my $prefix_abs = abs_path($prefix);
2260         my $bindir_abs = abs_path($self->{bindir});
2261
2262         my @dirs = ();
2263
2264         my $shrdir=$args{share_dir} // "$prefix_abs/share";
2265         push(@dirs,$shrdir);
2266
2267         my $libdir="$prefix_abs/lib";
2268         push(@dirs,$libdir);
2269
2270         my $piddir="$prefix_abs/pid";
2271         push(@dirs,$piddir);
2272
2273         my $privatedir="$prefix_abs/private";
2274         push(@dirs,$privatedir);
2275
2276         my $cachedir = "$prefix_abs/cachedir";
2277         push(@dirs, $cachedir);
2278
2279         my $binddnsdir = "$prefix_abs/bind-dns";
2280         push(@dirs, $binddnsdir);
2281
2282         my $lockdir="$prefix_abs/lockdir";
2283         push(@dirs,$lockdir);
2284
2285         my $eventlogdir="$prefix_abs/lockdir/eventlog";
2286         push(@dirs,$eventlogdir);
2287
2288         my $logdir="$prefix_abs/logs";
2289         push(@dirs,$logdir);
2290
2291         my $driver32dir="$shrdir/W32X86";
2292         push(@dirs,$driver32dir);
2293
2294         my $driver64dir="$shrdir/x64";
2295         push(@dirs,$driver64dir);
2296
2297         my $driver40dir="$shrdir/WIN40";
2298         push(@dirs,$driver40dir);
2299
2300         my $ro_shrdir="$shrdir/root-tmp";
2301         push(@dirs,$ro_shrdir);
2302
2303         my $noperm_shrdir="$shrdir/noperm-tmp";
2304         push(@dirs,$noperm_shrdir);
2305
2306         my $msdfs_shrdir="$shrdir/msdfsshare";
2307         push(@dirs,$msdfs_shrdir);
2308
2309         my $msdfs_deeppath="$msdfs_shrdir/deeppath";
2310         push(@dirs,$msdfs_deeppath);
2311
2312         my $smbcacls_sharedir_dfs="$shrdir/smbcacls_sharedir_dfs";
2313         push(@dirs,$smbcacls_sharedir_dfs);
2314
2315         my $smbcacls_share="$shrdir/smbcacls_share";
2316         push(@dirs,$smbcacls_share);
2317
2318         my $smbcacls_share_testdir="$shrdir/smbcacls_share/smbcacls";
2319         push(@dirs,$smbcacls_share_testdir);
2320
2321         my $badnames_shrdir="$shrdir/badnames";
2322         push(@dirs,$badnames_shrdir);
2323
2324         my $lease1_shrdir="$shrdir/dynamic";
2325         push(@dirs,$lease1_shrdir);
2326
2327         my $manglenames_shrdir="$shrdir/manglenames";
2328         push(@dirs,$manglenames_shrdir);
2329
2330         my $widelinks_shrdir="$shrdir/widelinks";
2331         push(@dirs,$widelinks_shrdir);
2332
2333         my $widelinks_linkdir="$shrdir/widelinks_foo";
2334         push(@dirs,$widelinks_linkdir);
2335
2336         my $fsrvp_shrdir="$shrdir/fsrvp";
2337         push(@dirs,$fsrvp_shrdir);
2338
2339         my $shadow_tstdir="$shrdir/shadow";
2340         push(@dirs,$shadow_tstdir);
2341         my $shadow_mntdir="$shadow_tstdir/mount";
2342         push(@dirs,$shadow_mntdir);
2343         my $shadow_basedir="$shadow_mntdir/base";
2344         push(@dirs,$shadow_basedir);
2345         my $shadow_shrdir="$shadow_basedir/share";
2346         push(@dirs,$shadow_shrdir);
2347
2348         my $nosymlinks_shrdir="$shrdir/nosymlinks";
2349         push(@dirs,$nosymlinks_shrdir);
2350
2351         my $local_symlinks_shrdir="$shrdir/local_symlinks";
2352         push(@dirs,$local_symlinks_shrdir);
2353
2354         # this gets autocreated by winbindd
2355         my $wbsockdir="$prefix_abs/wbsock";
2356
2357         my $nmbdsockdir="$prefix_abs/nmbd";
2358         unlink($nmbdsockdir);
2359
2360         ## 
2361         ## create the test directory layout
2362         ##
2363         die ("prefix_abs = ''") if $prefix_abs eq "";
2364         die ("prefix_abs = '/'") if $prefix_abs eq "/";
2365
2366         mkdir($prefix_abs, 0777);
2367         print "CREATE TEST ENVIRONMENT IN '$prefix'...";
2368         if (not defined($no_delete_prefix) or not $no_delete_prefix) {
2369             system("rm -rf $prefix_abs/*");
2370         }
2371         mkdir($_, 0777) foreach(@dirs);
2372
2373         my $fs_specific_conf = $self->get_fs_specific_conf($shrdir);
2374
2375         ##
2376         ## lockdir and piddir must be 0755
2377         ##
2378         chmod 0755, $lockdir;
2379         chmod 0755, $piddir;
2380
2381
2382         ##
2383         ## Create a directory without permissions to enter
2384         ##
2385         chmod 0000, $noperm_shrdir;
2386
2387         ##
2388         ## create ro and msdfs share layout
2389         ##
2390
2391         chmod 0755, $ro_shrdir;
2392
2393         create_file_chmod("$ro_shrdir/unreadable_file", 0600) or return undef;
2394
2395         create_file_chmod("$ro_shrdir/msdfs-target", 0600) or return undef;
2396         symlink "msdfs:$server_ip\\ro-tmp,$server_ipv6\\ro-tmp",
2397                 "$msdfs_shrdir/msdfs-src1";
2398         symlink "msdfs:$server_ipv6\\ro-tmp", "$msdfs_shrdir/deeppath/msdfs-src2";
2399         symlink "msdfs:$server_ip\\smbcacls_sharedir_dfs,$server_ipv6\\smbcacls_sharedir_dfs",
2400                 "$msdfs_shrdir/smbcacls_sharedir_dfs";
2401
2402         ##
2403         ## create bad names in $badnames_shrdir
2404         ##
2405         ## (An invalid name, would be mangled to 8.3).
2406         create_file_chmod("$badnames_shrdir/\340|\231\216\377\177",
2407                           0600) or return undef;
2408
2409         ## (A bad name, would not be mangled to 8.3).
2410         create_file_chmod("$badnames_shrdir/\240\276\346\327\377\177",
2411                           0666) or return undef;
2412
2413         ## (A bad good name).
2414         create_file_chmod("$badnames_shrdir/blank.txt",
2415                           0666) or return undef;
2416
2417         ##
2418         ## create mangleable directory names in $manglenames_shrdir
2419         ##
2420         my $manglename_target = "$manglenames_shrdir/foo:bar";
2421         mkdir($manglename_target, 0777);
2422
2423         ##
2424         ## create symlinks for widelinks tests.
2425         ##
2426         my $widelinks_target = "$widelinks_linkdir/target";
2427         create_file_chmod("$widelinks_target", 0666) or return undef;
2428
2429         ##
2430         ## This link should get ACCESS_DENIED
2431         ##
2432         symlink "$widelinks_target", "$widelinks_shrdir/source";
2433         ##
2434         ## This link should be allowed
2435         ##
2436         symlink "$widelinks_shrdir", "$widelinks_shrdir/dot";
2437
2438         my $conffile="$libdir/server.conf";
2439         my $dfqconffile="$libdir/dfq.conf";
2440         my $errorinjectconf="$libdir/error_inject.conf";
2441         my $delayinjectconf="$libdir/delay_inject.conf";
2442         my $globalinjectconf="$libdir/global_inject.conf";
2443
2444         my $nss_wrapper_pl = "$ENV{PERL} $self->{srcdir}/third_party/nss_wrapper/nss_wrapper.pl";
2445         my $nss_wrapper_passwd = "$privatedir/passwd";
2446         my $nss_wrapper_group = "$privatedir/group";
2447         my $nss_wrapper_hosts = "$ENV{SELFTEST_PREFIX}/hosts";
2448         my $dns_host_file = "$ENV{SELFTEST_PREFIX}/dns_host_file";
2449
2450         my $mod_printer_pl = "$ENV{PERL} $self->{srcdir}/source3/script/tests/printing/modprinter.pl";
2451
2452         my $fake_snap_pl = "$ENV{PERL} $self->{srcdir}/source3/script/tests/fake_snap.pl";
2453
2454         my @eventlog_list = ("dns server", "application");
2455
2456         ##
2457         ## calculate uids and gids
2458         ##
2459
2460         my ($max_uid, $max_gid);
2461         my ($uid_nobody, $uid_root, $uid_pdbtest, $uid_pdbtest2, $uid_userdup);
2462         my ($uid_pdbtest_wkn);
2463         my ($uid_smbget);
2464         my ($uid_force_user);
2465         my ($gid_nobody, $gid_nogroup, $gid_root, $gid_domusers, $gid_domadmins);
2466         my ($gid_userdup, $gid_everyone);
2467         my ($gid_force_user);
2468         my ($uid_user1);
2469         my ($uid_user2);
2470         my ($uid_gooduser);
2471         my ($uid_eviluser);
2472         my ($uid_slashuser);
2473
2474         if ($unix_uid < 0xffff - 13) {
2475                 $max_uid = 0xffff;
2476         } else {
2477                 $max_uid = $unix_uid;
2478         }
2479
2480         $uid_root = $max_uid - 1;
2481         $uid_nobody = $max_uid - 2;
2482         $uid_pdbtest = $max_uid - 3;
2483         $uid_pdbtest2 = $max_uid - 4;
2484         $uid_userdup = $max_uid - 5;
2485         $uid_pdbtest_wkn = $max_uid - 6;
2486         $uid_force_user = $max_uid - 7;
2487         $uid_smbget = $max_uid - 8;
2488         $uid_user1 = $max_uid - 9;
2489         $uid_user2 = $max_uid - 10;
2490         $uid_gooduser = $max_uid - 11;
2491         $uid_eviluser = $max_uid - 12;
2492         $uid_slashuser = $max_uid - 13;
2493
2494         if ($unix_gids[0] < 0xffff - 8) {
2495                 $max_gid = 0xffff;
2496         } else {
2497                 $max_gid = $unix_gids[0];
2498         }
2499
2500         $gid_nobody = $max_gid - 1;
2501         $gid_nogroup = $max_gid - 2;
2502         $gid_root = $max_gid - 3;
2503         $gid_domusers = $max_gid - 4;
2504         $gid_domadmins = $max_gid - 5;
2505         $gid_userdup = $max_gid - 6;
2506         $gid_everyone = $max_gid - 7;
2507         $gid_force_user = $max_gid - 8;
2508
2509         ##
2510         ## create conffile
2511         ##
2512
2513         unless (open(CONF, ">$conffile")) {
2514                 warn("Unable to open $conffile");
2515                 return undef;
2516         }
2517
2518         my $interfaces = Samba::get_interfaces_config($server);
2519
2520         print CONF "
2521 [global]
2522         dcesrv:fuzz directory = $cachedir/fuzz
2523         netbios name = $netbios_name
2524         interfaces = $interfaces
2525         bind interfaces only = yes
2526         panic action = cd $self->{srcdir} && $self->{srcdir}/selftest/gdb_backtrace %d %\$(MAKE_TEST_BINARY)
2527         smbd:suicide mode = yes
2528         smbd:FSCTL_SMBTORTURE = yes
2529
2530         client min protocol = SMB2_02
2531         server min protocol = SMB2_02
2532
2533         server multi channel support = yes
2534
2535         workgroup = $domain
2536
2537         private dir = $privatedir
2538         binddns dir = $binddnsdir
2539         pid directory = $piddir
2540         lock directory = $lockdir
2541         log file = $logdir/log.\%m
2542         log level = $server_log_level
2543         debug pid = yes
2544         max log size = 0
2545
2546         state directory = $lockdir
2547         cache directory = $lockdir
2548
2549         passdb backend = tdbsam
2550
2551         time server = yes
2552
2553         add user script =               $nss_wrapper_pl --passwd_path $nss_wrapper_passwd --type passwd --action add --name %u --gid $gid_nogroup
2554         add group script =              $nss_wrapper_pl --group_path  $nss_wrapper_group  --type group  --action add --name %g
2555         add machine script =            $nss_wrapper_pl --passwd_path $nss_wrapper_passwd --type passwd --action add --name %u --gid $gid_nogroup
2556         add user to group script =      $nss_wrapper_pl --passwd_path $nss_wrapper_passwd --type member --action add --member %u --name %g --group_path $nss_wrapper_group
2557         delete user script =            $nss_wrapper_pl --passwd_path $nss_wrapper_passwd --type passwd --action delete --name %u
2558         delete group script =           $nss_wrapper_pl --group_path  $nss_wrapper_group  --type group  --action delete --name %g
2559         delete user from group script = $nss_wrapper_pl --passwd_path $nss_wrapper_passwd --type member --action delete --member %u --name %g --group_path $nss_wrapper_group
2560
2561         addprinter command =            $mod_printer_pl -a -s $conffile --
2562         deleteprinter command =         $mod_printer_pl -d -s $conffile --
2563
2564         eventlog list = application \"dns server\"
2565
2566         kernel oplocks = no
2567         kernel change notify = no
2568
2569         logging = file
2570         printing = bsd
2571         printcap name = /dev/null
2572
2573         winbindd socket directory = $wbsockdir
2574         nmbd:socket dir = $nmbdsockdir
2575         idmap config * : range = 100000-200000
2576         winbind enum users = yes
2577         winbind enum groups = yes
2578         winbind separator = /
2579         include system krb5 conf = no
2580
2581 #       min receivefile size = 4000
2582
2583         read only = no
2584
2585         smbd:sharedelay = 100000
2586         smbd:writetimeupdatedelay = 500000
2587         map hidden = no
2588         map system = no
2589         map readonly = no
2590         store dos attributes = yes
2591         create mask = 755
2592         dos filemode = yes
2593         strict rename = yes
2594         strict sync = yes
2595         mangled names = yes
2596         vfs objects = acl_xattr fake_acls xattr_tdb streams_depot time_audit full_audit
2597
2598         full_audit:syslog = no
2599         full_audit:success = none
2600         full_audit:failure = none
2601
2602         printing = vlp
2603         print command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb print %p %s
2604         lpq command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpq %p
2605         lp rm command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lprm %p %j
2606         lp pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lppause %p %j
2607         lp resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpresume %p %j
2608         queue pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queuepause %p
2609         queue resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queueresume %p
2610         lpq cache time = 0
2611         print notify backchannel = yes
2612
2613         ncalrpc dir = $prefix_abs/ncalrpc
2614
2615         # The samba3.blackbox.smbclient_s3 test uses this to test that
2616         # sending messages works, and that the %m sub works.
2617         message command = mv %s $shrdir/message.%m
2618
2619         # fsrvp server requires registry shares
2620         registry shares = yes
2621
2622         # Used by RPC SRVSVC tests
2623         add share command = $bindir_abs/smbaddshare
2624         change share command = $bindir_abs/smbchangeshare
2625         delete share command = $bindir_abs/smbdeleteshare
2626
2627         # fruit:copyfile is a global option
2628         fruit:copyfile = yes
2629
2630         #this does not mean that we use non-secure test env,
2631         #it just means we ALLOW one to be configured.
2632         allow insecure wide links = yes
2633
2634         include = $globalinjectconf
2635
2636         # Begin extra options
2637         $extra_options
2638         # End extra options
2639
2640         #Include user defined custom parameters if set
2641 ";
2642
2643         if (defined($ENV{INCLUDE_CUSTOM_CONF})) {
2644                 print CONF "\t$ENV{INCLUDE_CUSTOM_CONF}\n";
2645         }
2646
2647         print CONF "
2648 [smbcacls_share]
2649         path = $smbcacls_share
2650         comment = smb username is [%U]
2651         msdfs root = yes
2652
2653 [smbcacls_sharedir_dfs]
2654         path = $smbcacls_sharedir_dfs
2655         comment = smb username is [%U]
2656 [tmp]
2657         path = $shrdir
2658         comment = smb username is [%U]
2659 [tmpsort]
2660         path = $shrdir
2661         comment = Load dirsort module
2662         vfs objects = dirsort acl_xattr fake_acls xattr_tdb streams_depot
2663 [tmpenc]
2664         path = $shrdir
2665         comment = encrypt smb username is [%U]
2666         server smb encrypt = required
2667         vfs objects = dirsort
2668 [tmpguest]
2669         path = $shrdir
2670         guest ok = yes
2671 [guestonly]
2672         path = $shrdir
2673         guest only = yes
2674         guest ok = yes
2675 [forceuser]
2676         path = $shrdir
2677         force user = $unix_name
2678         guest ok = yes
2679 [forceuser_unixonly]
2680         comment = force a user with unix user SID and group SID
2681         path = $shrdir
2682         force user = pdbtest
2683         guest ok = yes
2684 [forceuser_wkngroup]
2685         comment = force a user with well-known group SID
2686         path = $shrdir
2687         force user = pdbtest_wkn
2688         guest ok = yes
2689 [forcegroup]
2690         path = $shrdir
2691         force group = nogroup
2692         guest ok = yes
2693 [ro-tmp]
2694         path = $ro_shrdir
2695         guest ok = yes
2696 [noperm]
2697         path = $noperm_shrdir
2698         wide links = yes
2699         guest ok = yes
2700 [write-list-tmp]
2701         path = $shrdir
2702         read only = yes
2703         write list = $unix_name
2704 [valid-users-tmp]
2705         path = $shrdir
2706         valid users = $unix_name
2707         access based share enum = yes
2708 [msdfs-share]
2709         path = $msdfs_shrdir
2710         msdfs root = yes
2711         msdfs shuffle referrals = yes
2712         guest ok = yes
2713 [hideunread]
2714         copy = tmp
2715         hide unreadable = yes
2716 [tmpcase]
2717         copy = tmp
2718         case sensitive = yes
2719 [hideunwrite]
2720         copy = tmp
2721         hide unwriteable files = yes
2722 [durable]
2723         copy = tmp
2724         kernel share modes = no
2725         kernel oplocks = no
2726         posix locking = no
2727 [fs_specific]
2728         copy = tmp
2729         $fs_specific_conf
2730 [print1]
2731         copy = tmp
2732         printable = yes
2733
2734 [print2]
2735         copy = print1
2736 [print3]
2737         copy = print1
2738         default devmode = no
2739
2740 [print_var_exp]
2741         copy = print1
2742         print command = $self->{srcdir}/source3/script/tests/printing/printing_var_exp_lpr_cmd.sh \"Windows user: %U\" \"UNIX user: %u\" \"Domain: %D\"
2743
2744 [lp]
2745         copy = print1
2746
2747 [nfs4acl_simple_40]
2748         path = $shrdir
2749         comment = smb username is [%U]
2750         nfs4:mode = simple
2751         nfs4acl_xattr:version = 40
2752         vfs objects = nfs4acl_xattr xattr_tdb
2753
2754 [nfs4acl_special_40]
2755         path = $shrdir
2756         comment = smb username is [%U]
2757         nfs4:mode = special
2758         nfs4acl_xattr:version = 40
2759         vfs objects = nfs4acl_xattr xattr_tdb
2760
2761 [nfs4acl_simple_41]
2762         path = $shrdir
2763         comment = smb username is [%U]
2764         nfs4:mode = simple
2765         vfs objects = nfs4acl_xattr xattr_tdb
2766
2767 [nfs4acl_xdr_40]
2768         path = $shrdir
2769         comment = smb username is [%U]
2770         vfs objects = nfs4acl_xattr xattr_tdb
2771         nfs4:mode = simple
2772         nfs4acl_xattr:encoding = xdr
2773         nfs4acl_xattr:version = 40
2774
2775 [nfs4acl_xdr_41]
2776         path = $shrdir
2777         comment = smb username is [%U]
2778         vfs objects = nfs4acl_xattr xattr_tdb
2779         nfs4:mode = simple
2780         nfs4acl_xattr:encoding = xdr
2781         nfs4acl_xattr:version = 41
2782
2783 [nfs4acl_nfs_40]
2784         path = $shrdir
2785         comment = smb username is [%U]
2786         vfs objects = nfs4acl_xattr xattr_tdb
2787         nfs4:mode = simple
2788         nfs4acl_xattr:encoding = nfs
2789         nfs4acl_xattr:version = 40
2790         nfs4acl_xattr:xattr_name = security.nfs4acl_xdr
2791
2792 [nfs4acl_nfs_41]
2793         path = $shrdir
2794         comment = smb username is [%U]
2795         vfs objects = nfs4acl_xattr xattr_tdb
2796         nfs4:mode = simple
2797         nfs4acl_xattr:encoding = nfs
2798         nfs4acl_xattr:version = 41
2799         nfs4acl_xattr:xattr_name = security.nfs4acl_xdr
2800
2801 [xcopy_share]
2802         path = $shrdir
2803         comment = smb username is [%U]
2804         create mask = 777
2805         force create mode = 777
2806 [posix_share]
2807         path = $shrdir
2808         comment = smb username is [%U]
2809         create mask = 0777
2810         force create mode = 0
2811         directory mask = 0777
2812         force directory mode = 0
2813         vfs objects = xattr_tdb streams_depot
2814 [aio]
2815         copy = durable
2816         aio read size = 1
2817         aio write size = 1
2818
2819 [print\$]
2820         copy = tmp
2821
2822 [vfs_fruit]
2823         path = $shrdir
2824         vfs objects = catia fruit streams_xattr acl_xattr xattr_tdb
2825         fruit:resource = file
2826         fruit:metadata = netatalk
2827         fruit:locking = netatalk
2828         fruit:encoding = native
2829         fruit:veto_appledouble = no
2830
2831 [vfs_fruit_xattr]
2832         path = $shrdir
2833         # This is used by vfs.fruit tests that require real fs xattr
2834         vfs objects = catia fruit streams_xattr acl_xattr
2835         fruit:resource = file
2836         fruit:metadata = netatalk
2837         fruit:locking = netatalk
2838         fruit:encoding = native
2839         fruit:veto_appledouble = no
2840
2841 [vfs_fruit_metadata_stream]
2842         path = $shrdir
2843         vfs objects = fruit streams_xattr acl_xattr xattr_tdb
2844         fruit:resource = file
2845         fruit:metadata = stream
2846         fruit:veto_appledouble = no
2847
2848 [vfs_fruit_stream_depot]
2849         path = $shrdir
2850         vfs objects = fruit streams_depot acl_xattr xattr_tdb
2851         fruit:resource = stream
2852         fruit:metadata = stream
2853         fruit:veto_appledouble = no
2854
2855 [vfs_wo_fruit]
2856         path = $shrdir
2857         vfs objects = streams_xattr acl_xattr xattr_tdb
2858
2859 [vfs_wo_fruit_stream_depot]
2860         path = $shrdir
2861         vfs objects = streams_depot acl_xattr xattr_tdb
2862
2863 [vfs_fruit_timemachine]
2864         path = $shrdir
2865         vfs objects = fruit streams_xattr acl_xattr xattr_tdb
2866         fruit:resource = file
2867         fruit:metadata = stream
2868         fruit:time machine = yes
2869         fruit:time machine max size = 32K
2870
2871 [vfs_fruit_wipe_intentionally_left_blank_rfork]
2872         path = $shrdir
2873         vfs objects = fruit streams_xattr acl_xattr xattr_tdb
2874         fruit:resource = file
2875         fruit:metadata = stream
2876         fruit:wipe_intentionally_left_blank_rfork = true
2877         fruit:delete_empty_adfiles = false
2878         fruit:veto_appledouble = no
2879
2880 [vfs_fruit_delete_empty_adfiles]
2881         path = $shrdir
2882         vfs objects = fruit streams_xattr acl_xattr xattr_tdb
2883         fruit:resource = file
2884         fruit:metadata = stream
2885         fruit:wipe_intentionally_left_blank_rfork = true
2886         fruit:delete_empty_adfiles = true
2887         fruit:veto_appledouble = no
2888
2889 [vfs_fruit_zero_fileid]
2890         path = $shrdir
2891         vfs objects = fruit streams_xattr acl_xattr xattr_tdb
2892         fruit:resource = file
2893         fruit:metadata = stream
2894         fruit:zero_file_id=yes
2895
2896 [badname-tmp]
2897         path = $badnames_shrdir
2898         guest ok = yes
2899
2900 [manglenames_share]
2901         path = $manglenames_shrdir
2902         guest ok = yes
2903
2904 [dynamic_share]
2905         path = $shrdir/dynamic/%t
2906         guest ok = yes
2907         root preexec = mkdir %P
2908
2909 [widelinks_share]
2910         path = $widelinks_shrdir
2911         wide links = no
2912         guest ok = yes
2913
2914 [fsrvp_share]
2915         path = $fsrvp_shrdir
2916         comment = fake shapshots using rsync
2917         vfs objects = shell_snap shadow_copy2
2918         shell_snap:check path command = $fake_snap_pl --check
2919         shell_snap:create command = $fake_snap_pl --create
2920         shell_snap:delete command = $fake_snap_pl --delete
2921         # a relative path here fails, the snapshot dir is no longer found
2922         shadow:snapdir = $fsrvp_shrdir/.snapshots
2923
2924 [shadow1]
2925         path = $shadow_shrdir
2926         comment = previous versions snapshots under mount point
2927         vfs objects = shadow_copy2
2928         shadow:mountpoint = $shadow_mntdir
2929
2930 [shadow2]
2931         path = $shadow_shrdir
2932         comment = previous versions snapshots outside mount point
2933         vfs objects = shadow_copy2
2934         shadow:mountpoint = $shadow_mntdir
2935         shadow:snapdir = $shadow_tstdir/.snapshots
2936
2937 [shadow3]
2938         path = $shadow_shrdir
2939         comment = previous versions with subvolume snapshots, snapshots under base dir
2940         vfs objects = shadow_copy2
2941         shadow:mountpoint = $shadow_mntdir
2942         shadow:basedir = $shadow_basedir
2943         shadow:snapdir = $shadow_basedir/.snapshots
2944
2945 [shadow4]
2946         path = $shadow_shrdir
2947         comment = previous versions with subvolume snapshots, snapshots outside mount point
2948         vfs objects = shadow_copy2
2949         shadow:mountpoint = $shadow_mntdir
2950         shadow:basedir = $shadow_basedir
2951         shadow:snapdir = $shadow_tstdir/.snapshots
2952
2953 [shadow5]
2954         path = $shadow_shrdir
2955         comment = previous versions at volume root snapshots under mount point
2956         vfs objects = shadow_copy2
2957         shadow:mountpoint = $shadow_shrdir
2958
2959 [shadow6]
2960         path = $shadow_shrdir
2961         comment = previous versions at volume root snapshots outside mount point
2962         vfs objects = shadow_copy2
2963         shadow:mountpoint = $shadow_shrdir
2964         shadow:snapdir = $shadow_tstdir/.snapshots
2965
2966 [shadow7]
2967         path = $shadow_shrdir
2968         comment = previous versions snapshots everywhere
2969         vfs objects = shadow_copy2
2970         shadow:mountpoint = $shadow_mntdir
2971         shadow:snapdirseverywhere = yes
2972
2973 [shadow8]
2974         path = $shadow_shrdir
2975         comment = previous versions using snapsharepath
2976         vfs objects = shadow_copy2
2977         shadow:mountpoint = $shadow_mntdir
2978         shadow:snapdir = $shadow_tstdir/.snapshots
2979         shadow:snapsharepath = share
2980
2981 [shadow_fmt0]
2982         comment = Testing shadow:format with default option
2983         vfs object = shadow_copy2
2984         path = $shadow_shrdir
2985         read only = no
2986         guest ok = yes
2987         shadow:mountpoint = $shadow_mntdir
2988         shadow:basedir = $shadow_basedir
2989         shadow:snapdir = $shadow_basedir/.snapshots
2990         shadow:format = \@GMT-%Y.%m.%d-%H.%M.%S
2991
2992 [shadow_fmt1]
2993         comment = Testing shadow:format with only date component
2994         vfs object = shadow_copy2
2995         path = $shadow_shrdir
2996         read only = no
2997         guest ok = yes
2998         shadow:mountpoint = $shadow_mntdir
2999         shadow:basedir = $shadow_basedir
3000         shadow:snapdir = $shadow_basedir/.snapshots
3001         shadow:format = \@GMT-%Y-%m-%d
3002
3003 [shadow_fmt2]
3004         comment = Testing shadow:format with some hardcoded prefix
3005         vfs object = shadow_copy2
3006         path = $shadow_shrdir
3007         read only = no
3008         guest ok = yes
3009         shadow:mountpoint = $shadow_mntdir
3010         shadow:basedir = $shadow_basedir
3011         shadow:snapdir = $shadow_basedir/.snapshots
3012         shadow:format = snap\@GMT-%Y.%m.%d-%H.%M.%S
3013
3014 [shadow_fmt3]
3015         comment = Testing shadow:format with modified format
3016         vfs object = shadow_copy2
3017         path = $shadow_shrdir
3018         read only = no
3019         guest ok = yes
3020         shadow:mountpoint = $shadow_mntdir
3021         shadow:basedir = $shadow_basedir
3022         shadow:snapdir = $shadow_basedir/.snapshots
3023         shadow:format = \@GMT-%Y.%m.%d-%H_%M_%S-snap
3024
3025 [shadow_fmt4]
3026         comment = Testing shadow:snapprefix regex
3027         vfs object = shadow_copy2
3028         path = $shadow_shrdir
3029         read only = no
3030         guest ok = yes
3031         shadow:mountpoint = $shadow_mntdir
3032         shadow:basedir = $shadow_basedir
3033         shadow:snapdir = $shadow_basedir/.snapshots
3034         shadow:snapprefix = \^s[a-z]*p\$
3035         shadow:format = _GMT-%Y.%m.%d-%H.%M.%S
3036
3037 [shadow_fmt5]
3038         comment = Testing shadow:snapprefix with delim regex
3039         vfs object = shadow_copy2
3040         path = $shadow_shrdir
3041         read only = no
3042         guest ok = yes
3043         shadow:mountpoint = $shadow_mntdir
3044         shadow:basedir = $shadow_basedir
3045         shadow:snapdir = $shadow_basedir/.snapshots
3046         shadow:delimiter = \@GMT
3047         shadow:snapprefix = [a-z]*
3048         shadow:format = \@GMT-%Y.%m.%d-%H.%M.%S
3049
3050 [shadow_wl]
3051         path = $shadow_shrdir
3052         comment = previous versions with wide links allowed
3053         vfs objects = shadow_copy2
3054         shadow:mountpoint = $shadow_mntdir
3055         wide links = yes
3056
3057 [shadow_write]
3058         path = $shadow_tstdir
3059         comment = previous versions snapshots under mount point
3060         vfs objects = shadow_copy2 streams_xattr error_inject
3061         aio write size = 0
3062         error_inject:pwrite = EBADF
3063         shadow:mountpoint = $shadow_tstdir
3064         shadow:fixinodes = yes
3065
3066 [dfq]
3067         path = $shrdir/dfree
3068         vfs objects = acl_xattr fake_acls xattr_tdb fake_dfq
3069         admin users = $unix_name
3070         include = $dfqconffile
3071 [dfq_cache]
3072         path = $shrdir/dfree
3073         vfs objects = acl_xattr fake_acls xattr_tdb fake_dfq
3074         admin users = $unix_name
3075         include = $dfqconffile
3076         dfree cache time = 60
3077 [dfq_owner]
3078         path = $shrdir/dfree
3079         vfs objects = acl_xattr fake_acls xattr_tdb fake_dfq
3080         inherit owner = yes
3081         include = $dfqconffile
3082 [quotadir]
3083         path = $shrdir/quota
3084         admin users = $unix_name
3085
3086 [acl_xattr_ign_sysacl_posix]
3087         copy = tmp
3088         acl_xattr:ignore system acls = yes
3089         acl_xattr:default acl style = posix
3090 [acl_xattr_ign_sysacl_windows]
3091         copy = tmp
3092         acl_xattr:ignore system acls = yes
3093         acl_xattr:default acl style = windows
3094
3095 [mangle_illegal]
3096         copy = tmp
3097         mangled names = illegal
3098
3099 [nosymlinks]
3100         copy = tmp
3101         path = $nosymlinks_shrdir
3102         follow symlinks = no
3103
3104 [local_symlinks]
3105         copy = tmp
3106         path = $local_symlinks_shrdir
3107         follow symlinks = yes
3108
3109 [kernel_oplocks]
3110         copy = tmp
3111         kernel oplocks = yes
3112         vfs objects = streams_xattr xattr_tdb
3113
3114 [streams_xattr]
3115         copy = tmp
3116         vfs objects = streams_xattr xattr_tdb
3117
3118 [compound_find]
3119         copy = tmp
3120         smbd:find async delay usec = 10000
3121 [error_inject]
3122         copy = tmp
3123         vfs objects = error_inject
3124         include = $errorinjectconf
3125
3126 [delay_inject]
3127         copy = tmp
3128         vfs objects = delay_inject
3129         kernel share modes = no
3130         kernel oplocks = no
3131         posix locking = no
3132         include = $delayinjectconf
3133
3134 [aio_delay_inject]
3135         copy = tmp
3136         vfs objects = delay_inject
3137         delay_inject:pread_send = 2000
3138         delay_inject:pwrite_send = 2000
3139
3140 [brl_delay_inject1]
3141         copy = tmp
3142         vfs objects = delay_inject
3143         delay_inject:brl_lock_windows = 90
3144         delay_inject:brl_lock_windows_use_timer = yes
3145
3146 [brl_delay_inject2]
3147         copy = tmp
3148         vfs objects = delay_inject
3149         delay_inject:brl_lock_windows = 90
3150         delay_inject:brl_lock_windows_use_timer = no
3151
3152 [delete_readonly]
3153         path = $prefix_abs/share
3154         delete readonly = yes
3155
3156 [enc_desired]
3157         path = $prefix_abs/share
3158         vfs objects =
3159         server smb encrypt = desired
3160
3161 [enc_off]
3162         path = $prefix_abs/share
3163         vfs objects =
3164         server smb encrypt = off
3165
3166 [notify_priv]
3167         copy = tmp
3168         honor change notify privilege = yes
3169
3170 [acls_non_canonical]
3171         copy = tmp
3172         acl flag inherited canonicalization = no
3173         ";
3174
3175         close(CONF);
3176
3177         my $net = Samba::bindir_path($self, "net");
3178         my $cmd = "";
3179         $cmd .= "UID_WRAPPER_ROOT=1 ";
3180         $cmd .= "SMB_CONF_PATH=\"$conffile\" ";
3181         $cmd .= "$net setlocalsid $samsid";
3182
3183         my $net_ret = system($cmd);
3184         if ($net_ret != 0) {
3185             warn("net setlocalsid failed: $net_ret\n$cmd");
3186             return undef;
3187         }
3188
3189         unless (open(ERRORCONF, ">$errorinjectconf")) {
3190                 warn("Unable to open $errorinjectconf");
3191                 return undef;
3192         }
3193         close(ERRORCONF);
3194
3195         unless (open(DELAYCONF, ">$delayinjectconf")) {
3196                 warn("Unable to open $delayinjectconf");
3197                 return undef;
3198         }
3199         close(DELAYCONF);
3200
3201         unless (open(DFQCONF, ">$dfqconffile")) {
3202                 warn("Unable to open $dfqconffile");
3203                 return undef;
3204         }
3205         close(DFQCONF);
3206
3207         unless (open(DELAYCONF, ">$globalinjectconf")) {
3208                 warn("Unable to open $globalinjectconf");
3209                 return undef;
3210         }
3211         close(DELAYCONF);
3212
3213         ##
3214         ## create a test account
3215         ##
3216
3217         unless (open(PASSWD, ">$nss_wrapper_passwd")) {
3218            warn("Unable to open $nss_wrapper_passwd");
3219            return undef;
3220         } 
3221         print PASSWD "nobody:x:$uid_nobody:$gid_nobody:nobody gecos:$prefix_abs:/bin/false
3222 $unix_name:x:$unix_uid:$unix_gids[0]:$unix_name gecos:$prefix_abs:/bin/false
3223 pdbtest:x:$uid_pdbtest:$gid_nogroup:pdbtest gecos:$prefix_abs:/bin/false
3224 pdbtest2:x:$uid_pdbtest2:$gid_nogroup:pdbtest gecos:$prefix_abs:/bin/false
3225 userdup:x:$uid_userdup:$gid_userdup:userdup gecos:$prefix_abs:/bin/false
3226 pdbtest_wkn:x:$uid_pdbtest_wkn:$gid_everyone:pdbtest_wkn gecos:$prefix_abs:/bin/false
3227 force_user:x:$uid_force_user:$gid_force_user:force user gecos:$prefix_abs:/bin/false
3228 smbget_user:x:$uid_smbget:$gid_domusers:smbget_user gecos:$prefix_abs:/bin/false
3229 user1:x:$uid_user1:$gid_nogroup:user1 gecos:$prefix_abs:/bin/false
3230 user2:x:$uid_user2:$gid_nogroup:user2 gecos:$prefix_abs:/bin/false
3231 gooduser:x:$uid_gooduser:$gid_domusers:gooduser gecos:$prefix_abs:/bin/false
3232 eviluser:x:$uid_eviluser:$gid_domusers:eviluser gecos::/bin/false
3233 slashuser:x:$uid_slashuser:$gid_domusers:slashuser gecos:/:/bin/false
3234 ";
3235         if ($unix_uid != 0) {
3236                 print PASSWD "root:x:$uid_root:$gid_root:root gecos:$prefix_abs:/bin/false
3237 ";
3238         }
3239         close(PASSWD);
3240
3241         unless (open(GROUP, ">$nss_wrapper_group")) {
3242              warn("Unable to open $nss_wrapper_group");
3243              return undef;
3244         }
3245         print GROUP "nobody:x:$gid_nobody:
3246 nogroup:x:$gid_nogroup:nobody
3247 $unix_name-group:x:$unix_gids[0]:
3248 domusers:X:$gid_domusers:
3249 domadmins:X:$gid_domadmins:
3250 userdup:x:$gid_userdup:$unix_name
3251 everyone:x:$gid_everyone:
3252 force_user:x:$gid_force_user:
3253 ";
3254         if ($unix_gids[0] != 0) {
3255                 print GROUP "root:x:$gid_root:
3256 ";
3257         }
3258
3259         close(GROUP);
3260
3261         ## hosts
3262         my $hostname = lc($server);
3263         unless (open(HOSTS, ">>$nss_wrapper_hosts")) {
3264                 warn("Unable to open $nss_wrapper_hosts");
3265                 return undef;
3266         }
3267         print HOSTS "${server_ip} ${hostname}.${dns_domain} ${hostname}\n";
3268         print HOSTS "${server_ipv6} ${hostname}.${dns_domain} ${hostname}\n";
3269         close(HOSTS);
3270
3271         $resolv_conf = "$privatedir/no_resolv.conf" unless defined($resolv_conf);
3272
3273         foreach my $evlog (@eventlog_list) {
3274                 my $evlogtdb = "$eventlogdir/$evlog.tdb";
3275                 open(EVENTLOG, ">$evlogtdb") or die("Unable to open $evlogtdb");
3276                 close(EVENTLOG);
3277         }
3278
3279         $createuser_env{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd;
3280         $createuser_env{NSS_WRAPPER_GROUP} = $nss_wrapper_group;
3281         $createuser_env{NSS_WRAPPER_HOSTS} = $nss_wrapper_hosts;
3282         $createuser_env{NSS_WRAPPER_HOSTNAME} = "${hostname}.samba.example.com";
3283         if ($ENV{SAMBA_DNS_FAKING}) {
3284                 $createuser_env{RESOLV_WRAPPER_HOSTS} = $dns_host_file;
3285         } else {
3286                 $createuser_env{RESOLV_WRAPPER_CONF} = $resolv_conf;
3287         }
3288         $createuser_env{RESOLV_CONF} = $resolv_conf;
3289
3290         createuser($self, $unix_name, $password, $conffile, \%createuser_env) || die("Unable to create user");
3291         createuser($self, "force_user", $password, $conffile, \%createuser_env) || die("Unable to create force_user");
3292         createuser($self, "smbget_user", $password, $conffile, \%createuser_env) || die("Unable to create smbget_user");
3293         createuser($self, "user1", $password, $conffile, \%createuser_env) || die("Unable to create user1");
3294         createuser($self, "user2", $password, $conffile, \%createuser_env) || die("Unable to create user2");
3295         createuser($self, "gooduser", $password, $conffile, \%createuser_env) || die("Unable to create gooduser");
3296         createuser($self, "eviluser", $password, $conffile, \%createuser_env) || die("Unable to create eviluser");
3297         createuser($self, "slashuser", $password, $conffile, \%createuser_env) || die("Unable to create slashuser");
3298
3299         open(DNS_UPDATE_LIST, ">$prefix/dns_update_list") or die("Unable to open $$prefix/dns_update_list");
3300         print DNS_UPDATE_LIST "A $server. $server_ip\n";
3301         print DNS_UPDATE_LIST "AAAA $server. $server_ipv6\n";
3302         close(DNS_UPDATE_LIST);
3303
3304         print "DONE\n";
3305
3306         $ret{SERVER_IP} = $server_ip;
3307         $ret{SERVER_IPV6} = $server_ipv6;
3308         $ret{NMBD_TEST_LOG} = "$prefix/nmbd_test.log";
3309         $ret{NMBD_TEST_LOG_POS} = 0;
3310         $ret{WINBINDD_TEST_LOG} = "$prefix/winbindd_test.log";
3311         $ret{WINBINDD_TEST_LOG_POS} = 0;
3312         $ret{SMBD_TEST_LOG} = "$prefix/smbd_test.log";
3313         $ret{SMBD_TEST_LOG_POS} = 0;
3314         $ret{SERVERCONFFILE} = $conffile;
3315         $ret{TESTENV_DIR} = $prefix_abs;
3316         $ret{CONFIGURATION} ="--configfile=$conffile";
3317         $ret{LOCK_DIR} = $lockdir;
3318         $ret{SERVER} = $server;
3319         $ret{USERNAME} = $unix_name;
3320         $ret{USERID} = $unix_uid;
3321         $ret{DOMAIN} = $domain;
3322         $ret{SAMSID} = $samsid;
3323         $ret{NETBIOSNAME} = $server;
3324         $ret{PASSWORD} = $password;
3325         $ret{PIDDIR} = $piddir;
3326         $ret{SELFTEST_WINBINDD_SOCKET_DIR} = $wbsockdir;
3327         $ret{NMBD_SOCKET_DIR} = $nmbdsockdir;
3328         $ret{SOCKET_WRAPPER_DEFAULT_IFACE} = $swiface;
3329         $ret{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd;
3330         $ret{NSS_WRAPPER_GROUP} = $nss_wrapper_group;
3331         $ret{NSS_WRAPPER_HOSTS} = $nss_wrapper_hosts;
3332         $ret{NSS_WRAPPER_HOSTNAME} = "${hostname}.samba.example.com";
3333         $ret{NSS_WRAPPER_MODULE_SO_PATH} = Samba::nss_wrapper_winbind_so_path($self);
3334         $ret{NSS_WRAPPER_MODULE_FN_PREFIX} = "winbind";
3335         if ($ENV{SAMBA_DNS_FAKING}) {
3336                 $ret{RESOLV_WRAPPER_HOSTS} = $dns_host_file;
3337         } else {
3338                 $ret{RESOLV_WRAPPER_CONF} = $resolv_conf;
3339         }
3340         $ret{RESOLV_CONF} = $resolv_conf;
3341         $ret{LOCAL_PATH} = "$shrdir";
3342         $ret{LOGDIR} = $logdir;
3343
3344         #
3345         # Avoid hitting system krb5.conf -
3346         # An env that needs Kerberos will reset this to the real
3347         # value.
3348         #
3349         $ret{KRB5_CONFIG} = abs_path($prefix) . "/no_krb5.conf";
3350
3351         # Define KRB5CCNAME for each environment we set up
3352         $ret{KRB5_CCACHE} = abs_path($prefix) . "/krb5ccache";
3353         $ENV{KRB5CCNAME} = $ret{KRB5_CCACHE};
3354
3355         return \%ret;
3356 }
3357
3358 sub wait_for_start($$$$$)
3359 {
3360         my ($self, $envvars, $nmbd, $winbindd, $smbd) = @_;
3361         my $cmd;
3362         my $netcmd;
3363         my $ret;
3364
3365         if ($nmbd eq "yes") {
3366                 my $count = 0;
3367
3368                 # give time for nbt server to register its names
3369                 print "checking for nmbd\n";
3370
3371                 # This will return quickly when things are up, but be slow if we need to wait for (eg) SSL init
3372                 my $nmblookup = Samba::bindir_path($self, "nmblookup");
3373
3374                 do {
3375                         $ret = system("$nmblookup $envvars->{CONFIGURATION} $envvars->{SERVER}");
3376                         if ($ret != 0) {
3377                                 sleep(1);
3378                         } else {
3379                                 system("$nmblookup $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} __SAMBA__");
3380                                 system("$nmblookup $envvars->{CONFIGURATION} __SAMBA__");
3381                                 system("$nmblookup $envvars->{CONFIGURATION} -U 10.255.255.255 __SAMBA__");
3382                                 system("$nmblookup $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} $envvars->{SERVER}");
3383                         }
3384                         $count++;
3385                 } while ($ret != 0 && $count < 10);
3386                 if ($count == 10) {
3387                         print "NMBD not reachable after 10 retries\n";
3388                         teardown_env($self, $envvars);
3389                         return 0;
3390                 }
3391         }
3392
3393         if ($winbindd eq "yes") {
3394             print "checking for winbindd\n";
3395             my $count = 0;
3396             $cmd = "SELFTEST_WINBINDD_SOCKET_DIR='$envvars->{SELFTEST_WINBINDD_SOCKET_DIR}' ";
3397             $cmd .= "NSS_WRAPPER_PASSWD='$envvars->{NSS_WRAPPER_PASSWD}' ";
3398             $cmd .= "NSS_WRAPPER_GROUP='$envvars->{NSS_WRAPPER_GROUP}' ";
3399             $cmd .= Samba::bindir_path($self, "wbinfo") . " --ping-dc";
3400
3401             do {
3402                 $ret = system($cmd);
3403                 if ($ret != 0) {
3404                     sleep(1);
3405                 }
3406                 $count++;
3407             } while ($ret != 0 && $count < 20);
3408             if ($count == 20) {
3409                 print "WINBINDD not reachable after 20 seconds\n";
3410                 teardown_env($self, $envvars);
3411                 return 0;
3412             }
3413         }
3414
3415         if ($smbd eq "yes") {
3416             # make sure smbd is also up set
3417             print "wait for smbd\n";
3418
3419             my $count = 0;
3420             do {
3421                 if (defined($envvars->{GNUTLS_FORCE_FIPS_MODE})) {
3422                         # We don't have NTLM in FIPS mode, so lets use
3423                         # smbcontrol instead of smbclient.
3424                         $cmd = Samba::bindir_path($self, "smbcontrol");
3425                         $cmd .= " $envvars->{CONFIGURATION}";
3426                         $cmd .= " smbd ping";
3427                 } else {
3428                         # This uses NTLM which is not available in FIPS
3429                         $cmd = Samba::bindir_path($self, "smbclient");
3430                         $cmd .= " $envvars->{CONFIGURATION}";
3431                         $cmd .= " -L $envvars->{SERVER}";
3432                         $cmd .= " -U%";
3433                         $cmd .= " -I $envvars->{SERVER_IP}";
3434                         $cmd .= " -p 139";
3435                 }
3436
3437                 $ret = system($cmd);
3438                 if ($ret != 0) {
3439                     sleep(1);
3440                 }
3441                 $count++
3442             } while ($ret != 0 && $count < 20);
3443             if ($count == 20) {
3444                 print "SMBD failed to start up in a reasonable time (20sec)\n";
3445                 teardown_env($self, $envvars);
3446                 return 0;
3447             }
3448         }
3449
3450         # Ensure we have domain users mapped.
3451         $netcmd = "NSS_WRAPPER_PASSWD='$envvars->{NSS_WRAPPER_PASSWD}' ";
3452         $netcmd .= "NSS_WRAPPER_GROUP='$envvars->{NSS_WRAPPER_GROUP}' ";
3453         $netcmd .= "UID_WRAPPER_ROOT='1' ";
3454         $netcmd .= Samba::bindir_path($self, "net") ." $envvars->{CONFIGURATION} ";
3455
3456         $cmd = $netcmd . "groupmap delete ntgroup=domusers";
3457         $ret = system($cmd);
3458
3459         $cmd = $netcmd . "groupmap add rid=513 unixgroup=domusers type=domain";
3460         $ret = system($cmd);
3461         if ($ret != 0) {
3462                 print("\"$cmd\" failed\n");
3463                 return 1;
3464         }
3465
3466         $cmd = $netcmd . "groupmap delete ntgroup=domadmins";
3467         $ret = system($cmd);
3468
3469         $cmd = $netcmd . "groupmap add rid=512 unixgroup=domadmins type=domain";
3470         $ret = system($cmd);
3471         if ($ret != 0) {
3472                 print("\"$cmd\" failed\n");
3473                 return 1;
3474         }
3475
3476         $cmd = $netcmd . "groupmap delete ntgroup=everyone";
3477         $ret = system($cmd);
3478
3479         $cmd = $netcmd . "groupmap add sid=S-1-1-0 unixgroup=everyone type=builtin";
3480         $ret = system($cmd);
3481         if ($ret != 0) {
3482                 print("\"$cmd\" failed\n");
3483                 return 1;
3484         }
3485
3486         # note: creating builtin groups requires winbindd for the
3487         # unix id allocator
3488         my $create_builtin_users = "no";
3489         if ($winbindd eq "yes") {
3490                 $cmd = "SELFTEST_WINBINDD_SOCKET_DIR='$envvars->{SELFTEST_WINBINDD_SOCKET_DIR}' ";
3491                 $cmd .= "NSS_WRAPPER_PASSWD='$envvars->{NSS_WRAPPER_PASSWD}' ";
3492                 $cmd .= "NSS_WRAPPER_GROUP='$envvars->{NSS_WRAPPER_GROUP}' ";
3493                 $cmd .= Samba::bindir_path($self, "wbinfo") . " --sid-to-gid=S-1-5-32-545";
3494                 my $wbinfo_out = qx($cmd 2>&1);
3495                 if ($? != 0) {
3496                         # wbinfo doesn't give us a better error code then
3497                         # WBC_ERR_DOMAIN_NOT_FOUND, but at least that's
3498                         # different then WBC_ERR_WINBIND_NOT_AVAILABLE
3499                         if ($wbinfo_out !~ /WBC_ERR_DOMAIN_NOT_FOUND/) {
3500                                 print("Failed to run \"wbinfo --sid-to-gid=S-1-5-32-545\": $wbinfo_out");
3501                                 teardown_env($self, $envvars);
3502                                 return 0;
3503                         }
3504                         $create_builtin_users = "yes";
3505                 }
3506         }
3507         if ($create_builtin_users eq "yes") {
3508             $cmd = "SELFTEST_WINBINDD_SOCKET_DIR='$envvars->{SELFTEST_WINBINDD_SOCKET_DIR}' ";
3509             $cmd .= "NSS_WRAPPER_PASSWD='$envvars->{NSS_WRAPPER_PASSWD}' ";
3510             $cmd .= "NSS_WRAPPER_GROUP='$envvars->{NSS_WRAPPER_GROUP}' ";
3511             $cmd .= Samba::bindir_path($self, "net") . " $envvars->{CONFIGURATION} ";
3512             $cmd .= "sam createbuiltingroup Users";
3513             $ret = system($cmd);
3514             if ($ret != 0) {
3515                 print "Failed to create BUILTIN\\Users group\n";
3516                 teardown_env($self, $envvars);
3517                 return 0;
3518             }
3519
3520             $cmd = Samba::bindir_path($self, "net") . " $envvars->{CONFIGURATION} ";
3521             $cmd .= "cache del IDMAP/SID2XID/S-1-5-32-545";
3522             system($cmd);
3523
3524             $cmd = "SELFTEST_WINBINDD_SOCKET_DIR='$envvars->{SELFTEST_WINBINDD_SOCKET_DIR}' ";
3525             $cmd .= "NSS_WRAPPER_PASSWD='$envvars->{NSS_WRAPPER_PASSWD}' ";
3526             $cmd .= "NSS_WRAPPER_GROUP='$envvars->{NSS_WRAPPER_GROUP}' ";
3527             $cmd .= Samba::bindir_path($self, "wbinfo") . " --sid-to-gid=S-1-5-32-545";
3528             $ret = system($cmd);
3529             if ($ret != 0) {
3530                 print "Missing \"BUILTIN\\Users\", did net sam createbuiltingroup Users fail?\n";
3531                 teardown_env($self, $envvars);
3532                 return 0;
3533             }
3534         }
3535
3536         print $self->getlog_env($envvars);
3537
3538         return 1;
3539 }
3540
3541 ##
3542 ## provision and start of ctdb
3543 ##
3544 sub setup_ctdb($$)
3545 {
3546         my ($self, $prefix) = @_;
3547         my $num_nodes = 3;
3548
3549         my $data = $self->provision_ctdb($prefix, $num_nodes);
3550         $data or return undef;
3551
3552         my $rc = $self->check_or_start_ctdb($data);
3553         if (not $rc) {
3554                 print("check_or_start_ctdb() failed\n");
3555                 return undef;
3556         }
3557
3558         $rc = $self->wait_for_start_ctdb($data);
3559         if (not $rc) {
3560                 print "Cluster startup failed\n";
3561                 return undef;
3562         }
3563
3564         return $data;
3565 }
3566
3567 sub provision_ctdb($$$$)
3568 {
3569         my ($self, $prefix, $num_nodes, $no_delete_prefix) = @_;
3570         my $rc;
3571
3572         print "PROVISIONING CTDB...\n";
3573
3574         my $prefix_abs = abs_path($prefix);
3575
3576         #
3577         # check / create directories:
3578         #
3579         die ("prefix_abs = ''") if $prefix_abs eq "";
3580         die ("prefix_abs = '/'") if $prefix_abs eq "/";
3581
3582         mkdir ($prefix_abs, 0777);
3583
3584         print "CREATE CTDB TEST ENVIRONMENT in '$prefix_abs'...\n";
3585
3586         if (not defined($no_delete_prefix) or not $no_delete_prefix) {
3587                 system("rm -rf $prefix_abs/*");
3588         }
3589
3590         #
3591         # Per-node data
3592         #
3593         my @nodes = ();
3594         for (my $i = 0; $i < $num_nodes; $i++) {
3595                 my %node = ();
3596                 my $server_name = "ctdb${i}";
3597                 my $pub_iface = Samba::get_interface($server_name);
3598                 my $ip = Samba::get_ipv4_addr($server_name);
3599
3600                 $node{NODE_NUMBER} = "$i";
3601                 $node{SERVER_NAME} = "$server_name";
3602                 $node{SOCKET_WRAPPER_DEFAULT_IFACE} = "$pub_iface";
3603                 $node{IP} = "$ip";
3604
3605                 push(@nodes, \%node);
3606         }
3607
3608         #
3609         # nodes
3610         #
3611         my $nodes_file = "$prefix/nodes.in";
3612         unless (open(NODES, ">$nodes_file")) {
3613                 warn("Unable to open nodesfile '$nodes_file'");
3614                 return undef;
3615         }
3616         for (my $i = 0; $i < $num_nodes; $i++) {
3617                 my $ip = $nodes[$i]->{IP};
3618                 print NODES "${ip}\n";
3619         }
3620         close(NODES);
3621
3622         #
3623         # local_daemons.sh setup
3624         #
3625         # Socket wrapper setup is done by selftest.pl, so don't use
3626         # the CTDB-specific setup
3627         #
3628         my $cmd;
3629         $cmd .= "ctdb/tests/local_daemons.sh " . $prefix_abs . " setup";
3630         $cmd .= " -n " . $num_nodes;
3631         $cmd .= " -N " . $nodes_file;
3632         # CTDB should not attempt to manage public addresses -
3633         # clients should just connect to CTDB private addresses
3634         $cmd .= " -P " . "/dev/null";
3635
3636         my $ret = system($cmd);
3637         if ($ret != 0) {
3638                 print("\"$cmd\" failed\n");
3639                 return undef;
3640         }
3641
3642         #
3643         # Unix domain socket and node directory for each daemon
3644         #
3645         for (my $i = 0; $i < $num_nodes; $i++) {
3646                 my ($cmd, $ret, $out);
3647
3648                 my $cmd_prefix = "ctdb/tests/local_daemons.sh ${prefix_abs}";
3649
3650                 #
3651                 # socket
3652                 #
3653
3654                 $cmd = "${cmd_prefix} print-socket ${i}";
3655
3656                 $out = `$cmd`;
3657                 $ret = $?;
3658                 if ($ret != 0) {
3659                     print("\"$cmd\" failed\n");
3660                     return undef;
3661                 }
3662                 chomp $out;
3663                 $nodes[$i]->{SOCKET_FILE} = "$out";
3664
3665                 #
3666                 # node directory
3667                 #
3668
3669                 $cmd = "${cmd_prefix} onnode ${i} 'echo \$CTDB_BASE'";
3670
3671                 $out = `$cmd`;
3672                 $ret = $?;
3673                 if ($ret != 0) {
3674                     print("\"$cmd\" failed\n");
3675                     return undef;
3676                 }
3677                 chomp $out;
3678                 $nodes[$i]->{NODE_PREFIX} = "$out";
3679         }
3680
3681         my %ret = ();
3682
3683         $ret{CTDB_PREFIX} = "$prefix";
3684         $ret{NUM_NODES} = $num_nodes;
3685         $ret{CTDB_NODES} = \@nodes;
3686         $ret{CTDB_NODES_FILE} = $nodes_file;
3687
3688         return \%ret;
3689 }
3690
3691 sub check_or_start_ctdb($$) {
3692         my ($self, $data) = @_;
3693
3694         my $prefix = $data->{CTDB_PREFIX};
3695         my $num_nodes = $data->{NUM_NODES};
3696         my $nodes = $data->{CTDB_NODES};
3697         my $STDIN_READER;
3698
3699         # Share a single stdin pipe for all nodes
3700         pipe($STDIN_READER, $data->{CTDB_STDIN_PIPE});
3701
3702         for (my $i = 0; $i < $num_nodes; $i++) {
3703                 my $node = $nodes->[$i];
3704
3705                 $node->{STDIN_PIPE} = $data->{CTDB_STDIN_PIPE};
3706
3707                 my $cmd = "ctdb/tests/local_daemons.sh";
3708                 my @full_cmd = ("$cmd", "$prefix", "start", "$i");
3709                 my $daemon_ctx = {
3710                         NAME => "ctdbd",
3711                         BINARY_PATH => $cmd,
3712                         FULL_CMD => [ @full_cmd ],
3713                         TEE_STDOUT => 1,
3714                         LOG_FILE => "/dev/null",
3715                         ENV_VARS => {},
3716                 };
3717
3718                 print "STARTING CTDBD (node ${i})\n";
3719
3720                 # This does magic with $STDIN_READER, so use it
3721                 my $ret = Samba::fork_and_exec($self,
3722                                                $node,
3723                                                $daemon_ctx,
3724                                                $STDIN_READER);
3725
3726                 if ($ret == 0) {
3727                         print("\"$cmd\" failed\n");
3728                         teardown_env_ctdb($self, $data);
3729                         return 0;
3730                 }
3731         }
3732
3733         close($STDIN_READER);
3734
3735         return 1;
3736 }
3737
3738 sub wait_for_start_ctdb($$)
3739 {
3740         my ($self, $data) = @_;
3741
3742         my $prefix = $data->{CTDB_PREFIX};
3743
3744         print "Wait for ctdbd...\n";
3745
3746         my $ctdb = Samba::bindir_path($self, "ctdb");
3747         my $cmd;
3748         $cmd .= "ctdb/tests/local_daemons.sh ${prefix} onnode all";
3749         $cmd .= " ${ctdb} nodestatus all 2>&1";
3750
3751         my $count = 0;
3752         my $wait_seconds = 60;
3753         my $out;
3754
3755         until ($count > $wait_seconds) {
3756                 $out = `$cmd`;
3757                 my $ret = $?;
3758                 if ($ret == 0) {
3759                         print "\ncluster became healthy\n";
3760                         last;
3761                 }
3762                 print "Waiting for CTDB...\n";
3763                 sleep(1);
3764                 $count++;
3765         }
3766
3767         if ($count > $wait_seconds) {
3768                 print "\nGiving up to wait for CTDB...\n";
3769                 print "${out}\n\n";
3770                 print "CTDB log:\n";
3771                 $cmd = "ctdb/tests/local_daemons.sh ${prefix} print-log all >&2";
3772                 system($cmd);
3773                 teardown_env_ctdb($self, $data);
3774                 return 0;
3775         }
3776
3777         print "\nCTDB initialized\n";
3778
3779         return 1;
3780 }
3781
3782 1;