selftest: skip targets that are not compiled in if we do not have ADS
[nivanova/samba-autobuild/.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 package Samba3;
7
8 use strict;
9 use Cwd qw(abs_path);
10 use FindBin qw($RealBin);
11 use POSIX;
12 use target::Samba;
13
14 sub have_ads($) {
15     my ($self);
16         my $found_ads = 0;
17         my $smbd_build_options = Samba::bindir_path($self, "smbd") . " -b";
18         my @build_options = `$smbd_build_options`;
19         foreach my $option (@build_options) {
20                 if ($option =~ "WITH_ADS") {
21                        $found_ads = 1;
22                 }
23         }
24
25         # If we were not built with ADS support, pretend we were never even available
26         return $found_ads;
27 }
28
29 sub new($$) {
30         my ($classname, $bindir, $binary_mapping, $srcdir, $server_maxtime) = @_;
31         my $self = { vars => {},
32                      bindir => $bindir,
33                      binary_mapping => $binary_mapping,
34                      srcdir => $srcdir,
35                      server_maxtime => $server_maxtime
36         };
37         bless $self;
38         return $self;
39 }
40
41 sub teardown_env($$)
42 {
43         my ($self, $envvars) = @_;
44
45         my $smbdpid = read_pid($envvars, "smbd");
46         my $nmbdpid = read_pid($envvars, "nmbd");
47         my $winbinddpid = read_pid($envvars, "winbindd");
48
49         $self->stop_sig_term($smbdpid);
50         $self->stop_sig_term($nmbdpid);
51         $self->stop_sig_term($winbinddpid);
52
53         sleep(2);
54
55         $self->stop_sig_kill($smbdpid);
56         $self->stop_sig_kill($nmbdpid);
57         $self->stop_sig_kill($winbinddpid);
58
59         return 0;
60 }
61
62 sub getlog_env_app($$$)
63 {
64         my ($self, $envvars, $name) = @_;
65
66         my $title = "$name LOG of: $envvars->{NETBIOSNAME}\n";
67         my $out = $title;
68
69         open(LOG, "<".$envvars->{$name."_TEST_LOG"});
70
71         seek(LOG, $envvars->{$name."_TEST_LOG_POS"}, SEEK_SET);
72         while (<LOG>) {
73                 $out .= $_;
74         }
75         $envvars->{$name."_TEST_LOG_POS"} = tell(LOG);
76         close(LOG);
77
78         return "" if $out eq $title;
79  
80         return $out;
81 }
82
83 sub getlog_env($$)
84 {
85         my ($self, $envvars) = @_;
86         my $ret = "";
87
88         $ret .= $self->getlog_env_app($envvars, "SMBD");
89         $ret .= $self->getlog_env_app($envvars, "NMBD");
90         $ret .= $self->getlog_env_app($envvars, "WINBINDD");
91
92         return $ret;
93 }
94
95 sub check_env($$)
96 {
97         my ($self, $envvars) = @_;
98
99         # TODO ...
100         return 1;
101 }
102
103 sub setup_env($$$)
104 {
105         my ($self, $envname, $path) = @_;
106         
107         if (defined($self->{vars}->{$envname})) {
108                 return $self->{vars}->{$envname};
109         }
110
111         if ($envname eq "s3dc") {
112                 return $self->setup_s3dc("$path/s3dc");
113         } elsif ($envname eq "secshare") {
114                 return $self->setup_secshare("$path/secshare");
115         } elsif ($envname eq "maptoguest") {
116                 return $self->setup_maptoguest("$path/maptoguest");
117         } elsif ($envname eq "ktest") {
118                 return $self->setup_ktest("$path/ktest");
119         } elsif ($envname eq "secserver") {
120                 if (not defined($self->{vars}->{s3dc})) {
121                         if (not defined($self->setup_s3dc("$path/s3dc"))) {
122                                 return undef;
123                         }
124                 }
125                 return $self->setup_secserver("$path/secserver", $self->{vars}->{s3dc});
126         } elsif ($envname eq "member") {
127                 if (not defined($self->{vars}->{s3dc})) {
128                         if (not defined($self->setup_s3dc("$path/s3dc"))) {
129                                 return undef;
130                         }
131                 }
132                 return $self->setup_member("$path/member", $self->{vars}->{s3dc});
133         } else {
134                 return "UNKNOWN";
135         }
136 }
137
138 sub setup_s3dc($$)
139 {
140         my ($self, $path) = @_;
141
142         print "PROVISIONING S3DC...";
143
144         my $s3dc_options = "
145         domain master = yes
146         domain logons = yes
147         lanman auth = yes
148 ";
149
150         my $vars = $self->provision($path,
151                                     "LOCALS3DC2",
152                                     2,
153                                     "locals3dc2pass",
154                                     $s3dc_options);
155
156         $vars or return undef;
157
158         $self->check_or_start($vars,
159                                "yes", "yes", "yes");
160
161         if (not $self->wait_for_start($vars)) {
162                return undef;
163         }
164
165         $vars->{DC_SERVER} = $vars->{SERVER};
166         $vars->{DC_SERVER_IP} = $vars->{SERVER_IP};
167         $vars->{DC_NETBIOSNAME} = $vars->{NETBIOSNAME};
168         $vars->{DC_USERNAME} = $vars->{USERNAME};
169         $vars->{DC_PASSWORD} = $vars->{PASSWORD};
170
171         $self->{vars}->{s3dc} = $vars;
172
173         return $vars;
174 }
175
176 sub setup_member($$$)
177 {
178         my ($self, $prefix, $s3dcvars) = @_;
179
180         print "PROVISIONING MEMBER...";
181
182         my $member_options = "
183         security = domain
184         server signing = on
185 ";
186         my $ret = $self->provision($prefix,
187                                    "LOCALMEMBER3",
188                                    3,
189                                    "localmember3pass",
190                                    $member_options);
191
192         $ret or return undef;
193
194         my $net = Samba::bindir_path($self, "net");
195         my $cmd = "";
196         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
197         $cmd .= "$net join $ret->{CONFIGURATION} $s3dcvars->{DOMAIN} member";
198         $cmd .= " -U$s3dcvars->{USERNAME}\%$s3dcvars->{PASSWORD}";
199
200         if (system($cmd) != 0) {
201             warn("Join failed\n$cmd");
202             return undef;
203         }
204
205         $self->check_or_start($ret, "yes", "yes", "yes");
206
207         if (not $self->wait_for_start($ret)) {
208                return undef;
209         }
210
211         $ret->{DC_SERVER} = $s3dcvars->{SERVER};
212         $ret->{DC_SERVER_IP} = $s3dcvars->{SERVER_IP};
213         $ret->{DC_NETBIOSNAME} = $s3dcvars->{NETBIOSNAME};
214         $ret->{DC_USERNAME} = $s3dcvars->{USERNAME};
215         $ret->{DC_PASSWORD} = $s3dcvars->{PASSWORD};
216
217         return $ret;
218 }
219
220 sub setup_admember($$$$)
221 {
222         my ($self, $prefix, $dcvars, $iface) = @_;
223
224         # If we didn't build with ADS, pretend this env was never available
225         if (not $self->have_ads()) {
226                 return "UNKNOWN";
227         }
228
229         print "PROVISIONING S3 AD MEMBER$iface...";
230
231         my $member_options = "
232         security = ads
233         server signing = on
234         workgroup = $dcvars->{DOMAIN}
235         realm = $dcvars->{REALM}
236 ";
237
238         my $ret = $self->provision($prefix,
239                                    "LOCALADMEMBER$iface",
240                                    $iface,
241                                    "loCalMember${iface}Pass",
242                                    $member_options);
243
244         $ret or return undef;
245
246         close(USERMAP);
247         $ret->{DOMAIN} = $dcvars->{DOMAIN};
248         $ret->{REALM} = $dcvars->{REALM};
249
250         my $ctx;
251         my $prefix_abs = abs_path($prefix);
252         $ctx = {};
253         $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
254         $ctx->{domain} = $dcvars->{DOMAIN};
255         $ctx->{realm} = $dcvars->{REALM};
256         $ctx->{dnsname} = lc($dcvars->{REALM});
257         $ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
258         Samba::mk_krb5_conf($ctx, "");
259
260         $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
261
262         my $net = Samba::bindir_path($self, "net");
263         my $cmd = "";
264         $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
265         $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
266         $cmd .= "$net join $ret->{CONFIGURATION}";
267         $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
268
269         if (system($cmd) != 0) {
270             warn("Join failed\n$cmd");
271             return undef;
272         }
273
274         # We need world access to this share, as otherwise the domain
275         # administrator from the AD domain provided by Samba4 can't
276         # access the share for tests.
277         chmod 0777, "$prefix/share";
278
279         $self->check_or_start($ret,
280                               "yes", "yes", "yes");
281
282         $self->wait_for_start($ret);
283
284         $ret->{DC_SERVER} = $dcvars->{SERVER};
285         $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
286         $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
287         $ret->{DC_USERNAME} = $dcvars->{USERNAME};
288         $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
289
290         # Special case, this is called from Samba4.pm but needs to use the Samba3 check_env and get_log_env
291         $ret->{target} = $self;
292
293         return $ret;
294 }
295
296 sub setup_plugin_s4_dc($$$$)
297 {
298         my ($self, $prefix, $dcvars, $iface) = @_;
299
300         print "PROVISIONING S4 PLUGIN AD DC$iface...";
301
302         my $plugin_s4_dc_options = "
303         workgroup = $dcvars->{DOMAIN}
304         realm = $dcvars->{REALM}
305
306         security = ads
307         domain logons = yes
308         passdb backend = samba4
309         auth methods = guest samba4
310         server signing = on
311
312         rpc_server:epmapper = disabled
313         rpc_server:rpcecho = disabled
314         rpc_server:dssetup = disabled
315         rpc_server:svctl = disabled
316         rpc_server:ntsvcs = disabled
317         rpc_server:eventlog = disabled
318         rpc_server:initshutdown = disabled
319
320         rpc_server:winreg = embedded
321         rpc_server:srvsvc = embedded
322         rpc_server:netdfs = embedded
323         rpc_server:wkssvc = embedded
324         rpc_server:spoolss = embedded
325
326         rpc_server:lsarpc = external
327         rpc_server:netlogon = external
328         rpc_server:samr = external
329
330         rpc_daemon:epmd = disabled
331         rpc_daemon:lsasd = disabled
332         rpc_daemon:spoolssd = disabled
333
334         rpc_server:tcpip = no
335
336 [IPC\$]
337         vfs objects = dfs_samba4
338 ";
339
340         my $ret = $self->provision($prefix,
341                                    "plugindc",
342                                    $iface,
343                                    "pluGin${iface}Pass",
344                                    $plugin_s4_dc_options, 1);
345
346         $ret or return undef;
347
348         close(USERMAP);
349         $ret->{DOMAIN} = $dcvars->{DOMAIN};
350         $ret->{REALM} = $dcvars->{REALM};
351         $ret->{KRB5_CONFIG} = $dcvars->{KRB5_CONFIG};
352
353         # We need world access to this share, as otherwise the domain
354         # administrator from the AD domain provided by Samba4 can't
355         # access the share for tests.
356         chmod 0777, "$prefix/share";
357
358         $self->check_or_start($ret,
359                               "no", "no", "yes");
360
361         $self->wait_for_start($ret);
362
363         # Special case, this is called from Samba4.pm but needs to use the Samba3 check_env and get_log_env
364         $ret->{target} = $self;
365
366         return $ret;
367 }
368
369 sub setup_secshare($$)
370 {
371         my ($self, $path) = @_;
372
373         print "PROVISIONING server with security=share...";
374
375         my $secshare_options = "
376         security = share
377         lanman auth = yes
378 ";
379
380         my $vars = $self->provision($path,
381                                     "LOCALSHARE4",
382                                     4,
383                                     "local4pass",
384                                     $secshare_options);
385
386         $vars or return undef;
387
388         $self->check_or_start($vars, "yes", "no", "yes");
389
390         if (not $self->wait_for_start($vars)) {
391                return undef;
392         }
393
394         $self->{vars}->{secshare} = $vars;
395
396         return $vars;
397 }
398
399 sub setup_secserver($$$)
400 {
401         my ($self, $prefix, $s3dcvars) = @_;
402
403         print "PROVISIONING server with security=server...";
404
405         my $secserver_options = "
406         security = server
407         password server = $s3dcvars->{SERVER_IP}
408 ";
409
410         my $ret = $self->provision($prefix,
411                                    "LOCALSERVER5",
412                                    5,
413                                    "localserver5pass",
414                                    $secserver_options);
415
416         $ret or return undef;
417
418         $self->check_or_start($ret, "yes", "no", "yes");
419
420         if (not $self->wait_for_start($ret)) {
421                return undef;
422         }
423
424         $ret->{DC_SERVER} = $s3dcvars->{SERVER};
425         $ret->{DC_SERVER_IP} = $s3dcvars->{SERVER_IP};
426         $ret->{DC_NETBIOSNAME} = $s3dcvars->{NETBIOSNAME};
427         $ret->{DC_USERNAME} = $s3dcvars->{USERNAME};
428         $ret->{DC_PASSWORD} = $s3dcvars->{PASSWORD};
429
430         return $ret;
431 }
432
433 sub setup_ktest($$$)
434 {
435         my ($self, $prefix) = @_;
436
437         # If we didn't build with ADS, pretend this env was never available
438         if (not $self->have_ads()) {
439                 return "UNKNOWN";
440         }
441
442         print "PROVISIONING server with security=ads...";
443
444         my $ktest_options = "
445         workgroup = KTEST
446         realm = ktest.samba.example.com
447         security = ads
448         username map = $prefix/lib/username.map
449         server signing = required
450 ";
451
452         my $ret = $self->provision($prefix,
453                                    "LOCALKTEST6",
454                                    6,
455                                    "localktest6pass",
456                                    $ktest_options);
457
458         $ret or return undef;
459
460         my $ctx;
461         my $prefix_abs = abs_path($prefix);
462         $ctx = {};
463         $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
464         $ctx->{domain} = "KTEST";
465         $ctx->{realm} = "KTEST.SAMBA.EXAMPLE.COM";
466         $ctx->{dnsname} = lc($ctx->{realm});
467         $ctx->{kdc_ipv4} = "0.0.0.0";
468         Samba::mk_krb5_conf($ctx, "");
469
470         $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
471
472         open(USERMAP, ">$prefix/lib/username.map") or die("Unable to open $prefix/lib/username.map");
473         print USERMAP "
474 $ret->{USERNAME} = KTEST\\Administrator
475 ";
476         close(USERMAP);
477
478 #This is the secrets.tdb created by 'net ads join' from Samba3 to a
479 #Samba4 DC with the same parameters as are being used here.  The
480 #domain SID is S-1-5-21-1071277805-689288055-3486227160
481
482         system("cp $self->{srcdir}/source3/selftest/ktest-secrets.tdb $prefix/private/secrets.tdb");
483         chmod 0600, "$prefix/private/secrets.tdb";
484
485 #This uses a pre-calculated krb5 credentials cache, obtained by running Samba4 with:
486 # "--option=kdc:service ticket lifetime=239232" "--option=kdc:user ticket lifetime=239232" "--option=kdc:renewal lifetime=239232"
487 #
488 #and having in krb5.conf:
489 # ticket_lifetime = 799718400
490 # renew_lifetime = 799718400
491 #
492 # The commands for the -2 keytab where were:
493 # kinit administrator@KTEST.SAMBA.EXAMPLE.COM
494 # kvno host/localktest6@KTEST.SAMBA.EXAMPLE.COM
495 # kvno cifs/localktest6@KTEST.SAMBA.EXAMPLE.COM
496 # kvno host/LOCALKTEST6@KTEST.SAMBA.EXAMPLE.COM
497 # kvno cifs/LOCALKTEST6@KTEST.SAMBA.EXAMPLE.COM
498 #
499 # and then for the -3 keytab, I did
500 #
501 # net changetrustpw; kdestroy and the same again.
502 #
503 # This creates a credential cache with a very long lifetime (2036 at
504 # at 2011-04), and shows that running 'net changetrustpw' does not
505 # break existing logins (for the secrets.tdb method at least).
506 #
507
508         $ret->{KRB5_CCACHE}="FILE:$prefix/krb5_ccache";
509
510         system("cp $self->{srcdir}/source3/selftest/ktest-krb5_ccache-2 $prefix/krb5_ccache-2");
511         chmod 0600, "$prefix/krb5_ccache-2";
512
513         system("cp $self->{srcdir}/source3/selftest/ktest-krb5_ccache-3 $prefix/krb5_ccache-3");
514         chmod 0600, "$prefix/krb5_ccache-3";
515
516         # We need world access to this share, as otherwise the domain
517         # administrator from the AD domain provided by ktest can't
518         # access the share for tests.
519         chmod 0777, "$prefix/share";
520
521         $self->check_or_start($ret, "yes", "no", "yes");
522
523         if (not $self->wait_for_start($ret)) {
524                return undef;
525         }
526         return $ret;
527 }
528
529 sub setup_maptoguest($$)
530 {
531         my ($self, $path) = @_;
532
533         print "PROVISIONING maptoguest...";
534
535         my $options = "
536 map to guest = bad user
537 ";
538
539         my $vars = $self->provision($path,
540                                     "maptoguest",
541                                     7,
542                                     "maptoguestpass",
543                                     $options);
544
545         $vars or return undef;
546
547         $self->check_or_start($vars,
548                                "yes", "no", "yes");
549
550         if (not $self->wait_for_start($vars)) {
551                return undef;
552         }
553
554         $self->{vars}->{s3maptoguest} = $vars;
555
556         return $vars;
557 }
558
559 sub stop_sig_term($$) {
560         my ($self, $pid) = @_;
561         kill("USR1", $pid) or kill("ALRM", $pid) or warn("Unable to kill $pid: $!");
562 }
563
564 sub stop_sig_kill($$) {
565         my ($self, $pid) = @_;
566         kill("ALRM", $pid) or warn("Unable to kill $pid: $!");
567 }
568
569 sub write_pid($$$)
570 {
571         my ($env_vars, $app, $pid) = @_;
572
573         open(PID, ">$env_vars->{PIDDIR}/timelimit.$app.pid");
574         print PID $pid;
575         close(PID);
576 }
577
578 sub read_pid($$)
579 {
580         my ($env_vars, $app) = @_;
581
582         open(PID, "<$env_vars->{PIDDIR}/timelimit.$app.pid");
583         my $pid = <PID>;
584         close(PID);
585         return $pid;
586 }
587
588 sub check_or_start($$$$$) {
589         my ($self, $env_vars, $nmbd, $winbindd, $smbd) = @_;
590
591         unlink($env_vars->{NMBD_TEST_LOG});
592         print "STARTING NMBD...";
593         my $pid = fork();
594         if ($pid == 0) {
595                 open STDOUT, ">$env_vars->{NMBD_TEST_LOG}";
596                 open STDERR, '>&STDOUT';
597
598                 SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
599
600                 $ENV{KRB5_CONFIG} = $env_vars->{KRB5_CONFIG};
601                 $ENV{WINBINDD_SOCKET_DIR} = $env_vars->{WINBINDD_SOCKET_DIR};
602                 $ENV{NMBD_SOCKET_DIR} = $env_vars->{NMBD_SOCKET_DIR};
603
604                 $ENV{NSS_WRAPPER_PASSWD} = $env_vars->{NSS_WRAPPER_PASSWD};
605                 $ENV{NSS_WRAPPER_GROUP} = $env_vars->{NSS_WRAPPER_GROUP};
606                 $ENV{NSS_WRAPPER_WINBIND_SO_PATH} = $env_vars->{NSS_WRAPPER_WINBIND_SO_PATH};
607
608                 $ENV{UID_WRAPPER} = "1";
609
610                 if ($nmbd ne "yes") {
611                         $SIG{USR1} = $SIG{ALRM} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
612                                 my $signame = shift;
613                                 print("Skip nmbd received signal $signame");
614                                 exit 0;
615                         };
616                         sleep($self->{server_maxtime});
617                         exit 0;
618                 }
619
620                 my @optargs = ("-d0");
621                 if (defined($ENV{NMBD_OPTIONS})) {
622                         @optargs = split(/ /, $ENV{NMBD_OPTIONS});
623                 }
624
625                 $ENV{MAKE_TEST_BINARY} = Samba::bindir_path($self, "nmbd");
626
627                 my @preargs = (Samba::bindir_path($self, "timelimit"), $self->{server_maxtime});
628                 if(defined($ENV{NMBD_VALGRIND})) { 
629                         @preargs = split(/ /, $ENV{NMBD_VALGRIND});
630                 }
631
632                 exec(@preargs, Samba::bindir_path($self, "nmbd"), "-F", "--no-process-group", "--log-stdout", "-s", $env_vars->{SERVERCONFFILE}, @optargs) or die("Unable to start nmbd: $!");
633         }
634         write_pid($env_vars, "nmbd", $pid);
635         print "DONE\n";
636
637         unlink($env_vars->{WINBINDD_TEST_LOG});
638         print "STARTING WINBINDD...";
639         $pid = fork();
640         if ($pid == 0) {
641                 open STDOUT, ">$env_vars->{WINBINDD_TEST_LOG}";
642                 open STDERR, '>&STDOUT';
643
644                 SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
645
646                 $ENV{KRB5_CONFIG} = $env_vars->{KRB5_CONFIG};
647                 $ENV{WINBINDD_SOCKET_DIR} = $env_vars->{WINBINDD_SOCKET_DIR};
648                 $ENV{NMBD_SOCKET_DIR} = $env_vars->{NMBD_SOCKET_DIR};
649
650                 $ENV{NSS_WRAPPER_PASSWD} = $env_vars->{NSS_WRAPPER_PASSWD};
651                 $ENV{NSS_WRAPPER_GROUP} = $env_vars->{NSS_WRAPPER_GROUP};
652                 $ENV{NSS_WRAPPER_WINBIND_SO_PATH} = $env_vars->{NSS_WRAPPER_WINBIND_SO_PATH};
653
654                 $ENV{UID_WRAPPER} = "1";
655
656                 if ($winbindd ne "yes") {
657                         $SIG{USR1} = $SIG{ALRM} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
658                                 my $signame = shift;
659                                 print("Skip winbindd received signal $signame");
660                                 exit 0;
661                         };
662                         sleep($self->{server_maxtime});
663                         exit 0;
664                 }
665
666                 my @optargs = ("-d0");
667                 if (defined($ENV{WINBINDD_OPTIONS})) {
668                         @optargs = split(/ /, $ENV{WINBINDD_OPTIONS});
669                 }
670
671                 $ENV{MAKE_TEST_BINARY} = Samba::bindir_path($self, "winbindd");
672
673                 my @preargs = (Samba::bindir_path($self, "timelimit"), $self->{server_maxtime});
674                 if(defined($ENV{WINBINDD_VALGRIND})) {
675                         @preargs = split(/ /, $ENV{WINBINDD_VALGRIND});
676                 }
677
678                 print "Starting winbindd with config $env_vars->{SERVERCONFFILE}\n";
679
680                 exec(@preargs, Samba::bindir_path($self, "winbindd"), "-F", "--no-process-group", "--stdout", "-s", $env_vars->{SERVERCONFFILE}, @optargs) or die("Unable to start winbindd: $!");
681         }
682         write_pid($env_vars, "winbindd", $pid);
683         print "DONE\n";
684
685         unlink($env_vars->{SMBD_TEST_LOG});
686         print "STARTING SMBD...";
687         $pid = fork();
688         if ($pid == 0) {
689                 open STDOUT, ">$env_vars->{SMBD_TEST_LOG}";
690                 open STDERR, '>&STDOUT';
691
692                 SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
693
694                 $ENV{KRB5_CONFIG} = $env_vars->{KRB5_CONFIG};
695                 $ENV{WINBINDD_SOCKET_DIR} = $env_vars->{WINBINDD_SOCKET_DIR};
696                 $ENV{NMBD_SOCKET_DIR} = $env_vars->{NMBD_SOCKET_DIR};
697
698                 $ENV{NSS_WRAPPER_PASSWD} = $env_vars->{NSS_WRAPPER_PASSWD};
699                 $ENV{NSS_WRAPPER_GROUP} = $env_vars->{NSS_WRAPPER_GROUP};
700                 $ENV{NSS_WRAPPER_WINBIND_SO_PATH} = $env_vars->{NSS_WRAPPER_WINBIND_SO_PATH};
701
702                 $ENV{UID_WRAPPER} = "1";
703
704                 if ($smbd ne "yes") {
705                         $SIG{USR1} = $SIG{ALRM} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
706                                 my $signame = shift;
707                                 print("Skip smbd received signal $signame");
708                                 exit 0;
709                         };
710                         sleep($self->{server_maxtime});
711                         exit 0;
712                 }
713
714                 $ENV{MAKE_TEST_BINARY} = Samba::bindir_path($self, "smbd");
715                 my @optargs = ("-d0");
716                 if (defined($ENV{SMBD_OPTIONS})) {
717                         @optargs = split(/ /, $ENV{SMBD_OPTIONS});
718                 }
719                 my @preargs = (Samba::bindir_path($self, "timelimit"), $self->{server_maxtime});
720                 if(defined($ENV{SMBD_VALGRIND})) {
721                         @preargs = split(/ /,$ENV{SMBD_VALGRIND});
722                 }
723                 exec(@preargs, Samba::bindir_path($self, "smbd"), "-F", "--no-process-group", "--log-stdout", "-s", $env_vars->{SERVERCONFFILE}, @optargs) or die("Unable to start smbd: $!");
724         }
725         write_pid($env_vars, "smbd", $pid);
726         print "DONE\n";
727
728         return 0;
729 }
730
731 sub provision($$$$$$$)
732 {
733         my ($self, $prefix, $server, $swiface, $password, $extra_options, $no_delete_prefix) = @_;
734
735         ##
736         ## setup the various environment variables we need
737         ##
738
739         my %ret = ();
740         my $server_ip = "127.0.0.$swiface";
741         my $domain = "SAMBA-TEST";
742
743         my $unix_name = ($ENV{USER} or $ENV{LOGNAME} or `PATH=/usr/ucb:$ENV{PATH} whoami`);
744         chomp $unix_name;
745         my $unix_uid = $>;
746         my $unix_gids_str = $);
747         my @unix_gids = split(" ", $unix_gids_str);
748
749         my $prefix_abs = abs_path($prefix);
750         my $bindir_abs = abs_path($self->{bindir});
751         my $vfs_modulesdir_abs = ($ENV{VFSLIBDIR} or $bindir_abs);
752
753         my $dns_host_file = "$ENV{SELFTEST_PREFIX}/dns_host_file";
754
755         my @dirs = ();
756
757         my $shrdir="$prefix_abs/share";
758         push(@dirs,$shrdir);
759
760         my $libdir="$prefix_abs/lib";
761         push(@dirs,$libdir);
762
763         my $piddir="$prefix_abs/pid";
764         push(@dirs,$piddir);
765
766         my $privatedir="$prefix_abs/private";
767         push(@dirs,$privatedir);
768
769         my $lockdir="$prefix_abs/lockdir";
770         push(@dirs,$lockdir);
771
772         my $eventlogdir="$prefix_abs/lockdir/eventlog";
773         push(@dirs,$eventlogdir);
774
775         my $logdir="$prefix_abs/logs";
776         push(@dirs,$logdir);
777
778         my $driver32dir="$shrdir/W32X86";
779         push(@dirs,$driver32dir);
780
781         my $driver64dir="$shrdir/x64";
782         push(@dirs,$driver64dir);
783
784         my $driver40dir="$shrdir/WIN40";
785         push(@dirs,$driver40dir);
786
787         my $ro_shrdir="$shrdir/root-tmp";
788         push(@dirs,$ro_shrdir);
789
790         my $msdfs_shrdir="$shrdir/msdfsshare";
791         push(@dirs,$msdfs_shrdir);
792
793         my $msdfs_deeppath="$msdfs_shrdir/deeppath";
794         push(@dirs,$msdfs_deeppath);
795
796         # this gets autocreated by winbindd
797         my $wbsockdir="$prefix_abs/winbindd";
798         my $wbsockprivdir="$lockdir/winbindd_privileged";
799
800         my $nmbdsockdir="$prefix_abs/nmbd";
801         unlink($nmbdsockdir);
802
803         ## 
804         ## create the test directory layout
805         ##
806         die ("prefix_abs = ''") if $prefix_abs eq "";
807         die ("prefix_abs = '/'") if $prefix_abs eq "/";
808
809         mkdir($prefix_abs, 0777);
810         print "CREATE TEST ENVIRONMENT IN '$prefix'...";
811         if (not defined($no_delete_prefix) or not $no_delete_prefix) {
812             system("rm -rf $prefix_abs/*");
813         }
814         mkdir($_, 0777) foreach(@dirs);
815
816         ##
817         ## create ro and msdfs share layout
818         ##
819
820         chmod 0755, $ro_shrdir;
821         my $unreadable_file = "$ro_shrdir/unreadable_file";
822         unless (open(UNREADABLE_FILE, ">$unreadable_file")) {
823                 warn("Unable to open $unreadable_file");
824                 return undef;
825         }
826         close(UNREADABLE_FILE);
827         chmod 0600, $unreadable_file;
828
829         my $msdfs_target = "$ro_shrdir/msdfs-target";
830         unless (open(MSDFS_TARGET, ">$msdfs_target")) {
831                 warn("Unable to open $msdfs_target");
832                 return undef;
833         }
834         close(MSDFS_TARGET);
835         chmod 0666, $msdfs_target;
836         symlink "msdfs:$server_ip\\ro-tmp", "$msdfs_shrdir/msdfs-src1";
837         symlink "msdfs:$server_ip\\ro-tmp", "$msdfs_shrdir/deeppath/msdfs-src2";
838
839         my $conffile="$libdir/server.conf";
840
841         my $nss_wrapper_pl = "$ENV{PERL} $self->{srcdir}/lib/nss_wrapper/nss_wrapper.pl";
842         my $nss_wrapper_passwd = "$privatedir/passwd";
843         my $nss_wrapper_group = "$privatedir/group";
844
845         my $mod_printer_pl = "$ENV{PERL} $self->{srcdir}/source3/script/tests/printing/modprinter.pl";
846
847         my @eventlog_list = ("dns server", "application");
848
849         ##
850         ## calculate uids and gids
851         ##
852
853         my ($max_uid, $max_gid);
854         my ($uid_nobody, $uid_root);
855         my ($gid_nobody, $gid_nogroup, $gid_root, $gid_domusers);
856
857         if ($unix_uid < 0xffff - 2) {
858                 $max_uid = 0xffff;
859         } else {
860                 $max_uid = $unix_uid;
861         }
862
863         $uid_root = $max_uid - 1;
864         $uid_nobody = $max_uid - 2;
865
866         if ($unix_gids[0] < 0xffff - 3) {
867                 $max_gid = 0xffff;
868         } else {
869                 $max_gid = $unix_gids[0];
870         }
871
872         $gid_nobody = $max_gid - 1;
873         $gid_nogroup = $max_gid - 2;
874         $gid_root = $max_gid - 3;
875         $gid_domusers = $max_gid - 4;
876
877         ##
878         ## create conffile
879         ##
880
881         unless (open(CONF, ">$conffile")) {
882                 warn("Unable to open $conffile");
883                 return undef;
884         }
885         print CONF "
886 [global]
887         netbios name = $server
888         interfaces = $server_ip/8
889         bind interfaces only = yes
890         panic action = $self->{srcdir}/selftest/gdb_backtrace %d %\$(MAKE_TEST_BINARY)
891
892         workgroup = $domain
893
894         private dir = $privatedir
895         pid directory = $piddir
896         lock directory = $lockdir
897         log file = $logdir/log.\%m
898         log level = 0
899         debug pid = yes
900         max log size = 0
901
902         state directory = $lockdir
903         cache directory = $lockdir
904
905         passdb backend = tdbsam
906
907         time server = yes
908
909         add user script =               $nss_wrapper_pl --passwd_path $nss_wrapper_passwd --type passwd --action add --name %u --gid $gid_nogroup
910         add group script =              $nss_wrapper_pl --group_path  $nss_wrapper_group  --type group  --action add --name %g
911         add machine script =            $nss_wrapper_pl --passwd_path $nss_wrapper_passwd --type passwd --action add --name %u --gid $gid_nogroup
912         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
913         delete user script =            $nss_wrapper_pl --passwd_path $nss_wrapper_passwd --type passwd --action delete --name %u
914         delete group script =           $nss_wrapper_pl --group_path  $nss_wrapper_group  --type group  --action delete --name %g
915         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
916
917         addprinter command =            $mod_printer_pl -a -s $conffile --
918         deleteprinter command =         $mod_printer_pl -d -s $conffile --
919
920         eventlog list = application \"dns server\"
921
922         kernel oplocks = no
923         kernel change notify = no
924
925         syslog = no
926         printing = bsd
927         printcap name = /dev/null
928
929         winbindd:socket dir = $wbsockdir
930         nmbd:socket dir = $nmbdsockdir
931         idmap config * : range = 100000-200000
932         winbind enum users = yes
933         winbind enum groups = yes
934
935 #       min receivefile size = 4000
936
937         max protocol = SMB2
938         read only = no
939         server signing = auto
940
941         smbd:sharedelay = 100000
942 #       smbd:writetimeupdatedelay = 500000
943         map hidden = no
944         map system = no
945         map readonly = no
946         store dos attributes = yes
947         create mask = 755
948         dos filemode = yes
949         vfs objects = $vfs_modulesdir_abs/xattr_tdb.so $vfs_modulesdir_abs/streams_depot.so
950
951         printing = vlp
952         print command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb print %p %s
953         lpq command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpq %p
954         lp rm command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lprm %p %j
955         lp pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lppause %p %j
956         lp resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb lpresume %p %j
957         queue pause command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queuepause %p
958         queue resume command = $bindir_abs/vlp tdbfile=$lockdir/vlp.tdb queueresume %p
959         lpq cache time = 0
960
961         ncalrpc dir = $prefix_abs/ncalrpc
962         rpc_server:epmapper = external
963         rpc_server:spoolss = external
964         rpc_server:lsarpc = external
965         rpc_server:samr = external
966         rpc_server:netlogon = external
967         rpc_server:tcpip = yes
968
969         rpc_daemon:epmd = fork
970         rpc_daemon:spoolssd = fork
971         rpc_daemon:lsasd = fork
972
973         resolv:host file = $dns_host_file
974
975         # The samba3.blackbox.smbclient_s3 test uses this to test that
976         # sending messages works, and that the %m sub works.
977         message command = mv %s $shrdir/message.%m
978
979         # Begin extra options
980         $extra_options
981         # End extra options
982
983         #Include user defined custom parameters if set
984 ";
985
986         if (defined($ENV{INCLUDE_CUSTOM_CONF})) {
987                 print CONF "\t$ENV{INCLUDE_CUSTOM_CONF}\n";
988         }
989
990         print CONF "
991 [tmp]
992         path = $shrdir
993         comment = smb username is [%U]
994 [tmpguest]
995         path = $shrdir
996         guest ok = yes
997 [guestonly]
998         path = $shrdir
999         guest only = yes
1000         guest ok = yes
1001 [forceuser]
1002         path = $shrdir
1003         force user = $unix_name
1004         guest ok = yes
1005 [forcegroup]
1006         path = $shrdir
1007         force group = nogroup
1008         guest ok = yes
1009 [ro-tmp]
1010         path = $ro_shrdir
1011         guest ok = yes
1012 [msdfs-share]
1013         path = $msdfs_shrdir
1014         msdfs root = yes
1015         guest ok = yes
1016 [hideunread]
1017         copy = tmp
1018         hide unreadable = yes
1019 [tmpcase]
1020         copy = tmp
1021         case sensitive = yes
1022 [hideunwrite]
1023         copy = tmp
1024         hide unwriteable files = yes
1025 [print1]
1026         copy = tmp
1027         printable = yes
1028
1029 [print2]
1030         copy = print1
1031 [print3]
1032         copy = print1
1033 [lp]
1034         copy = print1
1035 [xcopy_share]
1036         path = $shrdir
1037         comment = smb username is [%U]
1038         create mask = 777
1039         force create mode = 777
1040 [print\$]
1041         copy = tmp
1042         ";
1043         close(CONF);
1044
1045         ##
1046         ## create a test account
1047         ##
1048
1049         unless (open(PASSWD, ">$nss_wrapper_passwd")) {
1050            warn("Unable to open $nss_wrapper_passwd");
1051            return undef;
1052         } 
1053         print PASSWD "nobody:x:$uid_nobody:$gid_nobody:nobody gecos:$prefix_abs:/bin/false
1054 $unix_name:x:$unix_uid:$unix_gids[0]:$unix_name gecos:$prefix_abs:/bin/false
1055 ";
1056         if ($unix_uid != 0) {
1057                 print PASSWD "root:x:$uid_root:$gid_root:root gecos:$prefix_abs:/bin/false";
1058         }
1059         close(PASSWD);
1060
1061         unless (open(GROUP, ">$nss_wrapper_group")) {
1062              warn("Unable to open $nss_wrapper_group");
1063              return undef;
1064         }
1065         print GROUP "nobody:x:$gid_nobody:
1066 nogroup:x:$gid_nogroup:nobody
1067 $unix_name-group:x:$unix_gids[0]:
1068 domusers:X:$gid_domusers:
1069 ";
1070         if ($unix_gids[0] != 0) {
1071                 print GROUP "root:x:$gid_root:";
1072         }
1073
1074         close(GROUP);
1075
1076         foreach my $evlog (@eventlog_list) {
1077                 my $evlogtdb = "$eventlogdir/$evlog.tdb";
1078                 open(EVENTLOG, ">$evlogtdb") or die("Unable to open $evlogtdb");
1079                 close(EVENTLOG);
1080         }
1081
1082         $ENV{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd;
1083         $ENV{NSS_WRAPPER_GROUP} = $nss_wrapper_group;
1084
1085         my $cmd = Samba::bindir_path($self, "smbpasswd")." -c $conffile -L -s -a $unix_name > /dev/null";
1086         unless (open(PWD, "|$cmd")) {
1087              warn("Unable to set password for test account\n$cmd");
1088              return undef;
1089         }
1090         print PWD "$password\n$password\n";
1091         unless (close(PWD)) {
1092              warn("Unable to set password for test account\n$cmd");
1093              return undef; 
1094         }
1095         print "DONE\n";
1096
1097         open(HOSTS, ">>$ENV{SELFTEST_PREFIX}/dns_host_file") or die("Unable to open $ENV{SELFTEST_PREFIX}/dns_host_file");
1098         print HOSTS "A $server. $server_ip
1099 ";
1100         close(HOSTS);
1101
1102         $ret{SERVER_IP} = $server_ip;
1103         $ret{NMBD_TEST_LOG} = "$prefix/nmbd_test.log";
1104         $ret{NMBD_TEST_LOG_POS} = 0;
1105         $ret{WINBINDD_TEST_LOG} = "$prefix/winbindd_test.log";
1106         $ret{WINBINDD_TEST_LOG_POS} = 0;
1107         $ret{SMBD_TEST_LOG} = "$prefix/smbd_test.log";
1108         $ret{SMBD_TEST_LOG_POS} = 0;
1109         $ret{SERVERCONFFILE} = $conffile;
1110         $ret{CONFIGURATION} ="-s $conffile";
1111         $ret{SERVER} = $server;
1112         $ret{USERNAME} = $unix_name;
1113         $ret{USERID} = $unix_uid;
1114         $ret{DOMAIN} = $domain;
1115         $ret{NETBIOSNAME} = $server;
1116         $ret{PASSWORD} = $password;
1117         $ret{PIDDIR} = $piddir;
1118         $ret{WINBINDD_SOCKET_DIR} = $wbsockdir;
1119         $ret{WINBINDD_PRIV_PIPE_DIR} = $wbsockprivdir;
1120         $ret{NMBD_SOCKET_DIR} = $nmbdsockdir;
1121         $ret{SOCKET_WRAPPER_DEFAULT_IFACE} = $swiface;
1122         $ret{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd;
1123         $ret{NSS_WRAPPER_GROUP} = $nss_wrapper_group;
1124         $ret{NSS_WRAPPER_WINBIND_SO_PATH} = $ENV{NSS_WRAPPER_WINBIND_SO_PATH};
1125         if (not defined($ret{NSS_WRAPPER_WINBIND_SO_PATH})) {
1126                 $ret{NSS_WRAPPER_WINBIND_SO_PATH} = Samba::bindir_path($self, "default/nsswitch/libnss-winbind.so");
1127         }
1128         $ret{LOCAL_PATH} = "$shrdir";
1129
1130         return \%ret;
1131 }
1132
1133 sub wait_for_start($$)
1134 {
1135         my ($self, $envvars) = @_;
1136
1137         # give time for nbt server to register its names
1138         print "delaying for nbt name registration\n";
1139         sleep(10);
1140         # This will return quickly when things are up, but be slow if we need to wait for (eg) SSL init 
1141         system(Samba::bindir_path($self, "nmblookup3") ." $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} __SAMBA__");
1142         system(Samba::bindir_path($self, "nmblookup3") ." $envvars->{CONFIGURATION} __SAMBA__");
1143         system(Samba::bindir_path($self, "nmblookup3") ." $envvars->{CONFIGURATION} -U 127.255.255.255 __SAMBA__");
1144         system(Samba::bindir_path($self, "nmblookup3") ." $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} $envvars->{SERVER}");
1145         system(Samba::bindir_path($self, "nmblookup3") ." $envvars->{CONFIGURATION} $envvars->{SERVER}");
1146
1147         # make sure smbd is also up set
1148         print "wait for smbd\n";
1149
1150         my $count = 0;
1151         my $ret;
1152         do {
1153             $ret = system(Samba::bindir_path($self, "smbclient3") ." $envvars->{CONFIGURATION} -L $envvars->{SERVER} -U% -p 139");
1154             if ($ret != 0) {
1155                 sleep(2);
1156             }
1157             $count++
1158         } while ($ret != 0 && $count < 10);
1159         if ($count == 10) {
1160             print "SMBD failed to start up in a reasonable time (20sec)\n";
1161             teardown_env($self, $envvars);
1162             return 0;
1163         }
1164         # Ensure we have domain users mapped.
1165         $ret = system(Samba::bindir_path($self, "net") ." $envvars->{CONFIGURATION} groupmap add rid=513 unixgroup=domusers type=domain");
1166         if ($ret != 0) {
1167             return 1;
1168         }
1169
1170         print $self->getlog_env($envvars);
1171
1172         return 1;
1173 }
1174
1175 1;