c43b61e560b28c1276dedac86b5053a008c58498
[metze/samba/wip.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
13 sub binpath($$)
14 {
15         my ($self, $binary) = @_;
16
17         if (defined($self->{bindir})) {
18                 my $path = "$self->{bindir}/$binary";
19                 -f $path or die("File $path doesn't exist");
20                 return $path;
21         }
22
23         return $binary;
24 }
25
26 sub new($$) {
27         my ($classname, $bindir) = @_;
28         my $self = { bindir => $bindir };
29         bless $self;
30         return $self;
31 }
32
33 sub teardown_env($$)
34 {
35         my ($self, $envvars) = @_;
36
37         my $smbdpid = read_pid($envvars, "smbd");
38         my $nmbdpid = read_pid($envvars, "nmbd");
39         my $winbinddpid = read_pid($envvars, "winbindd");
40
41         $self->stop_sig_term($smbdpid);
42         $self->stop_sig_term($nmbdpid);
43         $self->stop_sig_term($winbinddpid);
44         $self->stop_sig_kill($smbdpid);
45         $self->stop_sig_kill($nmbdpid);
46         $self->stop_sig_kill($winbinddpid);
47
48         return 0;
49 }
50
51 sub getlog_env_app($$$)
52 {
53         my ($self, $envvars, $name) = @_;
54
55         my $title = "$name LOG of: $envvars->{NETBIOSNAME}\n";
56         my $out = $title;
57
58         open(LOG, "<".$envvars->{$name."_TEST_LOG"});
59
60         seek(LOG, $envvars->{$name."_TEST_LOG_POS"}, SEEK_SET);
61         while (<LOG>) {
62                 $out .= $_;
63         }
64         $envvars->{$name."_TEST_LOG_POS"} = tell(LOG);
65         close(LOG);
66
67         return "" if $out eq $title;
68  
69         return $out;
70 }
71
72 sub getlog_env($$)
73 {
74         my ($self, $envvars) = @_;
75         my $ret = "";
76
77         $ret .= $self->getlog_env_app($envvars, "SMBD");
78         $ret .= $self->getlog_env_app($envvars, "NMBD");
79         $ret .= $self->getlog_env_app($envvars, "WINBINDD");
80
81         return $ret;
82 }
83
84 sub check_env($$)
85 {
86         my ($self, $envvars) = @_;
87
88         # TODO ...
89         return 1;
90 }
91
92 sub setup_env($$$)
93 {
94         my ($self, $envname, $path) = @_;
95         
96         if ($envname eq "dc") {
97                 return $self->setup_dc("$path/dc");
98         } else {
99                 return undef;
100         }
101 }
102
103 sub setup_dc($$)
104 {
105         my ($self, $path) = @_;
106
107         my $vars = $self->provision($path, "dc");
108
109         $self->check_or_start($vars,
110                               ($ENV{NMBD_MAXTIME} or 2700),
111                               ($ENV{WINBINDD_MAXTIME} or 2700),
112                               ($ENV{SMBD_MAXTIME} or 2700));
113
114         $self->wait_for_start($vars);
115
116         return $vars;
117 }
118
119 sub stop($)
120 {
121         my ($self) = @_;
122 }
123
124 sub stop_sig_term($$) {
125         my ($self, $pid) = @_;
126         kill("USR1", $pid) or kill("ALRM", $pid) or warn("Unable to kill $pid: $!");
127 }
128
129 sub stop_sig_kill($$) {
130         my ($self, $pid) = @_;
131         kill("ALRM", $pid) or warn("Unable to kill $pid: $!");
132 }
133
134 sub write_pid($$$)
135 {
136         my ($env_vars, $app, $pid) = @_;
137
138         open(PID, ">$env_vars->{PIDDIR}/timelimit.$app.pid");
139         print PID $pid;
140         close(PID);
141 }
142
143 sub read_pid($$)
144 {
145         my ($env_vars, $app) = @_;
146
147         open(PID, "<$env_vars->{PIDDIR}/timelimit.$app.pid");
148         my $pid = <PID>;
149         close(PID);
150         return $pid;
151 }
152
153 sub check_or_start($$$$) {
154         my ($self, $env_vars, $nmbd_maxtime, $winbindd_maxtime, $smbd_maxtime) = @_;
155
156         unlink($env_vars->{NMBD_TEST_LOG});
157         print "STARTING NMBD...";
158         my $pid = fork();
159         if ($pid == 0) {
160                 open STDOUT, ">$env_vars->{NMBD_TEST_LOG}";
161                 open STDERR, '>&STDOUT';
162
163                 SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
164
165                 $ENV{WINBINDD_SOCKET_DIR} = $env_vars->{WINBINDD_SOCKET_DIR};
166
167                 $ENV{NSS_WRAPPER_PASSWD} = $env_vars->{NSS_WRAPPER_PASSWD};
168                 $ENV{NSS_WRAPPER_GROUP} = $env_vars->{NSS_WRAPPER_GROUP};
169
170                 my @optargs = ("-d0");
171                 if (defined($ENV{NMBD_OPTIONS})) {
172                         @optargs = split(/ /, $ENV{NMBD_OPTIONS});
173                 }
174
175                 $ENV{MAKE_TEST_BINARY} = $self->binpath("nmbd");
176
177                 my @preargs = ($self->binpath("timelimit"), $nmbd_maxtime);
178                 if(defined($ENV{NMBD_VALGRIND})) { 
179                         @preargs = split(/ /, $ENV{NMBD_VALGRIND});
180                 }
181
182                 exec(@preargs, $self->binpath("nmbd"), "-F", "-S", "--no-process-group", "-s", $env_vars->{SERVERCONFFILE}, @optargs) or die("Unable to start nmbd: $!");
183         }
184         write_pid($env_vars, "nmbd", $pid);
185         print "DONE\n";
186
187         unlink($env_vars->{WINBINDD_TEST_LOG});
188         print "STARTING WINBINDD...";
189         $pid = fork();
190         if ($pid == 0) {
191                 open STDOUT, ">$env_vars->{WINBINDD_TEST_LOG}";
192                 open STDERR, '>&STDOUT';
193
194                 SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
195
196                 $ENV{WINBINDD_SOCKET_DIR} = $env_vars->{WINBINDD_SOCKET_DIR};
197
198                 $ENV{NSS_WRAPPER_PASSWD} = $env_vars->{NSS_WRAPPER_PASSWD};
199                 $ENV{NSS_WRAPPER_GROUP} = $env_vars->{NSS_WRAPPER_GROUP};
200
201                 my @optargs = ("-d0");
202                 if (defined($ENV{WINBINDD_OPTIONS})) {
203                         @optargs = split(/ /, $ENV{WINBINDD_OPTIONS});
204                 }
205
206                 $ENV{MAKE_TEST_BINARY} = $self->binpath("winbindd");
207
208                 my @preargs = ($self->binpath("timelimit"), $winbindd_maxtime);
209                 if(defined($ENV{WINBINDD_VALGRIND})) {
210                         @preargs = split(/ /, $ENV{WINBINDD_VALGRIND});
211                 }
212
213                 exec(@preargs, $self->binpath("winbindd"), "-F", "-S", "--no-process-group", "-s", $env_vars->{SERVERCONFFILE}, @optargs) or die("Unable to start winbindd: $!");
214         }
215         write_pid($env_vars, "winbindd", $pid);
216         print "DONE\n";
217
218         unlink($env_vars->{SMBD_TEST_LOG});
219         print "STARTING SMBD...";
220         $pid = fork();
221         if ($pid == 0) {
222                 open STDOUT, ">$env_vars->{SMBD_TEST_LOG}";
223                 open STDERR, '>&STDOUT';
224
225                 SocketWrapper::set_default_iface($env_vars->{SOCKET_WRAPPER_DEFAULT_IFACE});
226
227                 $ENV{WINBINDD_SOCKET_DIR} = $env_vars->{WINBINDD_SOCKET_DIR};
228
229                 $ENV{NSS_WRAPPER_PASSWD} = $env_vars->{NSS_WRAPPER_PASSWD};
230                 $ENV{NSS_WRAPPER_GROUP} = $env_vars->{NSS_WRAPPER_GROUP};
231
232                 $ENV{MAKE_TEST_BINARY} = $self->binpath("smbd");
233                 my @optargs = ("-d0");
234                 if (defined($ENV{SMBD_OPTIONS})) {
235                         @optargs = split(/ /, $ENV{SMBD_OPTIONS});
236                 }
237                 my @preargs = ($self->binpath("timelimit"), $smbd_maxtime);
238                 if(defined($ENV{SMBD_VALGRIND})) {
239                         @preargs = split(/ /,$ENV{SMBD_VALGRIND});
240                 }
241                 exec(@preargs, $self->binpath("smbd"), "-F", "-S", "--no-process-group", "-s", $env_vars->{SERVERCONFFILE}, @optargs) or die("Unable to start smbd: $!");
242         }
243         write_pid($env_vars, "smbd", $pid);
244         print "DONE\n";
245
246         return 0;
247 }
248
249 sub create_clientconf($$$)
250 {
251         my ($self, $prefix, $domain) = @_;
252
253         my $lockdir = "$prefix/locks";
254         my $logdir = "$prefix/logs";
255         my $piddir = "$prefix/pid";
256         my $privatedir = "$prefix/private";
257         my $scriptdir = "$RealBin/..";
258         my $conffile = "$prefix/smb.conf";
259
260         my $torture_interfaces='127.0.0.6/8,127.0.0.7/8,127.0.0.8/8,127.0.0.9/8,127.0.0.10/8,127.0.0.11/8';
261         open(CONF, ">$conffile");
262         print CONF "
263 [global]
264         workgroup = $domain
265
266         private dir = $privatedir
267         pid directory = $piddir
268         lock directory = $lockdir
269         log file = $logdir/log.\%m
270         log level = 0
271
272         name resolve order = bcast
273
274         netbios name = TORTURE_6
275         interfaces = $torture_interfaces
276         panic action = $scriptdir/gdb_backtrace \%d %\$(MAKE_TEST_BINARY)
277
278         passdb backend = tdbsam
279         ";
280         close(CONF);
281 }
282
283 sub provision($$$)
284 {
285         my ($self, $prefix, $role) = @_;
286
287         ##
288         ## setup the various environment variables we need
289         ##
290
291         my %ret = ();
292         my $server = "LOCALHOST2";
293         my $server_ip = "127.0.0.2";
294         my $domain = "SAMBA-TEST";
295
296         my $unix_name = ($ENV{USER} or $ENV{LOGNAME} or `PATH=/usr/ucb:$ENV{PATH} whoami`);
297         chomp $unix_name;
298         my $unix_uid = $>;
299         my $unix_gids_str = $);
300         my @unix_gids = split(" ", $unix_gids_str);
301         my $password = "test";
302
303         my $srcdir="$RealBin/..";
304         my $scriptdir="$srcdir/selftest";
305         my $prefix_abs = abs_path($prefix);
306         my $bindir_abs = abs_path($self->{bindir});
307
308         my @dirs = ();
309
310         my $shrdir="$prefix_abs/share";
311         push(@dirs,$shrdir);
312
313         my $libdir="$prefix_abs/lib";
314         push(@dirs,$libdir);
315
316         my $piddir="$prefix_abs/pid";
317         push(@dirs,$piddir);
318
319         my $privatedir="$prefix_abs/private";
320         push(@dirs,$privatedir);
321
322         my $lockdir="$prefix_abs/lockdir";
323         push(@dirs,$lockdir);
324
325         my $logdir="$prefix_abs/logs";
326         push(@dirs,$logdir);
327
328         # this gets autocreated by winbindd
329         my $wbsockdir="$prefix_abs/winbindd";
330         my $wbsockprivdir="$lockdir/winbindd_privileged";
331
332         ## 
333         ## create the test directory layout
334         ##
335         mkdir($prefix_abs, 0777);
336         print "CREATE TEST ENVIRONMENT IN '$prefix'...";
337         system("rm -rf $prefix_abs/*");
338         mkdir($_, 0777) foreach(@dirs);
339
340         my $conffile="$libdir/server.conf";
341
342         my $nss_wrapper_pl = "$ENV{PERL} $srcdir/../lib/nss_wrapper/nss_wrapper.pl";
343         my $nss_wrapper_passwd = "$privatedir/passwd";
344         my $nss_wrapper_group = "$privatedir/group";
345
346         open(CONF, ">$conffile") or die("Unable to open $conffile");
347         print CONF "
348 [global]
349         netbios name = $server
350         interfaces = $server_ip/8
351         bind interfaces only = yes
352         panic action = $scriptdir/gdb_backtrace %d %\$(MAKE_TEST_BINARY)
353
354         workgroup = $domain
355
356         private dir = $privatedir
357         pid directory = $piddir
358         lock directory = $lockdir
359         log file = $logdir/log.\%m
360         log level = 0
361
362         name resolve order = bcast
363
364         state directory = $lockdir
365         cache directory = $lockdir
366
367         passdb backend = tdbsam
368
369 ";
370
371         if ($role eq "dc") {
372                 print CONF "\tdomain master = yes\n";
373                 print CONF "\tdomain logons = yes\n";
374         }
375
376 print CONF "
377         time server = yes
378
379         add user script = $nss_wrapper_pl --path $nss_wrapper_passwd --type passwd --action add --name %u
380         add machine script = $nss_wrapper_pl --path $nss_wrapper_passwd --type passwd --action add --name %u
381         delete user script = $nss_wrapper_pl --path $nss_wrapper_passwd --type passwd --action delete --name %u
382
383         kernel oplocks = no
384         kernel change notify = no
385
386         syslog = no
387         printing = bsd
388         printcap name = /dev/null
389
390         winbindd:socket dir = $wbsockdir
391         idmap uid = 100000-200000
392         idmap gid = 100000-200000
393
394 #       min receivefile size = 4000
395
396         read only = no
397         smbd:sharedelay = 100000
398         smbd:writetimeupdatedelay = 500000
399         map hidden = yes
400         map system = yes
401         create mask = 755
402         vfs objects = $bindir_abs/xattr_tdb.so $bindir_abs/streams_depot.so
403
404         #Include user defined custom parameters if set
405         $ENV{INCLUDE_CUSTOM_CONF}
406
407 [tmp]
408         path = $shrdir
409 [hideunread]
410         copy = tmp
411         hide unreadable = yes
412 [hideunwrite]
413         copy = tmp
414         hide unwriteable files = yes
415 [print1]
416         copy = tmp
417         printable = yes
418         printing = test
419 [print2]
420         copy = print1
421 [print3]
422         copy = print1
423 [print4]
424         copy = print1
425         ";
426         close(CONF);
427
428         ##
429         ## create a test account
430         ##
431
432         open(PASSWD, ">$nss_wrapper_passwd") or die("Unable to open $nss_wrapper_passwd");
433         print PASSWD "
434 nobody:x:65534:65533:nobody gecos:$prefix_abs:/bin/false
435 $unix_name:x:$unix_uid:$unix_gids[0]:$unix_name gecos:$prefix_abs:/bin/false
436 ";
437         close(PASSWD);
438
439         open(GROUP, ">$nss_wrapper_group") or die("Unable to open $nss_wrapper_group");
440         print GROUP "
441 nobody:x:65533:
442 nogroup:x:65534:nobody
443 $unix_name-group:x:$unix_gids[0]:
444 ";
445         close(GROUP);
446
447         $ENV{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd;
448         $ENV{NSS_WRAPPER_GROUP} = $nss_wrapper_group;
449
450         open(PWD, "|".$self->binpath("smbpasswd")." -c $conffile -L -s -a $unix_name >/dev/null");
451         print PWD "$password\n$password\n";
452         close(PWD) or die("Unable to set password for test account");
453
454         $ENV{NSS_WRAPPER_PASSWD} = undef;
455         $ENV{NSS_WRAPPER_GROUP} = undef;
456
457         print "DONE\n";
458
459         $ret{SERVER_IP} = $server_ip;
460         $ret{NMBD_TEST_LOG} = "$prefix/nmbd_test.log";
461         $ret{WINBINDD_TEST_LOG} = "$prefix/winbindd_test.log";
462         $ret{SMBD_TEST_LOG} = "$prefix/smbd_test.log";
463         $ret{SERVERCONFFILE} = $conffile;
464         $ret{CONFIGURATION} ="-s $conffile";
465         $ret{SERVER} = $server;
466         $ret{USERNAME} = $unix_name;
467         $ret{DOMAIN} = $domain;
468         $ret{NETBIOSNAME} = $server;
469         $ret{PASSWORD} = $password;
470         $ret{PIDDIR} = $piddir;
471         $ret{WINBINDD_SOCKET_DIR} = $wbsockdir;
472         $ret{WINBINDD_PRIV_PIPE_DIR} = $wbsockprivdir;
473         $ret{SOCKET_WRAPPER_DEFAULT_IFACE} => 2,
474         $ret{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd;
475         $ret{NSS_WRAPPER_GROUP} = $nss_wrapper_group;
476
477         return \%ret;
478 }
479
480 sub wait_for_start($$)
481 {
482         my ($self, $envvars) = @_;
483
484         # give time for nbt server to register its names
485         print "delaying for nbt name registration\n";
486         sleep(10);
487         # This will return quickly when things are up, but be slow if we need to wait for (eg) SSL init 
488         system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} __SAMBA__");
489         system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} __SAMBA__");
490         system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} -U 127.255.255.255 __SAMBA__");
491         system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} $envvars->{SERVER}");
492         system($self->binpath("nmblookup") ." $envvars->{CONFIGURATION} $envvars->{SERVER}");
493         # make sure smbd is also up set
494         print "wait for smbd\n";
495         system($self->binpath("smbclient") ." $envvars->{CONFIGURATION} -L $envvars->{SERVER_IP} -U% -p 139 | head -2");
496         system($self->binpath("smbclient") ." $envvars->{CONFIGURATION} -L $envvars->{SERVER_IP} -U% -p 139 | head -2");
497
498         print "creating BUILTIN\\Administrators\n";
499         $ENV{WINBINDD_SOCKET_DIR} = $envvars->{WINBINDD_SOCKET_DIR};
500         system($self->binpath("net") ." $envvars->{CONFIGURATION} sam createbuiltingroup Administrators");
501         $ENV{WINBINDD_SOCKET_DIR} = undef;
502
503         print $self->getlog_env($envvars);
504 }
505
506 1;