s4:dsdb: Implement msDS-ManagedPassword attribute
[samba.git] / selftest / target / Samba3.pm
index 8786b320fa872379e322f009ff7bfdae8355233e..cf40633d127fc96609db228d8e612bbe64d6243f 100755 (executable)
@@ -16,10 +16,18 @@ use POSIX;
 use target::Samba;
 use File::Path 'remove_tree';
 
+sub return_alias_env
+{
+       my ($self, $path, $env) = @_;
+
+       # just an alias
+       return $env;
+}
+
 sub have_ads($) {
         my ($self) = @_;
        my $found_ads = 0;
-        my $smbd_build_options = Samba::bindir_path($self, "smbd") . " -b|";
+        my $smbd_build_options = Samba::bindir_path($self, "smbd") . " --configfile=/dev/null -b|";
         open(IN, $smbd_build_options) or die("Unable to run $smbd_build_options: $!");
 
         while (<IN>) {
@@ -54,8 +62,9 @@ sub get_fs_specific_conf($$)
 }
 
 sub new($$) {
-       my ($classname, $bindir, $srcdir, $server_maxtime) = @_;
+       my ($classname, $SambaCtx, $bindir, $srcdir, $server_maxtime) = @_;
        my $self = { vars => {},
+                    SambaCtx => $SambaCtx,
                     bindir => $bindir,
                     srcdir => $srcdir,
                     server_maxtime => $server_maxtime
@@ -65,6 +74,19 @@ sub new($$) {
 }
 
 sub teardown_env($$)
+{
+       my ($self, $envvars) = @_;
+
+       if (defined($envvars->{CTDB_PREFIX})) {
+               $self->teardown_env_ctdb($envvars);
+       } else {
+               $self->teardown_env_samba($envvars);
+       }
+
+       return;
+}
+
+sub teardown_env_samba($$)
 {
        my ($self, $envvars) = @_;
        my $count = 0;
@@ -75,44 +97,54 @@ sub teardown_env($$)
        my $smbdpid = $envvars->{SMBD_TL_PID};
        my $nmbdpid = $envvars->{NMBD_TL_PID};
        my $winbinddpid = $envvars->{WINBINDD_TL_PID};
+       my $samba_dcerpcdpid = $envvars->{SAMBA_DCERPCD_TL_PID};
 
        # This should give it time to write out the gcov data
        until ($count > 20) {
            my $smbdchild = Samba::cleanup_child($smbdpid, "smbd");
            my $nmbdchild = Samba::cleanup_child($nmbdpid, "nmbd");
            my $winbinddchild = Samba::cleanup_child($winbinddpid, "winbindd");
+           my $samba_dcerpcdchild = Samba::cleanup_child(
+               $samba_dcerpcdpid, "samba-dcerpcd");
            if ($smbdchild == -1
                && $nmbdchild == -1
-               && $winbinddchild == -1) {
+               && $winbinddchild == -1
+               && $samba_dcerpcdpid == -1) {
                last;
            }
            sleep(1);
            $count++;
        }
 
-       if ($count <= 20 && kill(0, $smbdpid, $nmbdpid, $winbinddpid) == 0) {
+       if ($count <= 20 &&
+           kill(0, $smbdpid, $nmbdpid, $winbinddpid, $samba_dcerpcdpid) == 0) {
            return;
        }
 
        $self->stop_sig_term($smbdpid);
        $self->stop_sig_term($nmbdpid);
        $self->stop_sig_term($winbinddpid);
+       $self->stop_sig_term($samba_dcerpcdpid);
 
        $count = 0;
        until ($count > 10) {
            my $smbdchild = Samba::cleanup_child($smbdpid, "smbd");
            my $nmbdchild = Samba::cleanup_child($nmbdpid, "nmbd");
            my $winbinddchild = Samba::cleanup_child($winbinddpid, "winbindd");
+           my $samba_dcerpcdpid = Samba::cleanup_child(
+               $samba_dcerpcdpid, "samba-dcerpcd");
            if ($smbdchild == -1
                && $nmbdchild == -1
-               && $winbinddchild == -1) {
+               && $winbinddchild == -1
+               && $samba_dcerpcdpid == -1) {
                last;
            }
            sleep(1);
            $count++;
        }
 
-       if ($count <= 10 && kill(0, $smbdpid, $nmbdpid, $winbinddpid) == 0) {
+       if ($count <= 10 &&
+           kill(0, $smbdpid, $nmbdpid, $winbinddpid, $samba_dcerpcdpid) == 0) {
            return;
        }
 
@@ -120,6 +152,32 @@ sub teardown_env($$)
        $self->stop_sig_kill($smbdpid);
        $self->stop_sig_kill($nmbdpid);
        $self->stop_sig_kill($winbinddpid);
+       $self->stop_sig_kill($samba_dcerpcdpid);
+
+       return 0;
+}
+
+sub teardown_env_ctdb($$)
+{
+       my ($self, $data) = @_;
+
+       if (defined($data->{SAMBA_NODES})) {
+               my $num_nodes = $data->{NUM_NODES};
+               my $nodes = $data->{SAMBA_NODES};
+
+               for (my $i = 0; $i < $num_nodes; $i++) {
+                       if (defined($nodes->[$i])) {
+                               $self->teardown_env_samba($nodes->[$i]);
+                       }
+               }
+       }
+
+       close($data->{CTDB_STDIN_PIPE});
+
+       if (not defined($data->{SAMBA_NODES})) {
+               # Give waiting children time to exit
+               sleep(5);
+       }
 
        return 0;
 }
@@ -141,7 +199,7 @@ sub getlog_env_app($$$)
        close(LOG);
 
        return "" if $out eq $title;
+
        return $out;
 }
 
@@ -173,10 +231,14 @@ sub check_env($$)
 %Samba3::ENV_DEPS = (
        # name              => [dep_1, dep_2, ...],
        nt4_dc              => [],
+       nt4_dc_smb1         => [],
+       nt4_dc_smb1_done    => ["nt4_dc_smb1"],
        nt4_dc_schannel     => [],
 
        simpleserver        => [],
        fileserver          => [],
+       fileserver_smb1     => [],
+       fileserver_smb1_done => ["fileserver_smb1"],
        maptoguest          => [],
        ktest               => [],
 
@@ -185,14 +247,22 @@ sub check_env($$)
        ad_member           => ["ad_dc", "fl2008r2dc", "fl2003dc"],
        ad_member_rfc2307   => ["ad_dc_ntvfs"],
        ad_member_idmap_rid => ["ad_dc"],
+       admem_idmap_autorid => ["ad_dc"],
        ad_member_idmap_ad  => ["fl2008r2dc"],
+       ad_member_fips      => ["ad_dc_fips"],
+       ad_member_offlogon  => ["ad_dc"],
+       ad_member_oneway    => ["fl2000dc"],
+       ad_member_idmap_nss => ["ad_dc"],
+       ad_member_s3_join   => ["vampire_dc"],
+
+       clusteredmember => ["nt4_dc"],
 );
 
 %Samba3::ENV_DEPS_POST = ();
 
 sub setup_nt4_dc
 {
-       my ($self, $path) = @_;
+       my ($self, $path, $more_conf, $domain, $server) = @_;
 
        print "PROVISIONING NT4 DC...";
 
@@ -202,34 +272,67 @@ sub setup_nt4_dc
        lanman auth = yes
        ntlm auth = yes
        raw NTLMv2 auth = yes
-       server schannel = auto
-
-       rpc_server:epmapper = external
-       rpc_server:spoolss = external
-       rpc_server:lsarpc = external
-       rpc_server:samr = external
-       rpc_server:netlogon = external
-       rpc_server:register_embedded_np = yes
-       rpc_server:FssagentRpc = external
-
-       rpc_daemon:epmd = fork
-       rpc_daemon:spoolssd = fork
-       rpc_daemon:lsasd = fork
-       rpc_daemon:fssd = fork
+       rpc start on demand helpers = false
+
+       CVE_2020_1472:warn_about_unused_debug_level = 3
+       server require schannel:schannel0\$ = no
+       server require schannel:schannel1\$ = no
+       server require schannel:schannel2\$ = no
+       server require schannel:schannel3\$ = no
+       server require schannel:schannel4\$ = no
+       server require schannel:schannel5\$ = no
+       server require schannel:schannel6\$ = no
+       server require schannel:schannel7\$ = no
+       server require schannel:schannel8\$ = no
+       server require schannel:schannel9\$ = no
+       server require schannel:schannel10\$ = no
+       server require schannel:schannel11\$ = no
+       server require schannel:torturetest\$ = no
+
+       server schannel require seal:schannel0\$ = no
+       server schannel require seal:schannel1\$ = no
+       server schannel require seal:schannel2\$ = no
+       server schannel require seal:schannel3\$ = no
+       server schannel require seal:schannel4\$ = no
+       server schannel require seal:schannel5\$ = no
+       server schannel require seal:schannel6\$ = no
+       server schannel require seal:schannel7\$ = no
+       server schannel require seal:schannel8\$ = no
+       server schannel require seal:schannel9\$ = no
+       server schannel require seal:schannel10\$ = no
+       server schannel require seal:schannel11\$ = no
+       server schannel require seal:torturetest\$ = no
+
+       vfs_default:VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS = no
+
        fss: sequence timeout = 1
        check parent directory delete on close = yes
 ";
 
+       if (defined($more_conf)) {
+               $nt4_dc_options = $nt4_dc_options . $more_conf;
+       }
+       if (!defined($domain)) {
+               $domain = "SAMBA-TEST";
+       }
+       if (!defined($server)) {
+               $server = "LOCALNT4DC2";
+       }
        my $vars = $self->provision(
            prefix => $path,
-           domain => "SAMBA-TEST",
-           server => "LOCALNT4DC2",
+           domain => $domain,
+           server => $server,
            password => "localntdc2pass",
            extra_options => $nt4_dc_options);
 
        $vars or return undef;
 
-       if (not $self->check_or_start($vars, "yes", "yes", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $vars,
+               samba_dcerpcd => "yes",
+               nmbd => "yes",
+               winbindd => "yes",
+               smbd => "yes")) {
               return undef;
        }
 
@@ -244,6 +347,23 @@ sub setup_nt4_dc
        return $vars;
 }
 
+sub setup_nt4_dc_smb1
+{
+       my ($self, $path) = @_;
+       my $conf = "
+[global]
+       client min protocol = CORE
+       server min protocol = LANMAN1
+";
+       return $self->setup_nt4_dc($path, $conf, "NT4SMB1", "LCLNT4DC2SMB1");
+}
+
+sub setup_nt4_dc_smb1_done
+{
+       my ($self, $path, $dep_env) = @_;
+       return $self->return_alias_env($path, $dep_env);
+}
+
 sub setup_nt4_dc_schannel
 {
        my ($self, $path) = @_;
@@ -255,17 +375,6 @@ sub setup_nt4_dc_schannel
        domain logons = yes
        lanman auth = yes
 
-       rpc_server:epmapper = external
-       rpc_server:spoolss = external
-       rpc_server:lsarpc = external
-       rpc_server:samr = external
-       rpc_server:netlogon = external
-       rpc_server:register_embedded_np = yes
-
-       rpc_daemon:epmd = fork
-       rpc_daemon:spoolssd = fork
-       rpc_daemon:lsasd = fork
-
        server schannel = yes
        # used to reproduce bug #12772
        server max protocol = SMB2_02
@@ -280,7 +389,11 @@ sub setup_nt4_dc_schannel
 
        $vars or return undef;
 
-       if (not $self->check_or_start($vars, "yes", "yes", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $vars,
+               nmbd => "yes",
+               winbindd => "yes",
+               smbd => "yes")) {
               return undef;
        }
 
@@ -304,7 +417,9 @@ sub setup_nt4_member
        print "PROVISIONING MEMBER...";
 
        my $require_mutexes = "dbwrap_tdb_require_mutexes:* = yes";
-       $require_mutexes = "" if ($ENV{SELFTEST_DONT_REQUIRE_TDB_MUTEX_SUPPORT} eq "1");
+       if ($ENV{SELFTEST_DONT_REQUIRE_TDB_MUTEX_SUPPORT} // '' eq "1") {
+               $require_mutexes = "";
+       }
 
        my $member_options = "
        security = domain
@@ -359,7 +474,11 @@ sub setup_nt4_member
            return undef;
        }
 
-       if (not $self->check_or_start($ret, "yes", "yes", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $ret,
+               nmbd => "yes",
+               winbindd => "yes",
+               smbd => "yes")) {
               return undef;
        }
 
@@ -374,19 +493,235 @@ sub setup_nt4_member
        return $ret;
 }
 
-sub setup_ad_member
+sub setup_clusteredmember
 {
-       my ($self, $prefix, $dcvars, $trustvars_f, $trustvars_e) = @_;
+       my ($self, $prefix, $nt4_dc_vars) = @_;
+       my $count = 0;
+       my $rc;
+       my @retvals = ();
+       my $ret;
+
+       print "PROVISIONING CLUSTEREDMEMBER...\n";
 
        my $prefix_abs = abs_path($prefix);
-       my @dirs = ();
+       mkdir($prefix_abs, 0777);
 
-       # If we didn't build with ADS, pretend this env was never available
-       if (not $self->have_ads()) {
-               return "UNKNOWN";
+       my $ctdb_data = $self->setup_ctdb($prefix);
+
+       if (not $ctdb_data) {
+               print "No ctdb data\n";
+               return undef;
+       }
+
+       print "PROVISIONING CLUSTERED SAMBA...\n";
+
+       my $num_nodes = $ctdb_data->{NUM_NODES};
+       my $nodes = $ctdb_data->{CTDB_NODES};
+
+       # Enable cleanup of earlier nodes if a later node fails
+       $ctdb_data->{SAMBA_NODES} = \@retvals;
+
+       for (my $i = 0; $i < $num_nodes; $i++) {
+               my $node = $nodes->[$i];
+               my $socket = $node->{SOCKET_FILE};
+               my $server_name = $node->{SERVER_NAME};
+               my $pub_iface = $node->{SOCKET_WRAPPER_DEFAULT_IFACE};
+               my $node_prefix = $node->{NODE_PREFIX};
+
+               print "CTDB_BASE=${node_prefix}\n";
+               print "CTDB_SOCKET=${socket}\n";
+
+               my $require_mutexes = "dbwrap_tdb_require_mutexes:* = yes";
+               if ($ENV{SELFTEST_DONT_REQUIRE_TDB_MUTEX_SUPPORT} // '' eq "1") {
+                       $require_mutexes = "" ;
+               }
+
+               my $member_options = "
+       security = domain
+       server signing = on
+       clustering = yes
+       rpc start on demand helpers = false
+       rpcd witness:include node ips = yes
+       ctdbd socket = ${socket}
+       include = registry
+       dbwrap_tdb_mutexes:* = yes
+       ${require_mutexes}
+";
+
+               my $node_ret = $self->provision(
+                   prefix => "$node_prefix",
+                   domain => $nt4_dc_vars->{DOMAIN},
+                   server => "$server_name",
+                   password => "clustermember8pass",
+                   netbios_name => "CLUSTEREDMEMBER",
+                   share_dir => "${prefix_abs}/shared",
+                   extra_options => $member_options,
+                   no_delete_prefix => 1);
+               if (not $node_ret) {
+                       print "Provision node $i failed\n";
+                       teardown_env($self, $ctdb_data);
+                       return undef;
+               }
+
+               my $registry_share_template = "$node_ret->{SERVERCONFFILE}.registry_share_template";
+               unless (open(REGISTRYCONF, ">$registry_share_template")) {
+                       warn("Unable to open $registry_share_template");
+                       teardown_env($self, $node_ret);
+                       teardown_env($self, $ctdb_data);
+                       return undef;
+               }
+
+               print REGISTRYCONF "
+[registry_share]
+       copy = tmp
+       comment = smb username is [%U]
+";
+
+               close(REGISTRYCONF);
+
+               my $net = Samba::bindir_path($self, "net");
+               my $cmd = "";
+
+               $cmd .= "UID_WRAPPER_ROOT=1 ";
+               $cmd .= "$net conf import $node_ret->{CONFIGURATION} ${registry_share_template}";
+
+               my $net_ret = system($cmd);
+               if ($net_ret != 0) {
+                       warn("net conf import failed: $net_ret\n$cmd");
+                       teardown_env($self, $node_ret);
+                       teardown_env($self, $ctdb_data);
+                       return undef;
+               }
+
+               my $nmblookup = Samba::bindir_path($self, "nmblookup");
+               do {
+                       print "Waiting for the LOGON SERVER registration ...\n";
+                       $rc = system("$nmblookup $node_ret->{CONFIGURATION} " .
+                                    "$node_ret->{DOMAIN}\#1c");
+                       if ($rc != 0) {
+                               sleep(1);
+                       }
+                       $count++;
+               } while ($rc != 0 && $count < 10);
+
+               if ($count == 10) {
+                       print "NMBD not reachable after 10 retries\n";
+                       teardown_env($self, $node_ret);
+                       teardown_env($self, $ctdb_data);
+                       return undef;
+               }
+
+               push(@retvals, $node_ret);
+       }
+
+       $ret = {%$ctdb_data, %{$retvals[0]}};
+
+       my $net = Samba::bindir_path($self, "net");
+       my $cmd = "";
+       $cmd .= "UID_WRAPPER_ROOT=1 ";
+       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+       $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
+       $cmd .= "$net join $ret->{CONFIGURATION} $nt4_dc_vars->{DOMAIN} member";
+       $cmd .= " -U$nt4_dc_vars->{USERNAME}\%$nt4_dc_vars->{PASSWORD}";
+
+       if (system($cmd) != 0) {
+               warn("Join failed\n$cmd");
+               teardown_env($self, $ret);
+               return undef;
+       }
+
+       for (my $i=0; $i<@retvals; $i++) {
+               my $node_provision = $retvals[$i];
+               my $ok;
+               $ok = $self->check_or_start(
+                   env_vars => $node_provision,
+                   samba_dcerpcd => "yes",
+                   winbindd => "yes",
+                   smbd => "yes",
+                   child_cleanup => sub {
+                       map {
+                           my $fh = $_->{STDIN_PIPE};
+                           close($fh) if defined($fh);
+                       } @retvals });
+               if (not $ok) {
+                       teardown_env($self, $ret);
+                       return undef;
+               }
+       }
+
+       #
+       # Build a unclist for every share
+       #
+       unless (open(NODES, "<$ret->{CTDB_NODES_FILE}")) {
+               warn("Unable to open CTDB nodes file");
+               teardown_env($self, $ret);
+               return undef;
+       }
+       my @nodes = <NODES>;
+       close(NODES);
+       chomp @nodes;
+
+       my $conffile = $ret->{SERVERCONFFILE};
+       $cmd = "";
+       $cmd .= 'sed -n -e \'s|^\[\(.*\)\]$|\1|p\'';
+       $cmd .= " \"$conffile\"";
+       $cmd .= " | grep -vx 'global'";
+
+       my @shares = `$cmd`;
+       $rc = $?;
+       if ($rc != 0) {
+               warn("Listing shares failed\n$cmd");
+               teardown_env($self, $ret);
+               return undef;
+       }
+       chomp @shares;
+
+       my $unclistdir = "${prefix_abs}/unclists";
+       mkdir($unclistdir, 0777);
+       foreach my $share (@shares) {
+               my $l = "${unclistdir}/${share}.txt";
+               unless (open(UNCLIST, ">${l}")) {
+                       warn("Unable to open UNC list ${l}");
+                       teardown_env($self, $ret);
+                       return undef;
+               }
+               foreach my $node (@nodes) {
+                       print UNCLIST "//${node}/${share}\n";
+               }
+               close(UNCLIST);
+       }
+
+       $ret->{DOMSID} = $nt4_dc_vars->{DOMSID};
+       $ret->{DC_SERVER} = $nt4_dc_vars->{SERVER};
+       $ret->{DC_SERVER_IP} = $nt4_dc_vars->{SERVER_IP};
+       $ret->{DC_SERVER_IPV6} = $nt4_dc_vars->{SERVER_IPV6};
+       $ret->{DC_NETBIOSNAME} = $nt4_dc_vars->{NETBIOSNAME};
+       $ret->{DC_USERNAME} = $nt4_dc_vars->{USERNAME};
+       $ret->{DC_PASSWORD} = $nt4_dc_vars->{PASSWORD};
+
+       return $ret;
+}
+
+sub provision_ad_member
+{
+       my ($self,
+           $prefix,
+           $machine_account,
+           $dcvars,
+           $trustvars_f,
+           $trustvars_e,
+           $extra_member_options,
+           $force_fips_mode,
+           $offline_logon,
+           $no_nss_winbind) = @_;
+
+       if (defined($offline_logon) && defined($no_nss_winbind)) {
+               warn ("Offline logon incompatible with no nss winbind\n");
+               return undef;
        }
 
-       print "PROVISIONING S3 AD MEMBER...";
+       my $prefix_abs = abs_path($prefix);
+       my @dirs = ();
 
        mkdir($prefix_abs, 0777);
 
@@ -415,16 +750,41 @@ sub setup_ad_member
        $substitution_path = "$share_dir/D_$dcvars->{DOMAIN}/u_$dcvars->{DOMAIN}/alice/g_$dcvars->{DOMAIN}/domain users";
        push(@dirs, $substitution_path);
 
+       my $smbcacls_sharedir="$share_dir/smbcacls";
+       push(@dirs,$smbcacls_sharedir);
+
+       my $option_offline_logon = "no";
+       if (defined($offline_logon)) {
+               $option_offline_logon = "yes";
+       }
+
+       my $netbios_aliases = "";
+       if ($machine_account eq "LOCALADMEMBER") {
+               $netbios_aliases = "netbios aliases = foo bar";
+       }
+
+       unless (defined($extra_member_options)) {
+               $extra_member_options = "";
+       }
+
        my $member_options = "
        security = ads
         workgroup = $dcvars->{DOMAIN}
         realm = $dcvars->{REALM}
-        netbios aliases = foo bar
+        $netbios_aliases
        template homedir = /home/%D/%G/%U
        auth event notification = true
        password server = $dcvars->{SERVER}
        winbind scan trusted domains = no
-       winbind use krb5 enterprise principals = yes
+       winbind offline logon = $option_offline_logon
+
+       allow dcerpc auth level connect:lsarpc = yes
+       dcesrv:max auth states = 8
+       rpc start on demand helpers = false
+
+       # Begin extra member options
+       $extra_member_options
+       # End extra member options
 
 [sub_dug]
        path = $share_dir/D_%D/U_%U/G_%G
@@ -434,22 +794,65 @@ sub setup_ad_member
        path = $share_dir/D_%D/u_%u/g_%g
        writeable = yes
 
+[sub_valid_users]
+       path = $share_dir
+       valid users = ADDOMAIN/%U
+
+[sub_valid_users_domain]
+    path = $share_dir
+    valid users = %D/%U
+
+[sub_valid_users_group]
+    path = $share_dir
+    valid users = \@$dcvars->{DOMAIN}/%G
+
+[valid_users]
+    path = $share_dir
+    valid users = $dcvars->{DOMAIN}/$dcvars->{DC_USERNAME}
+
+[valid_users_group]
+    path = $share_dir
+    valid users = \"\@$dcvars->{DOMAIN}/domain users\"
+
+[valid_users_unix_group]
+    path = $share_dir
+    valid users = \"+$dcvars->{DOMAIN}/domain users\"
+
+[valid_users_nis_group]
+    path = $share_dir
+    valid users = \"&$dcvars->{DOMAIN}/domain users\"
+
+[valid_users_unix_nis_group]
+    path = $share_dir
+    valid users = \"+&$dcvars->{DOMAIN}/domain users\"
+
+[valid_users_nis_unix_group]
+    path = $share_dir
+    valid users = \"&+$dcvars->{DOMAIN}/domain users\"
+
+[invalid_users]
+    path = $share_dir
+    invalid users = $dcvars->{DOMAIN}/$dcvars->{DC_USERNAME}
+
+[valid_and_invalid_users]
+    path = $share_dir
+    valid users = $dcvars->{DOMAIN}/$dcvars->{DC_USERNAME} $dcvars->{DOMAIN}/alice
+    invalid users = $dcvars->{DOMAIN}/$dcvars->{DC_USERNAME}
 ";
 
        my $ret = $self->provision(
            prefix => $prefix,
            domain => $dcvars->{DOMAIN},
-           server => "LOCALADMEMBER",
+           realm => $dcvars->{REALM},
+           server => $machine_account,
            password => "loCalMemberPass",
            extra_options => $member_options,
-           dc_server_ip => $dcvars->{SERVER_IP},
-           dc_server_ipv6 => $dcvars->{SERVER_IPV6});
+           resolv_conf => $dcvars->{RESOLV_CONF});
 
        $ret or return undef;
 
        mkdir($_, 0777) foreach(@dirs);
 
-       close(USERMAP);
        $ret->{DOMAIN} = $dcvars->{DOMAIN};
        $ret->{REALM} = $dcvars->{REALM};
        $ret->{DOMSID} = $dcvars->{DOMSID};
@@ -466,7 +869,11 @@ sub setup_ad_member
        Samba::mk_krb5_conf($ctx, "");
 
        $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
-       $ret->{RESOLV_CONF} = $dcvars->{RESOLV_CONF};
+
+       if (defined($force_fips_mode)) {
+               $ret->{GNUTLS_FORCE_FIPS_MODE} = "1";
+               $ret->{OPENSSL_FORCE_FIPS_MODE} = "1";
+       }
 
        my $net = Samba::bindir_path($self, "net");
        # Add hosts file for name lookups
@@ -477,10 +884,15 @@ sub setup_ad_member
        } else {
                $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
        }
+       if (defined($force_fips_mode)) {
+               $cmd .= "GNUTLS_FORCE_FIPS_MODE=1 ";
+               $cmd .= "OPENSSL_FORCE_FIPS_MODE=1 ";
+       }
+       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
        $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
        $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
        $cmd .= "$net join $ret->{CONFIGURATION}";
-       $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
+       $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD} --use-kerberos=required";
 
        if (system($cmd) != 0) {
            warn("Join failed\n$cmd");
@@ -492,8 +904,106 @@ sub setup_ad_member
        # access the share for tests.
        chmod 0777, "$prefix/share";
 
-       if (not $self->check_or_start($ret, "yes", "yes", "yes")) {
-               return undef;
+       if (defined($offline_logon)) {
+               my $wbinfo = Samba::bindir_path($self, "wbinfo");
+
+               if (not $self->check_or_start(
+                       env_vars => $ret,
+                       winbindd => "yes")) {
+                       return undef;
+               }
+
+               # Fill samlogoncache for alice
+               $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
+               $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
+               $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
+               $cmd .= "$wbinfo --pam-logon=ADDOMAIN/alice%Secret007";
+               if (system($cmd) != 0) {
+                       warn("Filling the cache failed\n$cmd");
+                       return undef;
+               }
+
+               $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
+               $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
+               $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
+               $cmd .= "$wbinfo --ccache-save=ADDOMAIN/alice%Secret007";
+               if (system($cmd) != 0) {
+                       warn("Filling the cache failed\n$cmd");
+                       return undef;
+               }
+
+               # Fill samlogoncache for bob
+               $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
+               $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
+               $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
+               $cmd .= "$wbinfo --pam-logon=ADDOMAIN/bob%Secret007";
+               if (system($cmd) != 0) {
+                       warn("Filling the cache failed\n$cmd");
+                       return undef;
+               }
+
+               $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
+               $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
+               $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
+               $cmd .= "$wbinfo --ccache-save=ADDOMAIN/bob%Secret007";
+               if (system($cmd) != 0) {
+                       warn("Filling the cache failed\n$cmd");
+                       return undef;
+               }
+
+               # Set windindd offline
+               my $smbcontrol = Samba::bindir_path($self, "smbcontrol");
+               $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
+               $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
+               $cmd .= "UID_WRAPPER_ROOT='1' ";
+               $cmd .= "$smbcontrol $ret->{CONFIGURATION} winbindd offline";
+               if (system($cmd) != 0) {
+                       warn("Setting winbindd offline failed\n$cmd");
+                       return undef;
+               }
+
+               # Validate the offline cache
+               $cmd = "NSS_WRAPPER_PASSWD='$ret->{NSS_WRAPPER_PASSWD}' ";
+               $cmd .= "NSS_WRAPPER_GROUP='$ret->{NSS_WRAPPER_GROUP}' ";
+               $cmd .= "UID_WRAPPER_ROOT='1' ";
+               $cmd .= "$smbcontrol $ret->{CONFIGURATION} winbindd validate-cache";
+               if (system($cmd) != 0) {
+                       warn("Validation of winbind credential cache failed\n$cmd");
+                       teardown_env($self, $ret);
+                       return undef;
+               }
+
+               # Shut down winbindd
+               teardown_env($self, $ret);
+
+               ### Change SOCKET_WRAPPER_DIR so it can't connect to AD
+               my $swrap_env = $ENV{SOCKET_WRAPPER_DIR};
+               $ENV{SOCKET_WRAPPER_DIR} = "$prefix_abs";
+
+               # Start winbindd in offline mode
+               if (not $self->check_or_start(
+                       env_vars => $ret,
+                       winbindd => "offline")) {
+                       return undef;
+               }
+
+               # Set socket dir again
+               $ENV{SOCKET_WRAPPER_DIR} = $swrap_env;
+
+       } else {
+               if (defined($no_nss_winbind)) {
+                       $ret->{NSS_WRAPPER_MODULE_SO_PATH} = "";
+                       $ret->{NSS_WRAPPER_MODULE_FN_PREFIX} = "";
+               }
+
+               if (not $self->check_or_start(
+                       env_vars => $ret,
+                       samba_dcerpcd => "yes",
+                       nmbd => "yes",
+                       winbindd => "yes",
+                       smbd => "yes")) {
+                       return undef;
+               }
        }
 
        $ret->{DC_SERVER} = $dcvars->{SERVER};
@@ -503,6 +1013,10 @@ sub setup_ad_member
        $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
        $ret->{DC_USERNAME} = $dcvars->{USERNAME};
        $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
+       $ret->{DOMAIN_ADMIN} = $dcvars->{DOMAIN_ADMIN};
+       $ret->{DOMAIN_ADMIN_PASSWORD} = $dcvars->{DOMAIN_ADMIN_PASSWORD};
+       $ret->{DOMAIN_USER} = $dcvars->{DOMAIN_USER};
+       $ret->{DOMAIN_USER_PASSWORD} = $dcvars->{DOMAIN_USER_PASSWORD};
 
        # forest trust
        $ret->{TRUST_F_BOTH_SERVER} = $trustvars_f->{SERVER};
@@ -527,6 +1041,50 @@ sub setup_ad_member
        return $ret;
 }
 
+sub setup_ad_member
+{
+       my ($self,
+           $prefix,
+           $dcvars,
+           $trustvars_f,
+           $trustvars_e) = @_;
+
+       # If we didn't build with ADS, pretend this env was never available
+       if (not $self->have_ads()) {
+               return "UNKNOWN";
+       }
+
+       print "PROVISIONING AD MEMBER...";
+
+       return $self->provision_ad_member($prefix,
+                                         "LOCALADMEMBER",
+                                         $dcvars,
+                                         $trustvars_f,
+                                         $trustvars_e);
+}
+
+sub setup_ad_member_s3_join
+{
+        my ($self,
+            $prefix,
+            $dcvars,
+            $trustvars_f,
+            $trustvars_e) = @_;
+
+        # If we didn't build with ADS, pretend this env was never available
+        if (not $self->have_ads()) {
+                return "UNKNOWN";
+        }
+
+        print "PROVISIONING AD MEMBER...";
+
+        return $self->provision_ad_member($prefix,
+                                          "LOCALADMEMBER2",
+                                          $dcvars,
+                                          $trustvars_f,
+                                          $trustvars_e);
+}
+
 sub setup_ad_member_rfc2307
 {
        my ($self, $prefix, $dcvars) = @_;
@@ -559,15 +1117,14 @@ sub setup_ad_member_rfc2307
        my $ret = $self->provision(
            prefix => $prefix,
            domain => $dcvars->{DOMAIN},
+           realm => $dcvars->{REALM},
            server => "RFC2307MEMBER",
            password => "loCalMemberPass",
            extra_options => $member_options,
-           dc_server_ip => $dcvars->{SERVER_IP},
-           dc_server_ipv6 => $dcvars->{SERVER_IPV6});
+           resolv_conf => $dcvars->{RESOLV_CONF});
 
        $ret or return undef;
 
-       close(USERMAP);
        $ret->{DOMAIN} = $dcvars->{DOMAIN};
        $ret->{REALM} = $dcvars->{REALM};
        $ret->{DOMSID} = $dcvars->{DOMSID};
@@ -585,7 +1142,6 @@ sub setup_ad_member_rfc2307
        Samba::mk_krb5_conf($ctx, "");
 
        $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
-       $ret->{RESOLV_CONF} = $dcvars->{RESOLV_CONF};
 
        my $net = Samba::bindir_path($self, "net");
        # Add hosts file for name lookups
@@ -596,6 +1152,7 @@ sub setup_ad_member_rfc2307
        } else {
                $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
        }
+       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
        $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
        $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
        $cmd .= "$net join $ret->{CONFIGURATION}";
@@ -611,7 +1168,11 @@ sub setup_ad_member_rfc2307
        # access the share for tests.
        chmod 0777, "$prefix/share";
 
-       if (not $self->check_or_start($ret, "yes", "yes", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $ret,
+               nmbd => "yes",
+               winbindd => "yes",
+               smbd => "yes")) {
                return undef;
        }
 
@@ -621,11 +1182,15 @@ sub setup_ad_member_rfc2307
        $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
        $ret->{DC_USERNAME} = $dcvars->{USERNAME};
        $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
+       $ret->{DOMAIN_ADMIN} = $dcvars->{DOMAIN_ADMIN};
+       $ret->{DOMAIN_ADMIN_PASSWORD} = $dcvars->{DOMAIN_ADMIN_PASSWORD};
+       $ret->{DOMAIN_USER} = $dcvars->{DOMAIN_USER};
+       $ret->{DOMAIN_USER_PASSWORD} = $dcvars->{DOMAIN_USER_PASSWORD};
 
        return $ret;
 }
 
-sub setup_ad_member_idmap_rid
+sub setup_admem_idmap_autorid
 {
        my ($self, $prefix, $dcvars) = @_;
 
@@ -634,34 +1199,32 @@ sub setup_ad_member_idmap_rid
                return "UNKNOWN";
        }
 
-       print "PROVISIONING S3 AD MEMBER WITH idmap_rid config...";
+       print "PROVISIONING S3 AD MEMBER WITH idmap_autorid config...";
 
        my $member_options = "
        security = ads
        workgroup = $dcvars->{DOMAIN}
        realm = $dcvars->{REALM}
-       idmap config * : backend = tdb
-       idmap config * : range = 1000000-1999999
-       idmap config $dcvars->{DOMAIN} : backend = rid
-       idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
-       # Prevent overridding the provisioned lib/krb5.conf which sets certain
+       idmap config * : backend = autorid
+       idmap config * : range = 1000000-19999999
+       idmap config * : rangesize = 1000000
+
+       # Prevent overriding the provisioned lib/krb5.conf which sets certain
        # values required for tests to succeed
        create krb5 conf = no
-        map to guest = bad user
 ";
 
        my $ret = $self->provision(
            prefix => $prefix,
            domain => $dcvars->{DOMAIN},
-           server => "IDMAPRIDMEMBER",
+           realm => $dcvars->{REALM},
+           server => "ADMEMAUTORID",
            password => "loCalMemberPass",
            extra_options => $member_options,
-           dc_server_ip => $dcvars->{SERVER_IP},
-           dc_server_ipv6 => $dcvars->{SERVER_IPV6});
+           resolv_conf => $dcvars->{RESOLV_CONF});
 
        $ret or return undef;
 
-       close(USERMAP);
        $ret->{DOMAIN} = $dcvars->{DOMAIN};
        $ret->{REALM} = $dcvars->{REALM};
        $ret->{DOMSID} = $dcvars->{DOMSID};
@@ -679,7 +1242,6 @@ sub setup_ad_member_idmap_rid
        Samba::mk_krb5_conf($ctx, "");
 
        $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
-       $ret->{RESOLV_CONF} = $dcvars->{RESOLV_CONF};
 
        my $net = Samba::bindir_path($self, "net");
        # Add hosts file for name lookups
@@ -690,6 +1252,7 @@ sub setup_ad_member_idmap_rid
        } else {
                $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
        }
+       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
        $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
        $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
        $cmd .= "$net join $ret->{CONFIGURATION}";
@@ -705,7 +1268,11 @@ sub setup_ad_member_idmap_rid
        # access the share for tests.
        chmod 0777, "$prefix/share";
 
-       if (not $self->check_or_start($ret, "yes", "yes", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $ret,
+               nmbd => "yes",
+               winbindd => "yes",
+               smbd => "yes")) {
                return undef;
        }
 
@@ -715,11 +1282,15 @@ sub setup_ad_member_idmap_rid
        $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
        $ret->{DC_USERNAME} = $dcvars->{USERNAME};
        $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
+       $ret->{DOMAIN_ADMIN} = $dcvars->{DOMAIN_ADMIN};
+       $ret->{DOMAIN_ADMIN_PASSWORD} = $dcvars->{DOMAIN_ADMIN_PASSWORD};
+       $ret->{DOMAIN_USER} = $dcvars->{DOMAIN_USER};
+       $ret->{DOMAIN_USER_PASSWORD} = $dcvars->{DOMAIN_USER_PASSWORD};
 
        return $ret;
 }
 
-sub setup_ad_member_idmap_ad
+sub setup_ad_member_idmap_rid
 {
        my ($self, $prefix, $dcvars) = @_;
 
@@ -728,33 +1299,35 @@ sub setup_ad_member_idmap_ad
                return "UNKNOWN";
        }
 
-       print "PROVISIONING S3 AD MEMBER WITH idmap_ad config...";
+       print "PROVISIONING S3 AD MEMBER WITH idmap_rid config...";
 
        my $member_options = "
        security = ads
        workgroup = $dcvars->{DOMAIN}
        realm = $dcvars->{REALM}
-       password server = $dcvars->{SERVER}
        idmap config * : backend = tdb
        idmap config * : range = 1000000-1999999
-       idmap config $dcvars->{DOMAIN} : backend = ad
+       idmap config $dcvars->{DOMAIN} : backend = rid
        idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
-       idmap config $dcvars->{TRUST_DOMAIN} : backend = ad
-       idmap config $dcvars->{TRUST_DOMAIN} : range = 2000000-2999999
+       # Prevent overriding the provisioned lib/krb5.conf which sets certain
+       # values required for tests to succeed
+       create krb5 conf = no
+        map to guest = bad user
+       winbind expand groups = 10
+       server signing = required
 ";
 
        my $ret = $self->provision(
            prefix => $prefix,
            domain => $dcvars->{DOMAIN},
-           server => "IDMAPADMEMBER",
+           realm => $dcvars->{REALM},
+           server => "IDMAPRIDMEMBER",
            password => "loCalMemberPass",
            extra_options => $member_options,
-           dc_server_ip => $dcvars->{SERVER_IP},
-           dc_server_ipv6 => $dcvars->{SERVER_IPV6});
+           resolv_conf => $dcvars->{RESOLV_CONF});
 
        $ret or return undef;
 
-       close(USERMAP);
        $ret->{DOMAIN} = $dcvars->{DOMAIN};
        $ret->{REALM} = $dcvars->{REALM};
        $ret->{DOMSID} = $dcvars->{DOMSID};
@@ -772,7 +1345,6 @@ sub setup_ad_member_idmap_ad
        Samba::mk_krb5_conf($ctx, "");
 
        $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
-       $ret->{RESOLV_CONF} = $dcvars->{RESOLV_CONF};
 
        my $net = Samba::bindir_path($self, "net");
        # Add hosts file for name lookups
@@ -783,6 +1355,7 @@ sub setup_ad_member_idmap_ad
        } else {
                $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
        }
+       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
        $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
        $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
        $cmd .= "$net join $ret->{CONFIGURATION}";
@@ -798,7 +1371,11 @@ sub setup_ad_member_idmap_ad
        # access the share for tests.
        chmod 0777, "$prefix/share";
 
-       if (not $self->check_or_start($ret, "yes", "yes", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $ret,
+               nmbd => "yes",
+               winbindd => "yes",
+               smbd => "yes")) {
                return undef;
        }
 
@@ -808,38 +1385,351 @@ sub setup_ad_member_idmap_ad
        $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
        $ret->{DC_USERNAME} = $dcvars->{USERNAME};
        $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
-
-       $ret->{TRUST_SERVER} = $dcvars->{TRUST_SERVER};
-       $ret->{TRUST_USERNAME} = $dcvars->{TRUST_USERNAME};
-       $ret->{TRUST_PASSWORD} = $dcvars->{TRUST_PASSWORD};
-       $ret->{TRUST_DOMAIN} = $dcvars->{TRUST_DOMAIN};
-       $ret->{TRUST_REALM} = $dcvars->{TRUST_REALM};
-       $ret->{TRUST_DOMSID} = $dcvars->{TRUST_DOMSID};
+       $ret->{DOMAIN_ADMIN} = $dcvars->{DOMAIN_ADMIN};
+       $ret->{DOMAIN_ADMIN_PASSWORD} = $dcvars->{DOMAIN_ADMIN_PASSWORD};
+       $ret->{DOMAIN_USER} = $dcvars->{DOMAIN_USER};
+       $ret->{DOMAIN_USER_PASSWORD} = $dcvars->{DOMAIN_USER_PASSWORD};
 
        return $ret;
 }
 
-sub setup_simpleserver
+sub setup_ad_member_idmap_ad
 {
-       my ($self, $path) = @_;
-
-       print "PROVISIONING simple server...";
+       my ($self, $prefix, $dcvars) = @_;
 
-       my $prefix_abs = abs_path($path);
+       # If we didn't build with ADS, pretend this env was never available
+       if (not $self->have_ads()) {
+               return "UNKNOWN";
+       }
 
-       my $simpleserver_options = "
-       lanman auth = yes
-       ntlm auth = yes
-       vfs objects = xattr_tdb streams_depot
-       change notify = no
-       smb encrypt = off
+       print "PROVISIONING S3 AD MEMBER WITH idmap_ad config...";
 
-[vfs_aio_pthread]
+       my $member_options = "
+       security = ads
+       workgroup = $dcvars->{DOMAIN}
+       realm = $dcvars->{REALM}
+       password server = $dcvars->{SERVER}
+       idmap config * : backend = tdb
+       idmap config * : range = 1000000-1999999
+       idmap config $dcvars->{DOMAIN} : backend = ad
+       idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
+       idmap config $dcvars->{DOMAIN} : unix_primary_group = yes
+       idmap config $dcvars->{DOMAIN} : unix_nss_info = yes
+       idmap config $dcvars->{DOMAIN} : deny ous = \"ou=sub,DC=samba2008r2,DC=example,DC=com\"
+       idmap config $dcvars->{TRUST_DOMAIN} : backend = ad
+       idmap config $dcvars->{TRUST_DOMAIN} : range = 2000000-2999999
+       gensec_gssapi:requested_life_time = 5
+       winbind scan trusted domains = yes
+       winbind expand groups = 1
+";
+
+       my $ret = $self->provision(
+           prefix => $prefix,
+           domain => $dcvars->{DOMAIN},
+           realm => $dcvars->{REALM},
+           server => "IDMAPADMEMBER",
+           password => "loCalMemberPass",
+           extra_options => $member_options,
+           resolv_conf => $dcvars->{RESOLV_CONF});
+
+       $ret or return undef;
+
+       $ret->{DOMAIN} = $dcvars->{DOMAIN};
+       $ret->{REALM} = $dcvars->{REALM};
+       $ret->{DOMSID} = $dcvars->{DOMSID};
+
+       my $ctx;
+       my $prefix_abs = abs_path($prefix);
+       $ctx = {};
+       $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
+       $ctx->{domain} = $dcvars->{DOMAIN};
+       $ctx->{realm} = $dcvars->{REALM};
+       $ctx->{dnsname} = lc($dcvars->{REALM});
+       $ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
+       $ctx->{kdc_ipv6} = $dcvars->{SERVER_IPV6};
+       $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
+       Samba::mk_krb5_conf($ctx, "");
+
+       $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
+
+       my $net = Samba::bindir_path($self, "net");
+       # Add hosts file for name lookups
+       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
+       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
+               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
+       } else {
+               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
+       }
+       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
+       $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
+       $cmd .= "$net join $ret->{CONFIGURATION}";
+       $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
+
+       if (system($cmd) != 0) {
+           warn("Join failed\n$cmd");
+           return undef;
+       }
+
+       # We need world access to this share, as otherwise the domain
+       # administrator from the AD domain provided by Samba4 can't
+       # access the share for tests.
+       chmod 0777, "$prefix/share";
+
+       if (not $self->check_or_start(
+               env_vars => $ret,
+               nmbd => "yes",
+               winbindd => "yes",
+               smbd => "yes")) {
+               return undef;
+       }
+
+       $ret->{DC_SERVER} = $dcvars->{SERVER};
+       $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
+       $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6};
+       $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
+       $ret->{DC_USERNAME} = $dcvars->{USERNAME};
+       $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
+       $ret->{DOMAIN_ADMIN} = $dcvars->{DOMAIN_ADMIN};
+       $ret->{DOMAIN_ADMIN_PASSWORD} = $dcvars->{DOMAIN_ADMIN_PASSWORD};
+       $ret->{DOMAIN_USER} = $dcvars->{DOMAIN_USER};
+       $ret->{DOMAIN_USER_PASSWORD} = $dcvars->{DOMAIN_USER_PASSWORD};
+
+       $ret->{TRUST_SERVER} = $dcvars->{TRUST_SERVER};
+       $ret->{TRUST_USERNAME} = $dcvars->{TRUST_USERNAME};
+       $ret->{TRUST_PASSWORD} = $dcvars->{TRUST_PASSWORD};
+       $ret->{TRUST_DOMAIN} = $dcvars->{TRUST_DOMAIN};
+       $ret->{TRUST_REALM} = $dcvars->{TRUST_REALM};
+       $ret->{TRUST_DOMSID} = $dcvars->{TRUST_DOMSID};
+
+       return $ret;
+}
+
+sub setup_ad_member_oneway
+{
+       my ($self, $prefix, $dcvars) = @_;
+
+       # If we didn't build with ADS, pretend this env was never available
+       if (not $self->have_ads()) {
+               return "UNKNOWN";
+       }
+
+       print "PROVISIONING S3 AD MEMBER WITH one-way trust...";
+
+       my $member_options = "
+       security = ads
+       workgroup = $dcvars->{DOMAIN}
+       realm = $dcvars->{REALM}
+       password server = $dcvars->{SERVER}
+       idmap config * : backend = tdb
+       idmap config * : range = 1000000-1999999
+       gensec_gssapi:requested_life_time = 5
+";
+
+       my $ret = $self->provision(
+           prefix => $prefix,
+           domain => $dcvars->{DOMAIN},
+           server => "S2KMEMBER",
+           password => "loCalS2KMemberPass",
+           extra_options => $member_options,
+           resolv_conf => $dcvars->{RESOLV_CONF});
+
+       $ret or return undef;
+
+       $ret->{DOMAIN} = $dcvars->{DOMAIN};
+       $ret->{REALM} = $dcvars->{REALM};
+       $ret->{DOMSID} = $dcvars->{DOMSID};
+
+       my $ctx;
+       my $prefix_abs = abs_path($prefix);
+       $ctx = {};
+       $ctx->{krb5_conf} = "$prefix_abs/lib/krb5.conf";
+       $ctx->{domain} = $dcvars->{DOMAIN};
+       $ctx->{realm} = $dcvars->{REALM};
+       $ctx->{dnsname} = lc($dcvars->{REALM});
+       $ctx->{kdc_ipv4} = $dcvars->{SERVER_IP};
+       $ctx->{kdc_ipv6} = $dcvars->{SERVER_IPV6};
+       $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
+       Samba::mk_krb5_conf($ctx, "");
+
+       $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
+
+       my $net = Samba::bindir_path($self, "net");
+       # Add hosts file for name lookups
+       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
+       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
+               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
+       } else {
+               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
+       }
+       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
+       $cmd .= "SELFTEST_WINBINDD_SOCKET_DIR=\"$ret->{SELFTEST_WINBINDD_SOCKET_DIR}\" ";
+       $cmd .= "$net join $ret->{CONFIGURATION}";
+       $cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
+
+       if (system($cmd) != 0) {
+           warn("Join failed\n$cmd");
+           return undef;
+       }
+
+       if (not $self->check_or_start(
+               env_vars => $ret,
+               winbindd => "yes")) {
+               return undef;
+       }
+
+       $ret->{DC_SERVER} = $dcvars->{SERVER};
+       $ret->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
+       $ret->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6};
+       $ret->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
+       $ret->{DC_USERNAME} = $dcvars->{USERNAME};
+       $ret->{DC_PASSWORD} = $dcvars->{PASSWORD};
+       $ret->{DOMAIN_ADMIN} = $dcvars->{DOMAIN_ADMIN};
+       $ret->{DOMAIN_ADMIN_PASSWORD} = $dcvars->{DOMAIN_ADMIN_PASSWORD};
+       $ret->{DOMAIN_USER} = $dcvars->{DOMAIN_USER};
+       $ret->{DOMAIN_USER_PASSWORD} = $dcvars->{DOMAIN_USER_PASSWORD};
+
+       $ret->{TRUST_SERVER} = $dcvars->{TRUST_SERVER};
+       $ret->{TRUST_USERNAME} = $dcvars->{TRUST_USERNAME};
+       $ret->{TRUST_PASSWORD} = $dcvars->{TRUST_PASSWORD};
+       $ret->{TRUST_DOMAIN} = $dcvars->{TRUST_DOMAIN};
+       $ret->{TRUST_REALM} = $dcvars->{TRUST_REALM};
+       $ret->{TRUST_DOMSID} = $dcvars->{TRUST_DOMSID};
+
+       return $ret;
+}
+
+sub setup_ad_member_fips
+{
+       my ($self,
+           $prefix,
+           $dcvars,
+           $trustvars_f,
+           $trustvars_e) = @_;
+
+       # If we didn't build with ADS, pretend this env was never available
+       if (not $self->have_ads()) {
+               return "UNKNOWN";
+       }
+
+       print "PROVISIONING AD FIPS MEMBER...";
+
+       return $self->provision_ad_member($prefix,
+                                         "FIPSADMEMBER",
+                                         $dcvars,
+                                         $trustvars_f,
+                                         $trustvars_e,
+                                         undef,
+                                         1);
+}
+
+sub setup_ad_member_offlogon
+{
+       my ($self,
+           $prefix,
+           $dcvars,
+           $trustvars_f,
+           $trustvars_e) = @_;
+
+       # If we didn't build with ADS, pretend this env was never available
+       if (not $self->have_ads()) {
+               return "UNKNOWN";
+       }
+
+       print "PROVISIONING AD MEMBER OFFLINE LOGON...";
+
+       return $self->provision_ad_member($prefix,
+                                         "OFFLINEADMEM",
+                                         $dcvars,
+                                         $trustvars_f,
+                                         $trustvars_e,
+                                         undef,
+                                         undef,
+                                         1);
+}
+
+sub setup_ad_member_idmap_nss
+{
+       my ($self,
+           $prefix,
+           $dcvars,
+           $trustvars_f,
+           $trustvars_e) = @_;
+
+       # If we didn't build with ADS, pretend this env was never available
+       if (not $self->have_ads()) {
+               return "UNKNOWN";
+       }
+
+       print "PROVISIONING AD MEMBER WITHOUT NSS WINBIND WITH idmap_nss config...";
+
+       my $extra_member_options = "
+       # bob:x:65521:65531:localbob gecos:/:/bin/false
+       # jane:x:65520:65531:localjane gecos:/:/bin/false
+       # jackthemapper:x:65519:65531:localjackthemaper gecos:/:/bin/false
+       # jacknomapper:x:65518:65531:localjacknomaper gecos:/:/bin/false
+       idmap config $dcvars->{DOMAIN} : backend = nss
+       idmap config $dcvars->{DOMAIN} : range = 65518-65521
+
+       # Support SMB1 so that we can use posix_whoami().
+       client min protocol = CORE
+       server min protocol = LANMAN1
+
+       username map = $prefix/lib/username.map
+";
+
+       my $ret = $self->provision_ad_member($prefix,
+                                            "ADMEMIDMAPNSS",
+                                            $dcvars,
+                                            $trustvars_f,
+                                            $trustvars_e,
+                                            $extra_member_options,
+                                            undef,
+                                            undef,
+                                            1);
+
+       open(USERMAP, ">$prefix/lib/username.map") or die("Unable to open $prefix/lib/username.map");
+       print USERMAP "
+!jacknomapper = \@jackthemappergroup
+!root = jacknomappergroup
+root = $dcvars->{DOMAIN}/root
+bob = $dcvars->{DOMAIN}/bob
+";
+       close(USERMAP);
+
+       return $ret;
+}
+
+sub setup_simpleserver
+{
+       my ($self, $path) = @_;
+
+       print "PROVISIONING simple server...";
+
+       my $prefix_abs = abs_path($path);
+       mkdir($prefix_abs, 0777);
+
+       my $external_streams_depot="$prefix_abs/external_streams_depot";
+       remove_tree($external_streams_depot);
+       mkdir($external_streams_depot, 0777);
+
+       my $simpleserver_options = "
+       lanman auth = yes
+       ntlm auth = yes
+       vfs objects = xattr_tdb streams_depot
+       change notify = no
+       server smb encrypt = off
+        allow trusted domains = no
+
+[vfs_aio_pthread]
        path = $prefix_abs/share
        read only = no
        vfs objects = aio_pthread
        aio_pthread:aio open = yes
-       smbd:async dosmode = no
+       smbd async dosmode = no
 
 [vfs_aio_pthread_async_dosmode_default1]
        path = $prefix_abs/share
@@ -847,7 +1737,7 @@ sub setup_simpleserver
        vfs objects = aio_pthread
        store dos attributes = yes
        aio_pthread:aio open = yes
-       smbd:async dosmode = yes
+       smbd async dosmode = yes
 
 [vfs_aio_pthread_async_dosmode_default2]
        path = $prefix_abs/share
@@ -855,33 +1745,13 @@ sub setup_simpleserver
        vfs objects = aio_pthread xattr_tdb
        store dos attributes = yes
        aio_pthread:aio open = yes
-       smbd:async dosmode = yes
+       smbd async dosmode = yes
 
-[vfs_aio_pthread_async_dosmode_force_sync1]
-       path = $prefix_abs/share
-       read only = no
-       vfs objects = aio_pthread
-       store dos attributes = yes
-       aio_pthread:aio open = yes
-       smbd:async dosmode = yes
-       # This simulates non linux systems
-       smbd:force sync user path safe threadpool = yes
-       smbd:force sync user chdir safe threadpool = yes
-       smbd:force sync root path safe threadpool = yes
-       smbd:force sync root chdir safe threadpool = yes
-
-[vfs_aio_pthread_async_dosmode_force_sync2]
+[async_dosmode_shadow_copy2]
        path = $prefix_abs/share
        read only = no
-       vfs objects = aio_pthread xattr_tdb
-       store dos attributes = yes
-       aio_pthread:aio open = yes
-       smbd:async dosmode = yes
-       # This simulates non linux systems
-       smbd:force sync user path safe threadpool = yes
-       smbd:force sync user chdir safe threadpool = yes
-       smbd:force sync root path safe threadpool = yes
-       smbd:force sync root chdir safe threadpool = yes
+       vfs objects = shadow_copy2 xattr_tdb
+       smbd async dosmode = yes
 
 [vfs_aio_fork]
        path = $prefix_abs/share
@@ -896,14 +1766,14 @@ sub setup_simpleserver
        hide files = /hidefile/
        hide dot files = yes
 
-[enc_desired]
-       path = $prefix_abs/share
-       vfs objects =
-       smb encrypt = desired
-
 [hidenewfiles]
        path = $prefix_abs/share
        hide new files timeout = 5
+
+[external_streams_depot]
+       path = $prefix_abs/share
+       read only = no
+       streams_depot:directory = $external_streams_depot
 ";
 
        my $vars = $self->provision(
@@ -915,7 +1785,10 @@ sub setup_simpleserver
 
        $vars or return undef;
 
-       if (not $self->check_or_start($vars, "yes", "no", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $vars,
+               nmbd => "yes",
+               smbd => "yes")) {
               return undef;
        }
 
@@ -936,7 +1809,7 @@ sub create_file_chmod($$)
 
 sub setup_fileserver
 {
-       my ($self, $path) = @_;
+       my ($self, $path, $more_conf, $server) = @_;
        my $prefix_abs = abs_path($path);
        my $srcdir_abs = abs_path($self->{srcdir});
 
@@ -979,20 +1852,44 @@ sub setup_fileserver
        my $force_user_valid_users_dir = "$share_dir/force_user_valid_users";
        push(@dirs, $force_user_valid_users_dir);
 
-       my $smbget_sharedir="$share_dir/smbget";
-       push(@dirs,$smbget_sharedir);
-
        my $tarmode_sharedir="$share_dir/tarmode";
        push(@dirs,$tarmode_sharedir);
 
+       my $tarmode2_sharedir="$share_dir/tarmode2";
+       push(@dirs,$tarmode2_sharedir);
+
+       my $smbcacls_sharedir="$share_dir/smbcacls";
+       push(@dirs,$smbcacls_sharedir);
+
        my $usershare_sharedir="$share_dir/usershares";
        push(@dirs,$usershare_sharedir);
 
+       my $dropbox_sharedir="$share_dir/dropbox";
+       push(@dirs,$dropbox_sharedir);
+
+       my $bad_iconv_sharedir="$share_dir/bad_iconv";
+       push(@dirs, $bad_iconv_sharedir);
+
+       my $veto_sharedir="$share_dir/veto";
+       push(@dirs,$veto_sharedir);
+
+       my $virusfilter_sharedir="$share_dir/virusfilter";
+       push(@dirs,$virusfilter_sharedir);
+
+       my $delete_unwrite_sharedir="$share_dir/delete_unwrite";
+       push(@dirs,$delete_unwrite_sharedir);
+       push(@dirs, "$delete_unwrite_sharedir/delete_veto_yes");
+       push(@dirs, "$delete_unwrite_sharedir/delete_veto_no");
+
+       my $volume_serial_number_sharedir="$share_dir/volume_serial_number";
+       push(@dirs, $volume_serial_number_sharedir);
+
+       my $ip4 = Samba::get_ipv4_addr("FILESERVER");
        my $fileserver_options = "
+        smb3 unix extensions = yes
        kernel change notify = yes
-       rpc_server:mdssvc = embedded
        spotlight backend = elasticsearch
-       elasticsearch:address = 127.0.0.35
+       elasticsearch:address = $ip4
        elasticsearch:port = 8080
        elasticsearch:mappings = $srcdir_abs/source3/rpc_server/mdssvc/elasticsearch_mappings.json
 
@@ -1003,6 +1900,14 @@ sub setup_fileserver
 
        get quota command = $prefix_abs/getset_quota.py
        set quota command = $prefix_abs/getset_quota.py
+[tarmode]
+       path = $tarmode_sharedir
+       comment = tar test share
+       xattr_tdb:file = $prefix_abs/tarmode-xattr.tdb
+[tarmode2]
+       path = $tarmode2_sharedir
+       comment = tar test share
+       xattr_tdb:file = $prefix_abs/tarmode2-xattr.tdb
 [spotlight]
        path = $share_dir
        spotlight = yes
@@ -1046,10 +1951,6 @@ sub setup_fileserver
        force group = everyone
        write list = force_user
 
-[smbget]
-       path = $smbget_sharedir
-       comment = smb username is [%U]
-       guest ok = yes
 [ign_sysacls]
        path = $share_dir
        comment = ignore system acls
@@ -1068,23 +1969,114 @@ sub setup_fileserver
        path = $share_dir
        comment = force group test
 #      force group = everyone
+
+[create_mode_664]
+       path = $share_dir
+       comment = smb username is [%U]
+       create mask = 0644
+       force create mode = 0664
+       vfs objects = dirsort
+
+[dropbox]
+       path = $dropbox_sharedir
+       comment = smb username is [%U]
+       writeable = yes
+       vfs objects =
+
+[bad_iconv]
+       path = $bad_iconv_sharedir
+       comment = smb username is [%U]
+       vfs objects =
+
+[veto_files_nodelete]
+       path = $veto_sharedir
+       read only = no
+       msdfs root = yes
+       veto files = /veto_name*/
+       delete veto files = no
+
+[veto_files_delete]
+       path = $veto_sharedir
+       msdfs root = yes
+       veto files = /veto_name*/
+       delete veto files = yes
+
+[delete_veto_files_only]
+       path = $veto_sharedir
+       delete veto files = yes
+
+[veto_files_nohidden]
+       path = $veto_sharedir
+       veto files = /.*/
+
+[veto_files]
+       path = $veto_sharedir
+       veto files = /veto_name*/
+
+[delete_yes_unwrite]
+       read only = no
+       path = $delete_unwrite_sharedir
+       hide unwriteable files = yes
+       delete veto files = yes
+
+[delete_no_unwrite]
+       read only = no
+       path = $delete_unwrite_sharedir
+       hide unwriteable files = yes
+       delete veto files = no
+
+[virusfilter]
+       path = $virusfilter_sharedir
+       vfs objects = acl_xattr virusfilter
+       virusfilter:scanner = dummy
+       virusfilter:min file size = 0
+       virusfilter:infected files = *infected*
+       virusfilter:infected file action = rename
+       virusfilter:scan on close = yes
+       vfs_default:VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS = no
+
+[volumeserialnumber]
+       path = $volume_serial_number_sharedir
+       volume serial number = 0xdeadbeef
+
+[ea_acl_xattr]
+       path = $share_dir
+       vfs objects = acl_xattr
+       acl_xattr:security_acl_name = user.hackme
+       read only = no
+
+[io_uring]
+       path = $share_dir
+       vfs objects = acl_xattr fake_acls xattr_tdb streams_depot time_audit full_audit io_uring
+       read only = no
+
 [homes]
        comment = Home directories
        browseable = No
        read only = No
 ";
 
+       if (defined($more_conf)) {
+               $fileserver_options = $fileserver_options . $more_conf;
+       }
+       if (!defined($server)) {
+               $server = "FILESERVER";
+       }
+
        my $vars = $self->provision(
            prefix => $path,
            domain => "WORKGROUP",
-           server => "FILESERVER",
+           server => $server,
            password => "fileserver",
            extra_options => $fileserver_options,
            no_delete_prefix => 1);
 
        $vars or return undef;
 
-       if (not $self->check_or_start($vars, "yes", "no", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $vars,
+               nmbd => "yes",
+               smbd => "yes")) {
               return undef;
        }
 
@@ -1130,9 +2122,73 @@ sub setup_fileserver
        ##
        create_file_chmod("$valid_users_sharedir/foo", 0644) or return undef;
 
+       ##
+       ## create a valid utf8 filename which is invalid as a CP850 conversion
+       ##
+       create_file_chmod("$bad_iconv_sharedir/\xED\x9F\xBF", 0644) or return undef;
+
+       ##
+       ## create unwritable files inside inside the delete unwrite veto share dirs.
+       ##
+       unlink("$delete_unwrite_sharedir/delete_veto_yes/file_444");
+       create_file_chmod("$delete_unwrite_sharedir/delete_veto_yes/file_444", 0444) or return undef;
+       unlink("$delete_unwrite_sharedir/delete_veto_no/file_444");
+       create_file_chmod("$delete_unwrite_sharedir/delete_veto_no/file_444", 0444) or return undef;
+
        return $vars;
 }
 
+sub setup_fileserver_smb1
+{
+       my ($self, $path) = @_;
+       my $prefix_abs = abs_path($path);
+       my $conf = "
+[global]
+       client min protocol = CORE
+       server min protocol = LANMAN1
+       check parent directory delete on close = yes
+
+[hidenewfiles]
+       path = $prefix_abs/share
+       hide new files timeout = 5
+[vfs_aio_pthread]
+       path = $prefix_abs/share
+       read only = no
+       vfs objects = aio_pthread
+       aio_pthread:aio open = yes
+       smbd async dosmode = no
+
+[vfs_aio_pthread_async_dosmode_default1]
+       path = $prefix_abs/share
+       read only = no
+       vfs objects = aio_pthread
+       store dos attributes = yes
+       aio_pthread:aio open = yes
+       smbd async dosmode = yes
+
+[vfs_aio_pthread_async_dosmode_default2]
+       path = $prefix_abs/share
+       read only = no
+       vfs objects = aio_pthread xattr_tdb
+       store dos attributes = yes
+       aio_pthread:aio open = yes
+       smbd async dosmode = yes
+
+[vfs_aio_fork]
+       path = $prefix_abs/share
+        vfs objects = aio_fork
+        read only = no
+        vfs_aio_fork:erratic_testing_mode=yes
+";
+       return $self->setup_fileserver($path, $conf, "FILESERVERSMB1");
+}
+
+sub setup_fileserver_smb1_done
+{
+       my ($self, $path, $dep_env) = @_;
+       return $self->return_alias_env($path, $dep_env);
+}
+
 sub setup_ktest
 {
        my ($self, $prefix) = @_;
@@ -1148,7 +2204,6 @@ sub setup_ktest
         workgroup = KTEST
         realm = ktest.samba.example.com
        security = ads
-        username map = $prefix/lib/username.map
         server signing = required
        server min protocol = SMB3_00
        client max protocol = SMB3
@@ -1156,6 +2211,10 @@ sub setup_ktest
         # This disables NTLM auth against the local SAM, which
         # we use can then test this setting by.
         ntlm auth = disabled
+
+        idmap config * : backend = autorid
+        idmap config * : range = 1000000-1999999
+        idmap config * : rangesize = 100000
 ";
 
        my $ret = $self->provision(
@@ -1176,16 +2235,10 @@ sub setup_ktest
        $ctx->{dnsname} = lc($ctx->{realm});
        $ctx->{kdc_ipv4} = "0.0.0.0";
        $ctx->{kdc_ipv6} = "::";
-       $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
-       Samba::mk_krb5_conf($ctx, "");
-
-       $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
-
-       open(USERMAP, ">$prefix/lib/username.map") or die("Unable to open $prefix/lib/username.map");
-       print USERMAP "
-$ret->{USERNAME} = KTEST\\Administrator
-";
-       close(USERMAP);
+       $ctx->{krb5_ccname} = "$prefix_abs/krb5cc_%{uid}";
+       Samba::mk_krb5_conf($ctx, "");
+
+       $ret->{KRB5_CONFIG} = $ctx->{krb5_conf};
 
 #This is the secrets.tdb created by 'net ads join' from Samba3 to a
 #Samba4 DC with the same parameters as are being used here.  The
@@ -1235,7 +2288,11 @@ $ret->{USERNAME} = KTEST\\Administrator
        # access the share for tests.
        chmod 0777, "$prefix/share";
 
-       if (not $self->check_or_start($ret, "yes", "no", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $ret,
+               nmbd => "yes",
+               winbindd => "offline",
+               smbd => "yes")) {
               return undef;
        }
        return $ret;
@@ -1244,12 +2301,24 @@ $ret->{USERNAME} = KTEST\\Administrator
 sub setup_maptoguest
 {
        my ($self, $path) = @_;
+       my $prefix_abs = abs_path($path);
+       my $libdir="$prefix_abs/lib";
+       my $share_dir="$prefix_abs/share";
+       my $errorinjectconf="$libdir/error_inject.conf";
 
        print "PROVISIONING maptoguest...";
 
        my $options = "
+domain logons = yes
 map to guest = bad user
 ntlm auth = yes
+server min protocol = LANMAN1
+
+[force_user_error_inject]
+       path = $share_dir
+       vfs objects = acl_xattr fake_acls xattr_tdb error_inject
+       force user = user1
+       include = $errorinjectconf
 ";
 
        my $vars = $self->provision(
@@ -1261,7 +2330,11 @@ ntlm auth = yes
 
        $vars or return undef;
 
-       if (not $self->check_or_start($vars, "yes", "no", "yes")) {
+       if (not $self->check_or_start(
+               env_vars => $vars,
+               nmbd => "yes",
+               winbindd => "yes",
+               smbd => "yes")) {
               return undef;
        }
 
@@ -1302,7 +2375,7 @@ sub make_bin_cmd
 {
        my ($self, $binary, $env_vars, $options, $valgrind, $dont_log_stdout) = @_;
 
-       my @optargs = ("-d0");
+       my @optargs = ();
        if (defined($options)) {
                @optargs = split(/ /, $options);
        }
@@ -1312,17 +2385,24 @@ sub make_bin_cmd
                @preargs = split(/ /, $valgrind);
        }
        my @args = ("-F", "--no-process-group",
-                   "-s", $env_vars->{SERVERCONFFILE},
+                   "--configfile=$env_vars->{SERVERCONFFILE}",
                    "-l", $env_vars->{LOGDIR});
 
        if (not defined($dont_log_stdout)) {
-               push(@args, "--log-stdout");
+               push(@args, "--debug-stdout");
        }
        return (@preargs, $binary, @args, @optargs);
 }
 
-sub check_or_start($$$$$) {
-       my ($self, $env_vars, $nmbd, $winbindd, $smbd) = @_;
+sub check_or_start($$) {
+       my ($self, %args) = @_;
+       my $env_vars = $args{env_vars};
+       my $nmbd = $args{nmbd} // "no";
+       my $winbindd = $args{winbindd} // "no";
+       my $smbd = $args{smbd} // "no";
+       my $samba_dcerpcd = $args{samba_dcerpcd} // "no";
+       my $child_cleanup = $args{child_cleanup};
+
        my $STDIN_READER;
 
        # use a pipe for stdin in the child processes. This allows
@@ -1330,37 +2410,68 @@ sub check_or_start($$$$$) {
        # exit when the test script exits
        pipe($STDIN_READER, $env_vars->{STDIN_PIPE});
 
-       my $binary = Samba::bindir_path($self, "nmbd");
-       my @full_cmd = $self->make_bin_cmd($binary, $env_vars,
-                                          $ENV{NMBD_OPTIONS}, $ENV{NMBD_VALGRIND},
-                                          $ENV{NMBD_DONT_LOG_STDOUT});
+       my $binary = Samba::bindir_path($self, "samba-dcerpcd");
+       my @full_cmd = $self->make_bin_cmd(
+           $binary,
+           $env_vars,
+           $ENV{SAMBA_DCERPCD_OPTIONS},
+           $ENV{SAMBA_DCERPCD_VALGRIND},
+           $ENV{SAMBA_DCERPCD_DONT_LOG_STDOUT});
+       push(@full_cmd, '--libexec-rpcds');
+
+       my $samba_dcerpcd_envs = Samba::get_env_for_process(
+           "samba_dcerpcd", $env_vars);
+
+       # fork and exec() samba_dcerpcd in the child process
+       my $daemon_ctx = {
+               NAME => "samba_dcerpcd",
+               BINARY_PATH => $binary,
+               FULL_CMD => [ @full_cmd ],
+               LOG_FILE => $env_vars->{SAMBA_DCERPCD_TEST_LOG},
+               PCAP_FILE => "env-$ENV{ENVNAME}-samba_dcerpcd",
+               ENV_VARS => $samba_dcerpcd_envs,
+       };
+       if ($samba_dcerpcd ne "yes") {
+               $daemon_ctx->{SKIP_DAEMON} = 1;
+       }
+
+       my $pid = Samba::fork_and_exec(
+           $self, $env_vars, $daemon_ctx, $STDIN_READER, $child_cleanup);
+
+       $env_vars->{SAMBA_DCERPCD_TL_PID} = $pid;
+       write_pid($env_vars, "samba_dcerpcd", $pid);
+
+       $binary = Samba::bindir_path($self, "nmbd");
+       @full_cmd = $self->make_bin_cmd($binary, $env_vars,
+                                       $ENV{NMBD_OPTIONS}, $ENV{NMBD_VALGRIND},
+                                       $ENV{NMBD_DONT_LOG_STDOUT});
        my $nmbd_envs = Samba::get_env_for_process("nmbd", $env_vars);
        delete $nmbd_envs->{RESOLV_WRAPPER_CONF};
        delete $nmbd_envs->{RESOLV_WRAPPER_HOSTS};
 
        # fork and exec() nmbd in the child process
-       my $daemon_ctx = {
+       $daemon_ctx = {
                NAME => "nmbd",
                BINARY_PATH => $binary,
                FULL_CMD => [ @full_cmd ],
                LOG_FILE => $env_vars->{NMBD_TEST_LOG},
+               PCAP_FILE => "env-$ENV{ENVNAME}-nmbd",
                ENV_VARS => $nmbd_envs,
        };
        if ($nmbd ne "yes") {
                $daemon_ctx->{SKIP_DAEMON} = 1;
        }
-       my $pid = Samba::fork_and_exec($self, $env_vars, $daemon_ctx, $STDIN_READER);
+       $pid = Samba::fork_and_exec(
+           $self, $env_vars, $daemon_ctx, $STDIN_READER, $child_cleanup);
 
        $env_vars->{NMBD_TL_PID} = $pid;
        write_pid($env_vars, "nmbd", $pid);
 
        $binary = Samba::bindir_path($self, "winbindd");
        @full_cmd = $self->make_bin_cmd($binary, $env_vars,
-                                        $ENV{WINBINDD_OPTIONS}, $ENV{WINBINDD_VALGRIND}, "N/A");
-
-       if (not defined($ENV{WINBINDD_DONT_LOG_STDOUT})) {
-               push(@full_cmd, "--stdout");
-       }
+                                        $ENV{WINBINDD_OPTIONS},
+                                        $ENV{WINBINDD_VALGRIND},
+                                        $ENV{WINBINDD_DONT_LOG_STDOUT});
 
        # fork and exec() winbindd in the child process
        $daemon_ctx = {
@@ -1368,11 +2479,14 @@ sub check_or_start($$$$$) {
                BINARY_PATH => $binary,
                FULL_CMD => [ @full_cmd ],
                LOG_FILE => $env_vars->{WINBINDD_TEST_LOG},
+               PCAP_FILE => "env-$ENV{ENVNAME}-winbindd",
        };
-       if ($winbindd ne "yes") {
+       if ($winbindd ne "yes" and $winbindd ne "offline") {
                $daemon_ctx->{SKIP_DAEMON} = 1;
        }
-       $pid = Samba::fork_and_exec($self, $env_vars, $daemon_ctx, $STDIN_READER);
+
+       $pid = Samba::fork_and_exec(
+           $self, $env_vars, $daemon_ctx, $STDIN_READER, $child_cleanup);
 
        $env_vars->{WINBINDD_TL_PID} = $pid;
        write_pid($env_vars, "winbindd", $pid);
@@ -1388,12 +2502,14 @@ sub check_or_start($$$$$) {
                BINARY_PATH => $binary,
                FULL_CMD => [ @full_cmd ],
                LOG_FILE => $env_vars->{SMBD_TEST_LOG},
+               PCAP_FILE => "env-$ENV{ENVNAME}-smbd",
        };
        if ($smbd ne "yes") {
                $daemon_ctx->{SKIP_DAEMON} = 1;
        }
 
-       $pid = Samba::fork_and_exec($self, $env_vars, $daemon_ctx, $STDIN_READER);
+       $pid = Samba::fork_and_exec(
+           $self, $env_vars, $daemon_ctx, $STDIN_READER, $child_cleanup);
 
        $env_vars->{SMBD_TL_PID} = $pid;
        write_pid($env_vars, "smbd", $pid);
@@ -1401,7 +2517,11 @@ sub check_or_start($$$$$) {
        # close the parent's read-end of the pipe
        close($STDIN_READER);
 
-       return $self->wait_for_start($env_vars, $nmbd, $winbindd, $smbd);
+       return $self->wait_for_start($env_vars,
+                               $nmbd,
+                               $winbindd,
+                               $smbd,
+                               $samba_dcerpcd);
 }
 
 sub createuser($$$$$)
@@ -1431,12 +2551,14 @@ sub provision($$)
 
        my $prefix = $args{prefix};
        my $domain = $args{domain};
+       my $realm = $args{realm};
        my $server = $args{server};
        my $password = $args{password};
        my $extra_options = $args{extra_options};
-       my $dc_server_ip = $args{dc_server_ip};
-       my $dc_server_ipv6 = $args{dc_server_ipv6};
+       my $resolv_conf = $args{resolv_conf};
        my $no_delete_prefix= $args{no_delete_prefix};
+       my $netbios_name = $args{netbios_name} // $server;
+       my $server_log_level = $ENV{SERVER_LOG_LEVEL} || 1;
 
        ##
        ## setup the various environment variables we need
@@ -1448,6 +2570,12 @@ sub provision($$)
        my %createuser_env = ();
        my $server_ip = Samba::get_ipv4_addr($server);
        my $server_ipv6 = Samba::get_ipv6_addr($server);
+       my $dns_domain;
+       if (defined($realm)) {
+           $dns_domain = lc($realm);
+       } else {
+           $dns_domain = "samba.example.com";
+       }
 
        my $unix_name = ($ENV{USER} or $ENV{LOGNAME} or `PATH=/usr/ucb:$ENV{PATH} whoami`);
        chomp $unix_name;
@@ -1460,7 +2588,7 @@ sub provision($$)
 
        my @dirs = ();
 
-       my $shrdir="$prefix_abs/share";
+       my $shrdir=$args{share_dir} // "$prefix_abs/share";
        push(@dirs,$shrdir);
 
        my $libdir="$prefix_abs/lib";
@@ -1505,18 +2633,33 @@ sub provision($$)
        my $msdfs_shrdir="$shrdir/msdfsshare";
        push(@dirs,$msdfs_shrdir);
 
+       my $msdfs_shrdir2="$shrdir/msdfsshare2";
+       push(@dirs,$msdfs_shrdir2);
+
+       my $msdfs_pathname_share="$shrdir/msdfs_pathname_share";
+       push(@dirs,$msdfs_pathname_share);
+
+       my $non_msdfs_pathname_share="$shrdir/non_msdfs_pathname_share";
+       push(@dirs,$non_msdfs_pathname_share);
+
        my $msdfs_deeppath="$msdfs_shrdir/deeppath";
        push(@dirs,$msdfs_deeppath);
 
+       my $smbcacls_sharedir_dfs="$shrdir/smbcacls_sharedir_dfs";
+       push(@dirs,$smbcacls_sharedir_dfs);
+
+       my $smbcacls_share="$shrdir/smbcacls_share";
+       push(@dirs,$smbcacls_share);
+
+       my $smbcacls_share_testdir="$shrdir/smbcacls_share/smbcacls";
+       push(@dirs,$smbcacls_share_testdir);
+
        my $badnames_shrdir="$shrdir/badnames";
        push(@dirs,$badnames_shrdir);
 
-       my $lease1_shrdir="$shrdir/SMB2_10";
+       my $lease1_shrdir="$shrdir/dynamic";
        push(@dirs,$lease1_shrdir);
 
-       my $lease2_shrdir="$shrdir/SMB3_00";
-       push(@dirs,$lease2_shrdir);
-
        my $manglenames_shrdir="$shrdir/manglenames";
        push(@dirs,$manglenames_shrdir);
 
@@ -1544,13 +2687,28 @@ sub provision($$)
        my $local_symlinks_shrdir="$shrdir/local_symlinks";
        push(@dirs,$local_symlinks_shrdir);
 
+       my $worm_shrdir="$shrdir/worm";
+       push(@dirs,$worm_shrdir);
+
+       my $fruit_resource_stream_shrdir="$shrdir/fruit_resource_stream";
+       push(@dirs,$fruit_resource_stream_shrdir);
+
+       my $smbget_sharedir="$shrdir/smbget";
+       push(@dirs, $smbget_sharedir);
+
+       my $recycle_shrdir="$shrdir/recycle";
+       push(@dirs,$recycle_shrdir);
+
+       my $fakedircreatetimes_shrdir="$shrdir/fakedircreatetimes";
+       push(@dirs,$fakedircreatetimes_shrdir);
+
        # this gets autocreated by winbindd
-       my $wbsockdir="$prefix_abs/winbindd";
+       my $wbsockdir="$prefix_abs/wbsock";
 
        my $nmbdsockdir="$prefix_abs/nmbd";
        unlink($nmbdsockdir);
 
-       ## 
+       ##
        ## create the test directory layout
        ##
        die ("prefix_abs = ''") if $prefix_abs eq "";
@@ -1583,13 +2741,18 @@ sub provision($$)
 
        chmod 0755, $ro_shrdir;
 
+       create_file_chmod("$ro_shrdir/readable_file", 0644) or return undef;
        create_file_chmod("$ro_shrdir/unreadable_file", 0600) or return undef;
 
        create_file_chmod("$ro_shrdir/msdfs-target", 0600) or return undef;
        symlink "msdfs:$server_ip\\ro-tmp,$server_ipv6\\ro-tmp",
                "$msdfs_shrdir/msdfs-src1";
        symlink "msdfs:$server_ipv6\\ro-tmp", "$msdfs_shrdir/deeppath/msdfs-src2";
+       symlink "msdfs:$server_ip\\smbcacls_sharedir_dfs,$server_ipv6\\smbcacls_sharedir_dfs",
+               "$msdfs_shrdir/smbcacls_sharedir_dfs";
 
+       symlink "msdfs:$server_ip\\msdfs-share2,$server_ipv6\\msdfs-share2", "$msdfs_shrdir/dfshop1";
+       symlink "msdfs:$server_ip\\tmp,$server_ipv6\\tmp", "$msdfs_shrdir2/dfshop2";
        ##
        ## create bad names in $badnames_shrdir
        ##
@@ -1618,7 +2781,7 @@ sub provision($$)
        create_file_chmod("$widelinks_target", 0666) or return undef;
 
        ##
-       ## This link should get ACCESS_DENIED
+       ## This link should get an error
        ##
        symlink "$widelinks_target", "$widelinks_shrdir/source";
        ##
@@ -1631,12 +2794,13 @@ sub provision($$)
        my $errorinjectconf="$libdir/error_inject.conf";
        my $delayinjectconf="$libdir/delay_inject.conf";
        my $globalinjectconf="$libdir/global_inject.conf";
+       my $aliceconfdir="$libdir";
+       my $aliceconffile="$libdir/alice.conf";
 
        my $nss_wrapper_pl = "$ENV{PERL} $self->{srcdir}/third_party/nss_wrapper/nss_wrapper.pl";
        my $nss_wrapper_passwd = "$privatedir/passwd";
        my $nss_wrapper_group = "$privatedir/group";
        my $nss_wrapper_hosts = "$ENV{SELFTEST_PREFIX}/hosts";
-       my $resolv_conf = "$privatedir/resolv.conf";
        my $dns_host_file = "$ENV{SELFTEST_PREFIX}/dns_host_file";
 
        my $mod_printer_pl = "$ENV{PERL} $self->{srcdir}/source3/script/tests/printing/modprinter.pl";
@@ -1657,11 +2821,17 @@ sub provision($$)
        my ($gid_nobody, $gid_nogroup, $gid_root, $gid_domusers, $gid_domadmins);
        my ($gid_userdup, $gid_everyone);
        my ($gid_force_user);
+       my ($gid_jackthemapper);
+       my ($gid_jacknomapper);
        my ($uid_user1);
        my ($uid_user2);
        my ($uid_gooduser);
        my ($uid_eviluser);
        my ($uid_slashuser);
+       my ($uid_localbob);
+       my ($uid_localjane);
+       my ($uid_localjackthemapper);
+       my ($uid_localjacknomapper);
 
        if ($unix_uid < 0xffff - 13) {
                $max_uid = 0xffff;
@@ -1682,6 +2852,10 @@ sub provision($$)
        $uid_gooduser = $max_uid - 11;
        $uid_eviluser = $max_uid - 12;
        $uid_slashuser = $max_uid - 13;
+       $uid_localbob = $max_uid - 14;
+       $uid_localjane = $max_uid - 15;
+       $uid_localjackthemapper = $max_uid - 16;
+       $uid_localjacknomapper = $max_uid - 17;
 
        if ($unix_gids[0] < 0xffff - 8) {
                $max_gid = 0xffff;
@@ -1697,6 +2871,8 @@ sub provision($$)
        $gid_userdup = $max_gid - 6;
        $gid_everyone = $max_gid - 7;
        $gid_force_user = $max_gid - 8;
+       $gid_jackthemapper = $max_gid - 9;
+       $gid_jacknomapper = $max_gid - 10;
 
        ##
        ## create conffile
@@ -1712,14 +2888,18 @@ sub provision($$)
        print CONF "
 [global]
         dcesrv:fuzz directory = $cachedir/fuzz
-       netbios name = $server
+       netbios name = $netbios_name
        interfaces = $interfaces
        bind interfaces only = yes
        panic action = cd $self->{srcdir} && $self->{srcdir}/selftest/gdb_backtrace %d %\$(MAKE_TEST_BINARY)
        smbd:suicide mode = yes
+       smbd:FSCTL_SMBTORTURE = yes
+       smbd:validate_oplock_types = yes
 
-       client min protocol = CORE
-       server min protocol = LANMAN1
+       client min protocol = SMB2_02
+       server min protocol = SMB2_02
+
+       server multi channel support = yes
 
        workgroup = $domain
 
@@ -1728,10 +2908,14 @@ sub provision($$)
        pid directory = $piddir
        lock directory = $lockdir
        log file = $logdir/log.\%m
-       log level = 1
+       log level = $server_log_level
+       winbind debug traceid = yes
        debug pid = yes
         max log size = 0
 
+       debug syslog format = always
+       debug hires timestamp = yes
+
        state directory = $lockdir
        cache directory = $lockdir
 
@@ -1834,6 +3018,14 @@ sub provision($$)
        }
 
        print CONF "
+[smbcacls_share]
+       path = $smbcacls_share
+        comment = smb username is [%U]
+       msdfs root = yes
+
+[smbcacls_sharedir_dfs]
+       path = $smbcacls_sharedir_dfs
+        comment = smb username is [%U]
 [tmp]
        path = $shrdir
         comment = smb username is [%U]
@@ -1844,7 +3036,7 @@ sub provision($$)
 [tmpenc]
        path = $shrdir
        comment = encrypt smb username is [%U]
-       smb encrypt = required
+       server smb encrypt = required
        vfs objects = dirsort
 [tmpguest]
        path = $shrdir
@@ -1891,6 +3083,23 @@ sub provision($$)
        msdfs root = yes
        msdfs shuffle referrals = yes
        guest ok = yes
+[msdfs-share-wl]
+       path = $msdfs_shrdir
+       msdfs root = yes
+       wide links = yes
+       guest ok = yes
+[msdfs-share2]
+       path = $msdfs_shrdir2
+       msdfs root = yes
+       guest ok = yes
+[msdfs-pathname-share]
+       path = $msdfs_pathname_share
+       msdfs root = yes
+       guest ok = yes
+[non-msdfs-pathname-share]
+       path = $non_msdfs_pathname_share
+       msdfs root = no
+       guest ok = yes
 [hideunread]
        copy = tmp
        hide unreadable = yes
@@ -1917,6 +3126,11 @@ sub provision($$)
 [print3]
        copy = print1
        default devmode = no
+
+[print_var_exp]
+       copy = print1
+       print command = $self->{srcdir}/source3/script/tests/printing/printing_var_exp_lpr_cmd.sh \"Windows user: %U\" \"UNIX user: %u\" \"Domain: %D\"
+
 [lp]
        copy = print1
 
@@ -1987,8 +3201,16 @@ sub provision($$)
        directory mask = 0777
        force directory mode = 0
        vfs objects = xattr_tdb streams_depot
+[smb3_posix_share]
+       vfs objects = fake_acls xattr_tdb streams_depot time_audit full_audit
+       create mask = 07777
+       directory mask = 07777
+       mangled names = no
+       path = $shrdir
+       read only = no
+       guest ok = yes
 [aio]
-       copy = tmp
+       copy = durable
        aio read size = 1
        aio write size = 1
 
@@ -2068,6 +3290,13 @@ sub provision($$)
        fruit:resource = file
        fruit:metadata = stream
        fruit:zero_file_id=yes
+       fruit:validate_afpinfo = no
+
+[fruit_resource_stream]
+       path = $fruit_resource_stream_shrdir
+       vfs objects = fruit streams_xattr acl_xattr xattr_tdb
+       fruit:resource = stream
+       fruit:metadata = stream
 
 [badname-tmp]
        path = $badnames_shrdir
@@ -2078,8 +3307,9 @@ sub provision($$)
        guest ok = yes
 
 [dynamic_share]
-       path = $shrdir/%R
+       path = $shrdir/dynamic/%t
        guest ok = yes
+       root preexec = mkdir %P
 
 [widelinks_share]
        path = $widelinks_shrdir
@@ -2088,7 +3318,7 @@ sub provision($$)
 
 [fsrvp_share]
        path = $fsrvp_shrdir
-       comment = fake shapshots using rsync
+       comment = fake snapshots using rsync
        vfs objects = shell_snap shadow_copy2
        shell_snap:check path command = $fake_snap_pl --check
        shell_snap:create command = $fake_snap_pl --create
@@ -2232,10 +3462,15 @@ sub provision($$)
 [shadow_write]
        path = $shadow_tstdir
        comment = previous versions snapshots under mount point
-       vfs objects = shadow_copy2 streams_xattr error_inject
-       aio write size = 0
-       error_inject:pwrite = EBADF
+       vfs objects = shadow_copy2 streams_xattr
        shadow:mountpoint = $shadow_tstdir
+       shadow:fixinodes = yes
+       smbd async dosmode = yes
+
+[shadow_depot]
+       path = $shadow_shrdir
+       comment = previous versions with streams_depot
+       vfs objects = streams_depot shadow_copy2
 
 [dfq]
        path = $shrdir/dfree
@@ -2274,12 +3509,22 @@ sub provision($$)
        copy = tmp
        path = $nosymlinks_shrdir
        follow symlinks = no
+[nosymlinks_smb1allow]
+       copy=nosymlinks
+       follow symlinks = yes
 
 [local_symlinks]
        copy = tmp
        path = $local_symlinks_shrdir
        follow symlinks = yes
 
+[worm]
+       copy = tmp
+       path = $worm_shrdir
+       vfs objects = worm
+       worm:grace_period = 1
+       comment = vfs_worm with 1s grace_period
+
 [kernel_oplocks]
        copy = tmp
        kernel oplocks = yes
@@ -2289,6 +3534,18 @@ sub provision($$)
        copy = tmp
        vfs objects = streams_xattr xattr_tdb
 
+[streams_xattr_nostrict]
+       copy = tmp
+       strict rename = no
+       vfs objects = streams_xattr xattr_tdb
+
+[acl_streams_xattr]
+       copy = tmp
+       vfs objects = acl_xattr streams_xattr fake_acls xattr_tdb
+       acl_xattr:ignore system acls = yes
+       acl_xattr:security_acl_name = user.acl
+       xattr_tdb:ignore_user_xattr = yes
+
 [compound_find]
        copy = tmp
        smbd:find async delay usec = 10000
@@ -2326,16 +3583,73 @@ sub provision($$)
 [delete_readonly]
        path = $prefix_abs/share
        delete readonly = yes
+
+[enc_desired]
+       path = $prefix_abs/share
+       vfs objects =
+       server smb encrypt = desired
+
+[enc_off]
+       path = $prefix_abs/share
+       vfs objects =
+       server smb encrypt = off
+
+[notify_priv]
+       copy = tmp
+       honor change notify privilege = yes
+
+[acls_non_canonical]
+       copy = tmp
+       acl flag inherited canonicalization = no
+
+[full_audit_success_bad_name]
+       copy = tmp
+       full_audit:success = badname
+
+[full_audit_fail_bad_name]
+       copy = tmp
+       full_audit:failure = badname
+
+[only_ipv6]
+       copy = tmpguest
+       server addresses = $server_ipv6
+
+[smbget]
+       path = $smbget_sharedir
+       comment = smb username is [%U]
+
+[recycle]
+       copy = tmp
+       path = $recycle_shrdir
+       vfs objects = recycle
+       recycle : repository = .trash
+       recycle : exclude = *.tmp
+       recycle : directory_mode = 755
+
+[fakedircreatetimes]
+       copy = tmp
+       path = $fakedircreatetimes_shrdir
+       fake directory create times = yes
+
+[smbget_guest]
+       path = $smbget_sharedir
+       comment = smb username is [%U]
+       guest ok = yes
+
+include = $aliceconfdir/%U.conf
        ";
+
        close(CONF);
 
        my $net = Samba::bindir_path($self, "net");
        my $cmd = "";
+       $cmd .= "UID_WRAPPER_ROOT=1 ";
        $cmd .= "SMB_CONF_PATH=\"$conffile\" ";
        $cmd .= "$net setlocalsid $samsid";
 
-       if (system($cmd) != 0) {
-           warn("Join failed\n$cmd");
+       my $net_ret = system($cmd);
+       if ($net_ret != 0) {
+           warn("net setlocalsid failed: $net_ret\n$cmd");
            return undef;
        }
 
@@ -2363,6 +3677,19 @@ sub provision($$)
        }
        close(DELAYCONF);
 
+       unless (open(ALICECONF, ">$aliceconffile")) {
+               warn("Unable to open $aliceconffile");
+               return undef;
+       }
+
+       print ALICECONF "
+[alice_share]
+       path = $shrdir
+       comment = smb username is [%U]
+       ";
+
+       close(ALICECONF);
+
        ##
        ## create a test account
        ##
@@ -2370,7 +3697,7 @@ sub provision($$)
        unless (open(PASSWD, ">$nss_wrapper_passwd")) {
            warn("Unable to open $nss_wrapper_passwd");
            return undef;
-        } 
+        }
        print PASSWD "nobody:x:$uid_nobody:$gid_nobody:nobody gecos:$prefix_abs:/bin/false
 $unix_name:x:$unix_uid:$unix_gids[0]:$unix_name gecos:$prefix_abs:/bin/false
 pdbtest:x:$uid_pdbtest:$gid_nogroup:pdbtest gecos:$prefix_abs:/bin/false
@@ -2384,6 +3711,10 @@ user2:x:$uid_user2:$gid_nogroup:user2 gecos:$prefix_abs:/bin/false
 gooduser:x:$uid_gooduser:$gid_domusers:gooduser gecos:$prefix_abs:/bin/false
 eviluser:x:$uid_eviluser:$gid_domusers:eviluser gecos::/bin/false
 slashuser:x:$uid_slashuser:$gid_domusers:slashuser gecos:/:/bin/false
+bob:x:$uid_localbob:$gid_domusers:localbob gecos:/:/bin/false
+jane:x:$uid_localjane:$gid_domusers:localjane gecos:/:/bin/false
+jackthemapper:x:$uid_localjackthemapper:$gid_domusers:localjackthemaper gecos:/:/bin/false
+jacknomapper:x:$uid_localjacknomapper:$gid_domusers:localjacknomaper gecos:/:/bin/false
 ";
        if ($unix_uid != 0) {
                print PASSWD "root:x:$uid_root:$gid_root:root gecos:$prefix_abs:/bin/false
@@ -2403,6 +3734,8 @@ domadmins:X:$gid_domadmins:
 userdup:x:$gid_userdup:$unix_name
 everyone:x:$gid_everyone:
 force_user:x:$gid_force_user:
+jackthemappergroup:x:$gid_jackthemapper:jackthemapper
+jacknomappergroup:x:$gid_jacknomapper:jacknomapper
 ";
        if ($unix_gids[0] != 0) {
                print GROUP "root:x:$gid_root:
@@ -2417,27 +3750,11 @@ force_user:x:$gid_force_user:
                warn("Unable to open $nss_wrapper_hosts");
                return undef;
        }
-       print HOSTS "${server_ip} ${hostname}.samba.example.com ${hostname}\n";
-       print HOSTS "${server_ipv6} ${hostname}.samba.example.com ${hostname}\n";
+       print HOSTS "${server_ip} ${hostname}.${dns_domain} ${hostname}\n";
+       print HOSTS "${server_ipv6} ${hostname}.${dns_domain} ${hostname}\n";
        close(HOSTS);
 
-       ## hosts
-       unless (open(RESOLV_CONF, ">$resolv_conf")) {
-               warn("Unable to open $resolv_conf");
-               return undef;
-       }
-       if (defined($dc_server_ip) or defined($dc_server_ipv6)) {
-               if (defined($dc_server_ip)) {
-                       print RESOLV_CONF "nameserver $dc_server_ip\n";
-               }
-               if (defined($dc_server_ipv6)) {
-                       print RESOLV_CONF "nameserver $dc_server_ipv6\n";
-               }
-       } else {
-               print RESOLV_CONF "nameserver ${server_ip}\n";
-               print RESOLV_CONF "nameserver ${server_ipv6}\n";
-       }
-       close(RESOLV_CONF);
+       $resolv_conf = "$privatedir/no_resolv.conf" unless defined($resolv_conf);
 
        foreach my $evlog (@eventlog_list) {
                my $evlogtdb = "$eventlogdir/$evlog.tdb";
@@ -2448,12 +3765,13 @@ force_user:x:$gid_force_user:
        $createuser_env{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd;
        $createuser_env{NSS_WRAPPER_GROUP} = $nss_wrapper_group;
        $createuser_env{NSS_WRAPPER_HOSTS} = $nss_wrapper_hosts;
-       $createuser_env{NSS_WRAPPER_HOSTNAME} = "${hostname}.samba.example.com";
+       $createuser_env{NSS_WRAPPER_HOSTNAME} = "${hostname}.${dns_domain}";
        if ($ENV{SAMBA_DNS_FAKING}) {
                $createuser_env{RESOLV_WRAPPER_HOSTS} = $dns_host_file;
        } else {
                $createuser_env{RESOLV_WRAPPER_CONF} = $resolv_conf;
        }
+       $createuser_env{RESOLV_CONF} = $resolv_conf;
 
        createuser($self, $unix_name, $password, $conffile, \%createuser_env) || die("Unable to create user");
        createuser($self, "force_user", $password, $conffile, \%createuser_env) || die("Unable to create force_user");
@@ -2463,6 +3781,8 @@ force_user:x:$gid_force_user:
        createuser($self, "gooduser", $password, $conffile, \%createuser_env) || die("Unable to create gooduser");
        createuser($self, "eviluser", $password, $conffile, \%createuser_env) || die("Unable to create eviluser");
        createuser($self, "slashuser", $password, $conffile, \%createuser_env) || die("Unable to create slashuser");
+       createuser($self, "jackthemapper", "mApsEcrEt", $conffile, \%createuser_env) || die("Unable to create jackthemapper");
+       createuser($self, "jacknomapper", "nOmApsEcrEt", $conffile, \%createuser_env) || die("Unable to create jacknomapper");
 
        open(DNS_UPDATE_LIST, ">$prefix/dns_update_list") or die("Unable to open $$prefix/dns_update_list");
        print DNS_UPDATE_LIST "A $server. $server_ip\n";
@@ -2473,6 +3793,8 @@ force_user:x:$gid_force_user:
 
        $ret{SERVER_IP} = $server_ip;
        $ret{SERVER_IPV6} = $server_ipv6;
+       $ret{SAMBA_DCERPCD_TEST_LOG} = "$prefix/samba_dcerpcd_test.log";
+       $ret{SAMBA_DCERPCD_LOG_POS} = 0;
        $ret{NMBD_TEST_LOG} = "$prefix/nmbd_test.log";
        $ret{NMBD_TEST_LOG_POS} = 0;
        $ret{WINBINDD_TEST_LOG} = "$prefix/winbindd_test.log";
@@ -2481,14 +3803,14 @@ force_user:x:$gid_force_user:
        $ret{SMBD_TEST_LOG_POS} = 0;
        $ret{SERVERCONFFILE} = $conffile;
        $ret{TESTENV_DIR} = $prefix_abs;
-       $ret{CONFIGURATION} ="-$conffile";
+       $ret{CONFIGURATION} ="--configfile=$conffile";
        $ret{LOCK_DIR} = $lockdir;
        $ret{SERVER} = $server;
        $ret{USERNAME} = $unix_name;
        $ret{USERID} = $unix_uid;
        $ret{DOMAIN} = $domain;
        $ret{SAMSID} = $samsid;
-       $ret{NETBIOSNAME} = $server;
+       $ret{NETBIOSNAME} = $netbios_name;
        $ret{PASSWORD} = $password;
        $ret{PIDDIR} = $piddir;
        $ret{SELFTEST_WINBINDD_SOCKET_DIR} = $wbsockdir;
@@ -2497,7 +3819,7 @@ force_user:x:$gid_force_user:
        $ret{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd;
        $ret{NSS_WRAPPER_GROUP} = $nss_wrapper_group;
        $ret{NSS_WRAPPER_HOSTS} = $nss_wrapper_hosts;
-       $ret{NSS_WRAPPER_HOSTNAME} = "${hostname}.samba.example.com";
+       $ret{NSS_WRAPPER_HOSTNAME} = "${hostname}.${dns_domain}";
        $ret{NSS_WRAPPER_MODULE_SO_PATH} = Samba::nss_wrapper_winbind_so_path($self);
        $ret{NSS_WRAPPER_MODULE_FN_PREFIX} = "winbind";
        if ($ENV{SAMBA_DNS_FAKING}) {
@@ -2505,6 +3827,7 @@ force_user:x:$gid_force_user:
        } else {
                $ret{RESOLV_WRAPPER_CONF} = $resolv_conf;
        }
+       $ret{RESOLV_CONF} = $resolv_conf;
        $ret{LOCAL_PATH} = "$shrdir";
         $ret{LOGDIR} = $logdir;
 
@@ -2524,11 +3847,33 @@ force_user:x:$gid_force_user:
 
 sub wait_for_start($$$$$)
 {
-       my ($self, $envvars, $nmbd, $winbindd, $smbd) = @_;
+       my ($self, $envvars, $nmbd, $winbindd, $smbd, $samba_dcerpcd) = @_;
        my $cmd;
        my $netcmd;
        my $ret;
 
+       if ($samba_dcerpcd eq "yes") {
+           my $count = 0;
+           my $rpcclient = Samba::bindir_path($self, "rpcclient");
+
+           print "checking for samba_dcerpcd\n";
+
+           do {
+               $ret = system("UID_WRAPPER_ROOT=1 $rpcclient $envvars->{CONFIGURATION} ncalrpc: -c epmmap");
+
+               if ($ret != 0) {
+                   sleep(1);
+               }
+               $count++
+           } while ($ret != 0 && $count < 10);
+
+           if ($count == 10) {
+               print "samba_dcerpcd not reachable after 10 retries\n";
+               teardown_env($self, $envvars);
+               return 0;
+           }
+       }
+
        if ($nmbd eq "yes") {
                my $count = 0;
 
@@ -2545,7 +3890,7 @@ sub wait_for_start($$$$$)
                        } else {
                                system("$nmblookup $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} __SAMBA__");
                                system("$nmblookup $envvars->{CONFIGURATION} __SAMBA__");
-                               system("$nmblookup $envvars->{CONFIGURATION} -U 127.255.255.255 __SAMBA__");
+                               system("$nmblookup $envvars->{CONFIGURATION} -U 10.255.255.255 __SAMBA__");
                                system("$nmblookup $envvars->{CONFIGURATION} -U $envvars->{SERVER_IP} $envvars->{SERVER}");
                        }
                        $count++;
@@ -2557,17 +3902,21 @@ sub wait_for_start($$$$$)
                }
        }
 
-       if ($winbindd eq "yes") {
+       if ($winbindd eq "yes" or $winbindd eq "offline") {
            print "checking for winbindd\n";
            my $count = 0;
            $cmd = "SELFTEST_WINBINDD_SOCKET_DIR='$envvars->{SELFTEST_WINBINDD_SOCKET_DIR}' ";
            $cmd .= "NSS_WRAPPER_PASSWD='$envvars->{NSS_WRAPPER_PASSWD}' ";
            $cmd .= "NSS_WRAPPER_GROUP='$envvars->{NSS_WRAPPER_GROUP}' ";
-           $cmd .= Samba::bindir_path($self, "wbinfo") . " --ping-dc";
+           if ($winbindd eq "yes") {
+               $cmd .= Samba::bindir_path($self, "wbinfo") . " --ping-dc";
+           } elsif ($winbindd eq "offline") {
+               $cmd .= Samba::bindir_path($self, "wbinfo") . " --ping";
+           }
 
            do {
+               $ret = system($cmd);
                if ($ret != 0) {
-                   $ret = system($cmd);
                    sleep(1);
                }
                $count++;
@@ -2585,7 +3934,23 @@ sub wait_for_start($$$$$)
 
            my $count = 0;
            do {
-               $ret = system(Samba::bindir_path($self, "smbclient") ." $envvars->{CONFIGURATION} -L $envvars->{SERVER} -U% -p 139");
+               if (defined($envvars->{GNUTLS_FORCE_FIPS_MODE})) {
+                       # We don't have NTLM in FIPS mode, so lets use
+                       # smbcontrol instead of smbclient.
+                       $cmd = Samba::bindir_path($self, "smbcontrol");
+                       $cmd .= " $envvars->{CONFIGURATION}";
+                       $cmd .= " smbd ping";
+               } else {
+                       # This uses NTLM which is not available in FIPS
+                       $cmd = Samba::bindir_path($self, "smbclient");
+                       $cmd .= " $envvars->{CONFIGURATION}";
+                       $cmd .= " -L $envvars->{SERVER}";
+                       $cmd .= " -U%";
+                       $cmd .= " -I $envvars->{SERVER_IP}";
+                       $cmd .= " -p 139";
+               }
+
+               $ret = system($cmd);
                if ($ret != 0) {
                    sleep(1);
                }
@@ -2601,6 +3966,7 @@ sub wait_for_start($$$$$)
        # Ensure we have domain users mapped.
        $netcmd = "NSS_WRAPPER_PASSWD='$envvars->{NSS_WRAPPER_PASSWD}' ";
        $netcmd .= "NSS_WRAPPER_GROUP='$envvars->{NSS_WRAPPER_GROUP}' ";
+       $netcmd .= "UID_WRAPPER_ROOT='1' ";
        $netcmd .= Samba::bindir_path($self, "net") ." $envvars->{CONFIGURATION} ";
 
        $cmd = $netcmd . "groupmap delete ntgroup=domusers";
@@ -2688,4 +4054,263 @@ sub wait_for_start($$$$$)
        return 1;
 }
 
+##
+## provision and start of ctdb
+##
+sub setup_ctdb($$)
+{
+       my ($self, $prefix) = @_;
+       my $num_nodes = 3;
+
+       my $data = $self->provision_ctdb($prefix, $num_nodes);
+       $data or return undef;
+
+       my $rc = $self->check_or_start_ctdb($data);
+       if (not $rc) {
+               print("check_or_start_ctdb() failed\n");
+               return undef;
+       }
+
+       $rc = $self->wait_for_start_ctdb($data);
+       if (not $rc) {
+               print "Cluster startup failed\n";
+               return undef;
+       }
+
+       return $data;
+}
+
+sub provision_ctdb($$$$)
+{
+       my ($self, $prefix, $num_nodes, $no_delete_prefix) = @_;
+       my $rc;
+
+       print "PROVISIONING CTDB...\n";
+
+       my $prefix_abs = abs_path($prefix);
+
+       #
+       # check / create directories:
+       #
+       die ("prefix_abs = ''") if $prefix_abs eq "";
+       die ("prefix_abs = '/'") if $prefix_abs eq "/";
+
+       mkdir ($prefix_abs, 0777);
+
+       print "CREATE CTDB TEST ENVIRONMENT in '$prefix_abs'...\n";
+
+       if (not defined($no_delete_prefix) or not $no_delete_prefix) {
+               system("rm -rf $prefix_abs/*");
+       }
+
+       #
+       # Per-node data
+       #
+       my @nodes = ();
+       for (my $i = 0; $i < $num_nodes; $i++) {
+               my %node = ();
+               my $server_name = "ctdb${i}";
+               my $pub_iface = Samba::get_interface($server_name);
+               my $ip = Samba::get_ipv4_addr($server_name);
+
+               $node{NODE_NUMBER} = "$i";
+               $node{SERVER_NAME} = "$server_name";
+               $node{SOCKET_WRAPPER_DEFAULT_IFACE} = "$pub_iface";
+               $node{IP} = "$ip";
+
+               push(@nodes, \%node);
+       }
+
+       #
+       # nodes
+       #
+       my $nodes_file = "$prefix/nodes.in";
+       unless (open(NODES, ">$nodes_file")) {
+               warn("Unable to open nodesfile '$nodes_file'");
+               return undef;
+       }
+       for (my $i = 0; $i < $num_nodes; $i++) {
+               my $ip = $nodes[$i]->{IP};
+               print NODES "${ip}\n";
+       }
+       close(NODES);
+
+       #
+       # local_daemons.sh setup
+       #
+       # Socket wrapper setup is done by selftest.pl, so don't use
+       # the CTDB-specific setup
+       #
+       my $cmd;
+       $cmd .= "ctdb/tests/local_daemons.sh " . $prefix_abs . " setup";
+       $cmd .= " -n " . $num_nodes;
+       $cmd .= " -N " . $nodes_file;
+       # CTDB should not attempt to manage public addresses -
+       # clients should just connect to CTDB private addresses
+       $cmd .= " -P " . "/dev/null";
+
+       my $ret = system($cmd);
+       if ($ret != 0) {
+               print("\"$cmd\" failed\n");
+               return undef;
+       }
+
+       #
+       # Unix domain socket and node directory for each daemon
+       #
+       for (my $i = 0; $i < $num_nodes; $i++) {
+               my ($cmd, $ret, $out);
+
+               my $cmd_prefix = "ctdb/tests/local_daemons.sh ${prefix_abs}";
+
+               #
+               # socket
+               #
+
+               $cmd = "${cmd_prefix} print-socket ${i}";
+
+               $out = `$cmd`;
+               $ret = $?;
+               if ($ret != 0) {
+                   print("\"$cmd\" failed\n");
+                   return undef;
+               }
+               chomp $out;
+               $nodes[$i]->{SOCKET_FILE} = "$out";
+
+               #
+               # node directory
+               #
+
+               $cmd = "${cmd_prefix} onnode ${i} 'echo \$CTDB_BASE'";
+
+               $out = `$cmd`;
+               $ret = $?;
+               if ($ret != 0) {
+                   print("\"$cmd\" failed\n");
+                   return undef;
+               }
+               chomp $out;
+               $nodes[$i]->{NODE_PREFIX} = "$out";
+       }
+
+       my %ret = ();
+
+       $ret{CTDB_PREFIX} = "$prefix";
+       $ret{NUM_NODES} = $num_nodes;
+       $ret{CTDB_NODES} = \@nodes;
+       $ret{CTDB_NODES_FILE} = $nodes_file;
+
+       for (my $i = 0; $i < $num_nodes; $i++) {
+               my $node = $nodes[$i];
+               my $socket = $node->{SOCKET_FILE};
+               my $server_name = $node->{SERVER_NAME};
+               my $node_prefix = $node->{NODE_PREFIX};
+               my $ip = $node->{IP};
+
+               $ret{"CTDB_BASE_NODE${i}"} = $node_prefix;
+               $ret{"CTDB_SOCKET_NODE${i}"} = $socket;
+               $ret{"CTDB_SERVER_NAME_NODE${i}"} = $server_name;
+               $ret{"CTDB_IFACE_IP_NODE${i}"} = $ip;
+       }
+
+       $ret{CTDB_BASE} = $ret{CTDB_BASE_NODE0};
+       $ret{CTDB_SOCKET} = $ret{CTDB_SOCKET_NODE0};
+       $ret{CTDB_SERVER_NAME} = $ret{CTDB_SERVER_NAME_NODE0};
+       $ret{CTDB_IFACE_IP} = $ret{CTDB_IFACE_IP_NODE0};
+
+       return \%ret;
+}
+
+sub check_or_start_ctdb($$) {
+       my ($self, $data) = @_;
+
+       my $prefix = $data->{CTDB_PREFIX};
+       my $num_nodes = $data->{NUM_NODES};
+       my $nodes = $data->{CTDB_NODES};
+       my $STDIN_READER;
+
+       # Share a single stdin pipe for all nodes
+       pipe($STDIN_READER, $data->{CTDB_STDIN_PIPE});
+
+       for (my $i = 0; $i < $num_nodes; $i++) {
+               my $node = $nodes->[$i];
+
+               $node->{STDIN_PIPE} = $data->{CTDB_STDIN_PIPE};
+
+               my $cmd = "ctdb/tests/local_daemons.sh";
+               my @full_cmd = ("$cmd", "$prefix", "start", "$i");
+               my $daemon_ctx = {
+                       NAME => "ctdbd",
+                       BINARY_PATH => $cmd,
+                       FULL_CMD => [ @full_cmd ],
+                       TEE_STDOUT => 1,
+                       LOG_FILE => "/dev/null",
+                       ENV_VARS => {},
+               };
+
+               print "STARTING CTDBD (node ${i})\n";
+
+               # This does magic with $STDIN_READER, so use it
+               my $ret = Samba::fork_and_exec($self,
+                                              $node,
+                                              $daemon_ctx,
+                                              $STDIN_READER);
+
+               if ($ret == 0) {
+                       print("\"$cmd\" failed\n");
+                       teardown_env_ctdb($self, $data);
+                       return 0;
+               }
+       }
+
+       close($STDIN_READER);
+
+       return 1;
+}
+
+sub wait_for_start_ctdb($$)
+{
+       my ($self, $data) = @_;
+
+       my $prefix = $data->{CTDB_PREFIX};
+
+       print "Wait for ctdbd...\n";
+
+       my $ctdb = Samba::bindir_path($self, "ctdb");
+       my $cmd;
+       $cmd .= "ctdb/tests/local_daemons.sh ${prefix} onnode all";
+       $cmd .= " ${ctdb} nodestatus all 2>&1";
+
+       my $count = 0;
+       my $wait_seconds = 60;
+       my $out;
+
+       until ($count > $wait_seconds) {
+               $out = `$cmd`;
+               my $ret = $?;
+               if ($ret == 0) {
+                       print "\ncluster became healthy\n";
+                       last;
+               }
+               print "Waiting for CTDB...\n";
+               sleep(1);
+               $count++;
+       }
+
+       if ($count > $wait_seconds) {
+               print "\nGiving up to wait for CTDB...\n";
+               print "${out}\n\n";
+               print "CTDB log:\n";
+               $cmd = "ctdb/tests/local_daemons.sh ${prefix} print-log all >&2";
+               system($cmd);
+               teardown_env_ctdb($self, $data);
+               return 0;
+       }
+
+       print "\nCTDB initialized\n";
+
+       return 1;
+}
+
 1;