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