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