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