Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into ctdb-merge
authorAlexander Bokovoy <ab@samba.org>
Thu, 24 Jan 2008 11:06:22 +0000 (14:06 +0300)
committerAlexander Bokovoy <ab@samba.org>
Thu, 24 Jan 2008 11:06:22 +0000 (14:06 +0300)
(This used to be commit 42d06d41bf2e9fb094f6064dc04f549d880b5f8d)

103 files changed:
PFIF.txt [new file with mode: 0644]
README
source3/Makefile.in
source3/auth/auth_domain.c
source3/client/client.c
source3/client/clitar.c
source3/client/smbmnt.c
source3/client/smbmount.c
source3/configure.in
source3/include/debug.h
source3/include/includes.h
source3/include/reg_objects.h
source3/include/rpc_dce.h
source3/include/rpc_samr.h
source3/include/smb.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/lib/afs.c
source3/lib/afs_settoken.c
source3/lib/dbwrap_tdb.c
source3/lib/debug.c
source3/lib/errmap_unix.c
source3/lib/replace/libreplace.m4
source3/lib/replace/libreplace_cc.m4
source3/lib/replace/libreplace_ld.m4
source3/lib/replace/libreplace_macros.m4
source3/lib/replace/system/config.m4
source3/lib/replace/system/network.h
source3/lib/replace/system/printing.h [deleted file]
source3/lib/replace/test/testsuite.c
source3/lib/system.c
source3/lib/util.c
source3/lib/util_sock.c
source3/lib/util_str.c
source3/lib/version.c
source3/libads/ads_struct.c
source3/libnet/libnet_conf.c
source3/libnet/libnet_join.c
source3/libsmb/cliconnect.c
source3/libsmb/clientgen.c
source3/libsmb/libsmbclient.c
source3/libsmb/trusts_util.c
source3/locking/brlock.c
source3/modules/vfs_default.c
source3/modules/vfs_recycle.c
source3/modules/vfs_streams_depot.c [new file with mode: 0644]
source3/modules/vfs_streams_xattr.c [new file with mode: 0644]
source3/modules/vfs_xattr_tdb.c
source3/nmbd/nmbd_processlogon.c
source3/nsswitch/libwbclient/wbclient.c
source3/param/loadparm.c
source3/printing/load.c
source3/printing/lpq_parse.c
source3/printing/print_aix.c
source3/registry/reg_api.c
source3/registry/reg_backend_current_version.c [new file with mode: 0644]
source3/registry/reg_backend_db.c [moved from source3/registry/reg_db.c with 98% similarity]
source3/registry/reg_backend_hkpt_params.c [new file with mode: 0644]
source3/registry/reg_backend_netlogon_params.c
source3/registry/reg_backend_perflib.c [new file with mode: 0644]
source3/registry/reg_backend_printing.c [moved from source3/registry/reg_printing.c with 99% similarity]
source3/registry/reg_backend_prod_options.c [new file with mode: 0644]
source3/registry/reg_backend_shares.c [moved from source3/registry/reg_shares.c with 96% similarity]
source3/registry/reg_backend_smbconf.c [moved from source3/registry/reg_smbconf.c with 96% similarity]
source3/registry/reg_backend_tcpip_params.c [new file with mode: 0644]
source3/registry/reg_cachehook.c
source3/registry/reg_dispatcher.c [moved from source3/registry/reg_frontend_hilvl.c with 96% similarity]
source3/registry/reg_dynamic.c [deleted file]
source3/registry/reg_init_full.c [moved from source3/registry/reg_frontend.c with 80% similarity]
source3/registry/reg_init_smbconf.c [moved from source3/lib/util_reg_smbconf.c with 100% similarity]
source3/registry/reg_util_legacy.c [new file with mode: 0644]
source3/rpc_client/cli_pipe.c
source3/rpc_client/cli_samr.c
source3/rpc_parse/parse_samr.c
source3/rpc_server/srv_samr_util.c
source3/rpcclient/cmd_samr.c
source3/rpcclient/cmd_spoolss.c
source3/rpcclient/rpcclient.c
source3/script/tests/selftest.sh
source3/script/tests/test_posix_s3.sh
source3/services/services_db.c
source3/smbd/close.c
source3/smbd/filename.c
source3/smbd/msdfs.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/password.c
source3/smbd/process.c
source3/smbd/reply.c
source3/smbd/service.c
source3/smbd/trans2.c
source3/smbd/utmp.c
source3/torture/torture.c
source3/utils/net_domain.c
source3/utils/net_rpc.c
source3/utils/net_rpc_join.c
source3/utils/net_rpc_samsync.c
source3/utils/ntlm_auth.c
source3/web/cgi.c
source3/winbindd/winbindd_cm.c
source3/winbindd/winbindd_dual.c
source3/winbindd/winbindd_pam.c
source3/winbindd/winbindd_util.c

diff --git a/PFIF.txt b/PFIF.txt
new file mode 100644 (file)
index 0000000..09f1458
--- /dev/null
+++ b/PFIF.txt
@@ -0,0 +1,7 @@
+This code was developed in participation with the Protocol Freedom
+Information Foundation.
+
+Please see 
+  http://protocolfreedom.org/ and
+  http://samba.org/samba/PFIF/ 
+for more details.
diff --git a/README b/README
index 1d55a1040ca150b1e51eb8ca44fe1995956171b3..e6634febc0ea08a3551dc0ba3b170a98fb7b7064 100644 (file)
--- a/README
+++ b/README
@@ -102,16 +102,16 @@ for more details) and are always glad to receive feedback or
 suggestions to the address samba@lists.samba.org.  More information
 on the various Samba mailing lists can be found at http://lists.samba.org/.
 
-You can also get the Samba sourcecode straight from the Subversion tree - see
-http://samba.org/samba/subversion.html.
+You can also get the Samba sourcecode straight from the git repository - see
+http://wiki.samba.org/index.php/Using_Git_for_Samba_Development.
 
 You could also send hardware/software/money/jewelry or pre-paid pizza
 vouchers directly to Andrew. The pizza vouchers would be especially
 welcome, in fact there is a special field in the survey for people who
 have paid up their pizza :-)
 
-If you like a particular feature then look through the Subversion change-log
-(on the web at http://websvn.samba.org/cgi-bin/viewcvs.cgi) and see
+If you like a particular feature then look through the git change-log
+(on the web at http://gitweb.samba.org/?p=samba.git;a=summary) and see
 who added it, then send them an email.
 
 Remember that free software of this kind lives or dies by the response
index 45aa4cbc379eccd9f2d28b0af9e9ec320bc4d25a..c519ff898505d62361508f83008a753493f7728e 100644 (file)
@@ -276,6 +276,7 @@ LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o \
                 librpc/gen_ndr/ndr_netlogon.o \
                 librpc/gen_ndr/ndr_samr.o \
                 librpc/gen_ndr/ndr_notify.o \
+                librpc/gen_ndr/ndr_xattr.o \
                 librpc/gen_ndr/ndr_libnet_join.o
 
 RPC_PARSE_OBJ0 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o
@@ -410,15 +411,54 @@ LIBMSRPC_GEN_OBJ = librpc/gen_ndr/cli_lsa.o \
                   $(LIBNDR_GEN_OBJ) \
                   $(RPCCLIENT_NDR_OBJ)
 
+#
+# registry-related objects
+#
+UTIL_REG_OBJ = lib/util_reg.o
+UTIL_REG_API_OBJ = lib/util_reg_api.o
+REG_INIT_SMBCONF_OBJ = registry/reg_init_smbconf.o
+
+REGFIO_OBJ = registry/regfio.o
+
 REGOBJS_OBJ = registry/reg_objects.o
 
-REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \
-               registry/reg_db.o registry/reg_eventlog.o registry/reg_shares.o \
-               registry/reg_util.o registry/reg_dynamic.o registry/reg_perfcount.o \
-              registry/reg_smbconf.o registry/reg_api.o \
-              registry/reg_frontend_hilvl.o \
-              registry/reg_backend_netlogon_params.o \
-              $(UTIL_REG_API_OBJ) $(UTIL_REG_SMBCONF_OBJ)
+REGISTRY_BACKENDS = registry/reg_backend_printing.o \
+                   registry/reg_backend_db.o \
+                   registry/reg_backend_smbconf.o \
+                   registry/reg_backend_shares.o \
+                   registry/reg_backend_netlogon_params.o \
+                   registry/reg_backend_prod_options.o \
+                   registry/reg_backend_tcpip_params.o \
+                   registry/reg_backend_hkpt_params.o \
+                   registry/reg_backend_current_version.o \
+                   registry/reg_backend_perflib.o
+
+
+REGISTRY_OBJ = registry/reg_init_full.o registry/reg_cachehook.o \
+               registry/reg_eventlog.o \
+               registry/reg_util.o registry/reg_perfcount.o \
+              registry/reg_util_legacy.o \
+              registry/reg_api.o \
+              registry/reg_dispatcher.o \
+              $(REGISTRY_BACKENDS) \
+              $(UTIL_REG_API_OBJ) \
+              $(REG_INIT_SMBCONF_OBJ)
+
+# objects to be used when not all of the registry code should be
+# loaded but only the portion needed by reg_api, typically for
+# using smbconf (registry) - full access
+REG_API_OBJ = registry/reg_api.o \
+             registry/reg_dispatcher.o \
+             registry/reg_backend_smbconf.o \
+             registry/reg_backend_db.o \
+             registry/reg_util.o \
+             \
+             registry/reg_cachehook.o \
+             \
+             lib/util_nttoken.o \
+             $(UTIL_REG_API_OBJ) \
+             $(REG_INIT_SMBCONF_OBJ)
+
 
 RPC_LSA_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o librpc/gen_ndr/srv_lsa.o
 
@@ -427,8 +467,6 @@ RPC_NETLOG_OBJ = rpc_server/srv_netlog.o rpc_server/srv_netlog_nt.o
 RPC_SAMR_OBJ = rpc_server/srv_samr.o rpc_server/srv_samr_nt.o \
                rpc_server/srv_samr_util.o
 
-REGFIO_OBJ = registry/regfio.o
-
 RPC_INITSHUTDOWN_OBJ =  librpc/gen_ndr/srv_initshutdown.o rpc_server/srv_initshutdown_nt.o
 
 RPC_REG_OBJ =  rpc_server/srv_winreg_nt.o \
@@ -515,7 +553,7 @@ VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o
 VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o
 VFS_SHADOW_COPY2_OBJ = modules/vfs_shadow_copy2.o
 VFS_AFSACL_OBJ = modules/vfs_afsacl.o
-VFS_XATTR_TDB_OBJ = modules/vfs_xattr_tdb.o librpc/gen_ndr/ndr_xattr.o
+VFS_XATTR_TDB_OBJ = modules/vfs_xattr_tdb.o
 VFS_POSIXACL_OBJ = modules/vfs_posixacl.o
 VFS_AIXACL_OBJ = modules/vfs_aixacl.o modules/vfs_aixacl_util.o
 VFS_AIXACL2_OBJ = modules/vfs_aixacl2.o modules/vfs_aixacl_util.o modules/nfs4_acls.o
@@ -525,6 +563,8 @@ VFS_HPUXACL_OBJ = modules/vfs_hpuxacl.o
 VFS_IRIXACL_OBJ = modules/vfs_irixacl.o
 VFS_TRU64ACL_OBJ = modules/vfs_tru64acl.o
 VFS_CATIA_OBJ = modules/vfs_catia.o
+VFS_STREAMS_XATTR_OBJ = modules/vfs_streams_xattr.o
+VFS_STREAMS_DEPOT_OBJ = modules/vfs_streams_depot.o
 VFS_CACHEPRIME_OBJ = modules/vfs_cacheprime.o
 VFS_PREALLOC_OBJ = modules/vfs_prealloc.o
 VFS_COMMIT_OBJ = modules/vfs_commit.o
@@ -717,29 +757,6 @@ CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) \
              $(PASSDB_OBJ) @LIBWBCLIENT_STATIC@ $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(LDB_OBJ) \
             $(DISPLAY_SEC_OBJ) 
 
-UTIL_REG_OBJ = lib/util_reg.o
-UTIL_REG_API_OBJ = lib/util_reg_api.o
-UTIL_REG_SMBCONF_OBJ = lib/util_reg_smbconf.o
-
-# objects to be used when not all of the registry code should be
-# loaded but only the portion needed by reg_api, typically for
-# using smbconf (registry) - full access
-REG_API_OBJ = registry/reg_api.o \
-             registry/reg_frontend_hilvl.o \
-             registry/reg_smbconf.o \
-             registry/reg_db.o \
-             registry/reg_util.o \
-             \
-             registry/reg_cachehook.o \
-             registry/reg_eventlog.o \
-             registry/reg_perfcount.o \
-             registry/reg_dynamic.o \
-             \
-             lib/util_nttoken.o \
-             $(UTIL_REG_API_OBJ) \
-             $(UTIL_REG_SMBCONF_OBJ)
-
-
 LIBNETAPI_OBJ1 = lib/netapi/netapi.o \
                 lib/netapi/joindomain.o \
                 lib/netapi/serverinfo.o \
@@ -846,7 +863,7 @@ EVTLOGADM_OBJ       = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ)
                $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \
                $(SECRETS_OBJ) \
                registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o registry/reg_util.o \
-               registry/reg_db.o
+               registry/reg_backend_db.o
 
 SHARESEC_OBJ0 = utils/sharesec.o
 SHARESEC_OBJ  = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ) \
@@ -1746,6 +1763,14 @@ bin/catia.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_CATIA_OBJ)
        @echo "Building plugin $@"
        @$(SHLD_MODULE) $(VFS_CATIA_OBJ)
 
+bin/streams_xattr.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_STREAMS_XATTR_OBJ)
+       @echo "Building plugin $@"
+       @$(SHLD_MODULE) $(VFS_STREAMS_XATTR_OBJ)
+
+bin/streams_depot.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_STREAMS_DEPOT_OBJ)
+       @echo "Building plugin $@"
+       @$(SHLD_MODULE) $(VFS_STREAMS_DEPOT_OBJ)
+
 bin/cacheprime.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_CACHEPRIME_OBJ)
        @echo "Building plugin $@"
        @$(SHLD_MODULE) $(VFS_CACHEPRIME_OBJ)
index 1de9869f9078e91d41957b6df7fb1cf0cbe94735..40a29856002338e07c913e90603eac7a38cd55b0 100644 (file)
@@ -124,7 +124,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
 
        if (!lp_client_schannel()) {
                /* We need to set up a creds chain on an unauthenticated netlogon pipe. */
-               uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+               uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
                uint32 sec_chan_type = 0;
                unsigned char machine_pwd[16];
                const char *account_name;
index 59ca2e0adcf32f666d1655f9473f84440051f04a..c9343104911096214bd140346d2f9bf4c3790afe 100644 (file)
@@ -1463,6 +1463,7 @@ static int cmd_mkdir(void)
                struct cli_state *targetcli;
                char *targetname = NULL;
                char *p = NULL;
+               char *saveptr;
 
                ddir2 = talloc_strdup(ctx, "");
                if (!ddir2) {
@@ -1478,7 +1479,7 @@ static int cmd_mkdir(void)
                        return 1;
                }
                trim_char(ddir,'.','\0');
-               p = strtok(ddir,"/\\");
+               p = strtok_r(ddir, "/\\", &saveptr);
                while (p) {
                        ddir2 = talloc_asprintf_append(ddir2, p);
                        if (!ddir2) {
@@ -1491,7 +1492,7 @@ static int cmd_mkdir(void)
                        if (!ddir2) {
                                return 1;
                        }
-                       p = strtok(NULL,"/\\");
+                       p = strtok_r(NULL, "/\\", &saveptr);
                }
        } else {
                do_mkdir(mask);
@@ -1600,7 +1601,7 @@ static int cmd_allinfo(void)
        }
 
        if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
-               d_printf("altname <file>\n");
+               d_printf("allinfo <file>\n");
                return 1;
        }
        name = talloc_asprintf_append(name, buf);
index 135815c3cd7d11a848f13d1725ce0f5ae051483f..816e7b17100a5d327391044246a6ef9ab9638058 100644 (file)
@@ -513,6 +513,7 @@ static bool ensurepath(const char *fname)
        char *partpath, *ffname;
        const char *p=fname;
        char *basehack;
+       char *saveptr;
 
        DEBUG(5, ( "Ensurepath called with: %s\n", fname));
 
@@ -528,7 +529,7 @@ static bool ensurepath(const char *fname)
 
        *partpath = 0;
 
-       /* fname copied to ffname so can strtok */
+       /* fname copied to ffname so can strtok_r */
 
        safe_strcpy(ffname, fname, strlen(fname));
 
@@ -541,7 +542,7 @@ static bool ensurepath(const char *fname)
                *basehack='\0';
        }
 
-       p=strtok(ffname, "\\");
+       p=strtok_r(ffname, "\\", &saveptr);
 
        while (p) {
                safe_strcat(partpath, p, strlen(fname) + 1);
@@ -558,7 +559,7 @@ static bool ensurepath(const char *fname)
                }
 
                safe_strcat(partpath, "\\", strlen(fname) + 1);
-               p = strtok(NULL,"/\\");
+               p = strtok_r(NULL, "/\\", &saveptr);
        }
 
        SAFE_FREE(partpath);
index 7f1e1d5003ac05580c34af1f3cf55e4a628bd87f..79c55b2f90ea336805626257939376cc3778f25c 100644 (file)
@@ -162,6 +162,7 @@ do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
        char *release, *major, *minor;
        char *data1, *data2;
        int ret;
+       char *saveptr;
 
        if (asprintf(&opts,
                        "version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s",
@@ -172,8 +173,8 @@ do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
 
        uname(&uts);
        release = uts.release;
-       major = strtok(release, ".");
-       minor = strtok(NULL, ".");
+       major = strtok_r(release, ".", &saveptr);
+       minor = strtok_r(NULL, ".", &saveptr);
        if (major && minor && atoi(major) == 2 && atoi(minor) < 4) {
                /* < 2.4, assume struct */
                data1 = (char *) data;
index 98c61a30d89d968d918f3d68651645863e4528dd..9fe2d36bd37846cdacbd45a60eec99d24b029c87 100644 (file)
@@ -764,6 +764,7 @@ static void parse_mount_smb(int argc, char **argv)
        char *opts;
        char *opteq;
        int val;
+       char *saveptr;
        TALLOC_CTX *ctx = talloc_tos();
 
        /* FIXME: This function can silently fail if the arguments are
@@ -813,7 +814,8 @@ static void parse_mount_smb(int argc, char **argv)
        /*
         * option parsing from nfsmount.c (util-linux-2.9u)
         */
-        for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) {
+        for (opts = strtok_r(optarg, ",", &saveptr); opts;
+            opts = strtok_r(NULL, ",", &saveptr)) {
                DEBUG(3, ("opts: %s\n", opts));
                 if ((opteq = strchr_m(opts, '='))) {
                         val = atoi(opteq + 1);
index f65eb3c204bbd4a59016f894facb832e436b849f..fcbe56f268a0491eb0c4b384c168cbac9638c07a 100644 (file)
@@ -707,7 +707,7 @@ dnl These have to be built static:
 default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_winreg rpc_initshutdown rpc_lsa_ds rpc_wkssvc rpc_svcctl2 rpc_ntsvcs rpc_net rpc_netdfs rpc_srvsvc2 rpc_spoolss rpc_eventlog2 auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin vfs_default nss_info_template"
 
 dnl These are preferably build shared, and static if dlopen() is not available
-default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_syncops vfs_xattr_tdb"
+default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_syncops vfs_xattr_tdb vfs_streams_xattr"
 
 if test "x$developer" = xyes; then
    default_static_modules="$default_static_modules rpc_rpcecho"
@@ -1864,7 +1864,7 @@ DSO_EXPORTS=""
                *aix*) AC_DEFINE(AIX,1,[Whether the host os is aix])
                        BLDSHARED="true"
                        LDSHFLAGS="-Wl,-G,-bexpall,-bbigtoc"
-                       DYNEXP="-Wl,-brtl,-bexpall,-bbigtoc"
+                       DYNEXP="-Wl,-brtl,-bexpfull,-bbigtoc"
                        PICFLAG="-O2"
                        # as AIX code is always position independent...
                        # .po will just create compile warnings, use po.o:
@@ -3051,15 +3051,6 @@ if test x"$samba_cv_HAVE_IFACE_IFREQ" = x"yes"; then
 fi
 fi
 
-dnl AIX 5.3.0.0
-AC_TRY_COMPILE([#include <sys/socket.h>],[
-struct sockaddr_storage s; s.__ss_family = 0],
-samba_cv_have_aix_sockaddr_storage=yes,samba_cv_have_aix_sockaddr_storage=no)
-
-if test x"$samba_cv_have_aix_sockaddr_storage" = x"yes"; then
-   AC_DEFINE(HAVE_AIX_SOCKADDR_STORAGE, 1, [Whether struct sockaddr_storage has __sa_family])
-fi
-
 if test $iface = no; then
 AC_CACHE_CHECK([for iface AIX],samba_cv_HAVE_IFACE_AIX,[
 SAVE_CPPFLAGS="$CPPFLAGS"
@@ -6506,6 +6497,8 @@ SMB_MODULE(vfs_irixacl, \$(VFS_IRIXACL_OBJ), "bin/irixacl.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_hpuxacl, \$(VFS_HPUXACL_OBJ), "bin/hpuxacl.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_tru64acl, \$(VFS_TRU64ACL_OBJ), "bin/tru64acl.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_catia, \$(VFS_CATIA_OBJ), "bin/catia.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_streams_xattr, \$(VFS_STREAMS_XATTR_OBJ), "bin/streams_xattr.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_streams_depot, \$(VFS_STREAMS_DEPOT_OBJ), "bin/streams_depot.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_cacheprime, \$(VFS_CACHEPRIME_OBJ), "bin/cacheprime.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_prealloc, \$(VFS_PREALLOC_OBJ), "bin/prealloc.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_commit, \$(VFS_COMMIT_OBJ), "bin/commit.$SHLIBEXT", VFS)
index 284671c730f00faa7b922fcbd008683143b8258c..d8dafcbd457509b25f35ca423d0b4f7b46668028 100644 (file)
@@ -176,11 +176,14 @@ extern bool *DEBUGLEVEL_CLASS_ISSET;
 #define unlikely(x) (x)
 #endif
 
-#define DEBUGLVL( level ) \
+#define CHECK_DEBUGLVL( level ) \
   ( ((level) <= MAX_DEBUG_LEVEL) && \
      unlikely((DEBUGLEVEL_CLASS[ DBGC_CLASS ] >= (level))||  \
      (!DEBUGLEVEL_CLASS_ISSET[ DBGC_CLASS ] && \
-      DEBUGLEVEL_CLASS[ DBGC_ALL   ] >= (level))  ) \
+      DEBUGLEVEL_CLASS[ DBGC_ALL   ] >= (level))  ) )
+
+#define DEBUGLVL( level ) \
+  ( CHECK_DEBUGLVL(level) \
    && dbghdr( level, DBGC_CLASS, __FILE__, FUNCTION_MACRO, (__LINE__) ) )
 
 
index e9477d8ba1620116e73a325e7851b212f3826984..c6d0885ad9f1dd35ba896149816bacbd686af2f7 100644 (file)
@@ -702,6 +702,7 @@ typedef char fstring[FSTRING_LEN];
 #include "rpc_perfcount.h"
 #include "rpc_perfcount_defs.h"
 #include "librpc/gen_ndr/notify.h"
+#include "librpc/gen_ndr/xattr.h"
 #include "nt_printing.h"
 #include "idmap.h"
 #include "client.h"
@@ -1107,6 +1108,14 @@ char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...) PRINTF_ATT
 #define VXFS_QUOTA
 #endif
 
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  0x1       /* set value, fail if attr already exists */
+#endif
+
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 0x2       /* set value, fail if attr does not exist */
+#endif
+
 #if defined(HAVE_KRB5)
 
 krb5_error_code smb_krb5_parse_name(krb5_context context,
index 3b846db68176b57a146b58b82b10f0ccc1264399..3df701f61cced8fc79fe60fe062b1a45f721108c 100644 (file)
@@ -94,13 +94,18 @@ typedef struct {
 #define KEY_HKCU               "HKCU"
 #define KEY_HKDD               "HKDD"
 #define KEY_SERVICES           "HKLM\\SYSTEM\\CurrentControlSet\\Services"
+#define KEY_EVENTLOG           "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Eventlog"
+#define KEY_SHARES             "HKLM\\SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Shares"
+#define KEY_NETLOGON_PARAMS    "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters"
+#define KEY_TCPIP_PARAMS       "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
+#define KEY_PROD_OPTIONS       "HKLM\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions"
 #define KEY_PRINTING           "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print"
 #define KEY_PRINTING_2K                "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"
 #define KEY_PRINTING_PORTS     "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Ports"
-#define KEY_EVENTLOG           "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Eventlog"
-#define KEY_SHARES             "HKLM\\SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Shares"
+#define KEY_CURRENT_VERSION    "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
+#define KEY_PERFLIB            "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"
+#define KEY_PERFLIB_009                "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009"
 #define KEY_SMBCONF            "HKLM\\SOFTWARE\\Samba\\smbconf"
-#define KEY_NETLOGON_PARAMS    "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters"
 #define KEY_TREE_ROOT          ""
 
 /*
index f162196524fb5d064633d66bee8a53e9b6a25cb9..ec08eb5f8f1f3761f70cd7bc9913b7f02b470206 100644 (file)
@@ -106,6 +106,8 @@ enum RPC_PKT_TYPE {
 /* these are the flags that ADS clients use */
 #define NETLOGON_NEG_AUTH2_ADS_FLAGS (0x200fbffb | NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT | NETLOGON_NEG_SCHANNEL)
 
+#define NETLOGON_NEG_SELECT_AUTH2_FLAGS ((lp_security() == SEC_ADS) ? NETLOGON_NEG_AUTH2_ADS_FLAGS : NETLOGON_NEG_AUTH2_FLAGS)
+
 enum schannel_direction {
        SENDER_IS_INITIATOR,
        SENDER_IS_ACCEPTOR
index 9274e37682e22d74c52ba9f2e94549d6b60bbeac..5ddb877b9074519280906a1ab994d815145c5824 100644 (file)
@@ -145,6 +145,31 @@ SamrTestPrivateFunctionsUser
 #define SAMR_CHGPASSWD_USER3   0x3F
 #define SAMR_CONNECT5          0x40
 
+/* SAMR account creation flags/permissions */
+#define SAMR_USER_GETNAME               0x1
+#define SAMR_USER_GETLOCALE             0x2
+#define SAMR_USER_GETLOCCOM             0x4
+#define SAMR_USER_GETLOGONINFO          0x8
+#define SAMR_USER_GETATTR               0x10
+#define SAMR_USER_SETATTR               0x20
+#define SAMR_USER_CHPASS                0x40
+#define SAMR_USER_SETPASS               0x80
+#define SAMR_USER_GETGROUPS             0x100
+#define SAMR_USER_GETMEMBERSHIP         0x200
+#define SAMR_USER_CHMEMBERSHIP          0x400
+#define SAMR_STANDARD_DELETE            0x10000
+#define SAMR_STANDARD_READCTRL          0x20000
+#define SAMR_STANDARD_WRITEDAC          0x40000
+#define SAMR_STANDARD_WRITEOWNER        0x80000
+#define SAMR_STANDARD_SYNC              0x100000
+#define SAMR_GENERIC_ACCESSSACL         0x800000
+#define SAMR_GENERIC_MAXALLOWED         0x2000000
+#define SAMR_GENERIC_ALL                0x10000000
+#define SAMR_GENERIC_EXECUTE            0x20000000
+#define SAMR_GENERIC_WRITE              0x40000000
+#define SAMR_GENERIC_READ               0x80000000
+
+
 typedef struct logon_hours_info
 {
        uint32 max_len; /* normally 1260 bytes */
@@ -1555,7 +1580,7 @@ typedef struct q_samr_create_user_info
        UNISTR2 uni_name;       /* unicode account name */
 
        uint32 acb_info;      /* account control info */
-       uint32 access_mask;     /* 0xe005 00b0 */
+       uint32 acct_flags;     /* 0xe005 00b0 */
 
 } SAMR_Q_CREATE_USER;
 
index 15e51dbdd7f228e10ff3315ad2920a12249555f7..f3cf1db6f8b09fe7d37956babc576d80343a039e 100644 (file)
@@ -513,6 +513,8 @@ typedef struct files_struct {
        FAKE_FILE_HANDLE *fake_file_handle;
 
        struct notify_change_buf *notify;
+
+       struct files_struct *base_fsp; /* placeholder for delete on close */
 } files_struct;
 
 #include "ntquotas.h"
@@ -1369,6 +1371,9 @@ struct bitmap {
 #define NTCREATEX_OPTIONS_PRIVATE_DENY_DOS     0x01000000
 #define NTCREATEX_OPTIONS_PRIVATE_DENY_FCB     0x02000000
 
+/* Private options for streams support */
+#define NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE 0x04000000
+
 /* Responses when opening a file. */
 #define FILE_WAS_SUPERSEDED 0
 #define FILE_WAS_OPENED 1
@@ -1899,6 +1904,8 @@ struct ea_list {
 #define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI"
 /* EA to use for DOS attributes */
 #define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB"
+/* Prefix for DosStreams in the vfs_streams_xattr module */
+#define SAMBA_XATTR_DOSSTREAM_PREFIX "user.DosStream."
 
 #define UUID_SIZE 16
 
@@ -1929,4 +1936,15 @@ enum usershare_err {
 /* Different reasons for closing a file. */
 enum file_close_type {NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE};
 
+/* Used in SMB_FS_OBJECTID_INFORMATION requests.  Must be exactly 48 bytes. */
+#define SAMBA_EXTENDED_INFO_MAGIC 0x536d4261 /* "SmBa" */
+#define SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH 28
+struct smb_extended_info {
+       uint32 samba_magic;             /* Always SAMBA_EXTRA_INFO_MAGIC */
+       uint32 samba_version;           /* Major/Minor/Release/Revision */
+       uint32 samba_subversion;        /* Prerelease/RC/Vendor patch */
+       NTTIME samba_gitcommitdate;
+       char   samba_version_string[SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH];
+};
+
 #endif /* _SMB_H */
index d03cf3477dc2202484ff95db2e6f8a5ba7192899..ca176aabb2b2f257d19ae384b970f09078db36d3 100644 (file)
 /* Leave at 22 - not yet released. Remove parameter fd from write. - obnox */
 /* Leave at 22 - not yet released. Remove parameter fromfd from sendfile. - obnox */
 /* Leave at 22 - not yet released. Remove parameter fromfd from recvfile. - obnox */
-/* Leave at 22 - not yet released. Additional change: add operations for offline files and remote storage volume abstraction -- ab*/
+/* Leave at 22 - not yet released. Additional change: add operations for offline files -- ab */
+/* Leave at 22 - not yet released. Add the streaminfo call. -- jpeach, vl */
 
 #define SMB_VFS_INTERFACE_VERSION 22
 
@@ -148,6 +149,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_SET_QUOTA,
        SMB_VFS_OP_GET_SHADOW_COPY_DATA,
        SMB_VFS_OP_STATVFS,
+       SMB_VFS_OP_FS_CAPABILITIES,
 
        /* Directory operations */
 
@@ -198,6 +200,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_NOTIFY_WATCH,
        SMB_VFS_OP_CHFLAGS,
        SMB_VFS_OP_FILE_ID_CREATE,
+       SMB_VFS_OP_STREAMINFO,
 
        /* NT ACL operations. */
 
@@ -282,6 +285,7 @@ struct vfs_ops {
                int (*set_quota)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
                int (*get_shadow_copy_data)(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, bool labels);
                int (*statvfs)(struct vfs_handle_struct *handle, const char *path, struct vfs_statvfs_struct *statbuf);
+               uint32_t (*fs_capabilities)(struct vfs_handle_struct *handle);
 
                /* Directory operations */
 
@@ -339,6 +343,13 @@ struct vfs_ops {
                int (*chflags)(struct vfs_handle_struct *handle, const char *path, unsigned int flags);
                struct file_id (*file_id_create)(struct vfs_handle_struct *handle, SMB_DEV_T dev, SMB_INO_T inode);
 
+               NTSTATUS (*streaminfo)(struct vfs_handle_struct *handle,
+                                      struct files_struct *fsp,
+                                      const char *fname,
+                                      TALLOC_CTX *mem_ctx,
+                                      unsigned int *num_streams,
+                                      struct stream_struct **streams);
+
                /* NT ACL operations. */
 
                NTSTATUS (*fget_nt_acl)(struct vfs_handle_struct *handle,
@@ -426,6 +437,7 @@ struct vfs_ops {
                struct vfs_handle_struct *set_quota;
                struct vfs_handle_struct *get_shadow_copy_data;
                struct vfs_handle_struct *statvfs;
+               struct vfs_handle_struct *fs_capabilities;
 
                /* Directory operations */
 
@@ -476,6 +488,7 @@ struct vfs_ops {
                struct vfs_handle_struct *notify_watch;
                struct vfs_handle_struct *chflags;
                struct vfs_handle_struct *file_id_create;
+               struct vfs_handle_struct *streaminfo;
 
                /* NT ACL operations. */
 
index dd30f977dc8adb5fbeb65da269e6f21d6b1c3ca9..1e64bd5ac3ef7ca8586c242322dc47b89c502857 100644 (file)
@@ -34,6 +34,7 @@
 #define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (qtype), (id), (qt)))
 #define SMB_VFS_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs.ops.get_shadow_copy_data((fsp)->conn->vfs.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
 #define SMB_VFS_STATVFS(conn, path, statbuf) ((conn)->vfs.ops.statvfs((conn)->vfs.handles.statvfs, (path), (statbuf)))
+#define SMB_VFS_FS_CAPABILITIES(conn) ((conn)->vfs.ops.fs_capabilities((conn)->vfs.handles.fs_capabilities))
 
 /* Directory operations */
 #define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (fname), (mask), (attr)))
@@ -82,6 +83,7 @@
 #define SMB_VFS_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs.ops.notify_watch((conn)->vfs.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
 #define SMB_VFS_CHFLAGS(conn, path, flags) ((conn)->vfs.ops.chflags((conn)->vfs.handles.chflags, (path), (flags)))
 #define SMB_VFS_FILE_ID_CREATE(conn, dev, inode) ((conn)->vfs.ops.file_id_create((conn)->vfs.handles.file_id_create, (dev), (inode)))
+#define SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs.ops.streaminfo((conn)->vfs.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 
 /* NT ACL operations. */
 #define SMB_VFS_FGET_NT_ACL(fsp, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
 #define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (qtype), (id), (qt)))
 #define SMB_VFS_OPAQUE_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs_opaque.ops.get_shadow_copy_data((fsp)->conn->vfs_opaque.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
 #define SMB_VFS_OPAQUE_STATVFS(conn, path, statbuf) ((conn)->vfs_opaque.ops.statvfs((conn)->vfs_opaque.handles.statvfs, (path), (statbuf)))
+#define SMB_VFS_OPAQUE_FS_CAPABILITIES(conn) ((conn)->vfs_opaque.ops.fs_capabilities((conn)->vfs_opaque.handles.fs_capabilities))
 
 /* Directory operations */
 #define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (fname), (mask), (attr)))
 #define SMB_VFS_OPAQUE_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_opaque.ops.notify_watch((conn)->vfs_opaque.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
 #define SMB_VFS_OPAQUE_CHFLAGS(conn, path, flags) ((conn)->vfs_opaque.ops.chflags((conn)->vfs_opaque.handles.chflags, (path), (flags)))
 #define SMB_VFS_OPAQUE_FILE_ID_CREATE(conn, dev, inode) ((conn)->vfs.ops_opaque.file_id_create((conn)->vfs_opaque.handles.file_id_create, (dev), (inode)))
+#define SMB_VFS_OPAQUE_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs_opaque.ops.streaminfo((conn)->vfs_opaque.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 
 /* NT ACL operations. */
 #define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
 #define SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (qtype), (id), (qt)))
 #define SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp, shadow_copy_data ,labels) ((handle)->vfs_next.ops.get_shadow_copy_data((handle)->vfs_next.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
 #define SMB_VFS_NEXT_STATVFS(handle, path, statbuf) ((handle)->vfs_next.ops.statvfs((handle)->vfs_next.handles.statvfs, (path), (statbuf)))
+#define SMB_VFS_NEXT_FS_CAPABILITIES(handle) ((handle)->vfs_next.ops.fs_capabilities((handle)->vfs_next.handles.fs_capabilities))
 
 /* Directory operations */
 #define SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (fname), (mask), (attr)))
 #define SMB_VFS_NEXT_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_next.ops.notify_watch((conn)->vfs_next.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
 #define SMB_VFS_NEXT_CHFLAGS(handle, path, flags) ((handle)->vfs_next.ops.chflags((handle)->vfs_next.handles.chflags, (path), (flags)))
 #define SMB_VFS_NEXT_FILE_ID_CREATE(handle, dev, inode) ((handle)->vfs_next.ops.file_id_create((handle)->vfs_next.handles.file_id_create, (dev), (inode)))
+#define SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, num_streams, streams) ((handle)->vfs.ops.streaminfo((handle)->vfs.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 
 /* NT ACL operations. */
 #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (security_info), (ppdesc)))
index a7d6f6c9f7fecd6df62aa8be1a4e3099a5120a82..9f5d81f44280cf39a6027facb3a781e62c1568a0 100644 (file)
@@ -42,20 +42,23 @@ static char *afs_encode_token(const char *cell, const DATA_BLOB ticket,
                              const struct ClearToken *ct)
 {
        char *base64_ticket;
-       char *result;
+       char *result = NULL;
 
        DATA_BLOB key = data_blob(ct->HandShakeKey, 8);
        char *base64_key;
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_stackframe();
+       if (mem_ctx == NULL)
+               goto done;
 
-       base64_ticket = base64_encode_data_blob(ticket);
+       base64_ticket = base64_encode_data_blob(mem_ctx, ticket);
        if (base64_ticket == NULL)
-               return NULL;
+               goto done;
 
-       base64_key = base64_encode_data_blob(key);
-       if (base64_key == NULL) {
-               TALLOC_FREE(base64_ticket);
-               return NULL;
-       }
+       base64_key = base64_encode_data_blob(mem_ctx, key);
+       if (base64_key == NULL)
+               goto done;
 
        asprintf(&result, "%s\n%u\n%s\n%u\n%u\n%u\n%s\n", cell,
                 ct->AuthHandle, base64_key, ct->ViceId, ct->BeginTimestamp,
@@ -63,8 +66,8 @@ static char *afs_encode_token(const char *cell, const DATA_BLOB ticket,
 
        DEBUG(10, ("Got ticket string:\n%s\n", result));
 
-       TALLOC_FREE(base64_ticket);
-       TALLOC_FREE(base64_key);
+done:
+       TALLOC_FREE(mem_ctx);
 
        return result;
 }
index aeef1c35203da77bb8cdc75d0e67c66a6fbe8d20..444f09efca09edaa6c064bbe0db26eaf177e1dac 100644 (file)
@@ -53,20 +53,21 @@ static bool afs_decode_token(const char *string, char **cell,
 {
        DATA_BLOB blob;
        struct ClearToken result_ct;
+       char *saveptr;
 
        char *s = SMB_STRDUP(string);
 
        char *t;
 
-       if ((t = strtok(s, "\n")) == NULL) {
-               DEBUG(10, ("strtok failed\n"));
+       if ((t = strtok_r(s, "\n", &saveptr)) == NULL) {
+               DEBUG(10, ("strtok_r failed\n"));
                return False;
        }
 
        *cell = SMB_STRDUP(t);
 
-       if ((t = strtok(NULL, "\n")) == NULL) {
-               DEBUG(10, ("strtok failed\n"));
+       if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
+               DEBUG(10, ("strtok_r failed\n"));
                return False;
        }
 
@@ -75,8 +76,8 @@ static bool afs_decode_token(const char *string, char **cell,
                return False;
        }
                
-       if ((t = strtok(NULL, "\n")) == NULL) {
-               DEBUG(10, ("strtok failed\n"));
+       if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
+               DEBUG(10, ("strtok_r failed\n"));
                return False;
        }
 
@@ -93,8 +94,8 @@ static bool afs_decode_token(const char *string, char **cell,
 
        data_blob_free(&blob);
 
-       if ((t = strtok(NULL, "\n")) == NULL) {
-               DEBUG(10, ("strtok failed\n"));
+       if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
+               DEBUG(10, ("strtok_r failed\n"));
                return False;
        }
 
@@ -103,8 +104,8 @@ static bool afs_decode_token(const char *string, char **cell,
                return False;
        }
                
-       if ((t = strtok(NULL, "\n")) == NULL) {
-               DEBUG(10, ("strtok failed\n"));
+       if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
+               DEBUG(10, ("strtok_r failed\n"));
                return False;
        }
 
@@ -113,8 +114,8 @@ static bool afs_decode_token(const char *string, char **cell,
                return False;
        }
                
-       if ((t = strtok(NULL, "\n")) == NULL) {
-               DEBUG(10, ("strtok failed\n"));
+       if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
+               DEBUG(10, ("strtok_r failed\n"));
                return False;
        }
 
@@ -123,8 +124,8 @@ static bool afs_decode_token(const char *string, char **cell,
                return False;
        }
                
-       if ((t = strtok(NULL, "\n")) == NULL) {
-               DEBUG(10, ("strtok failed\n"));
+       if ((t = strtok_r(NULL, "\n", &saveptr)) == NULL) {
+               DEBUG(10, ("strtok_r failed\n"));
                return False;
        }
 
index e87ceb428ffba5954ba58b75c487159832fa2527..18f94959315e4357e3cd032b81b1fcb08ccbc6e9 100644 (file)
@@ -91,7 +91,6 @@ static struct db_record *db_tdb_fetch_locked(struct db_context *db,
        struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
                                                       struct db_tdb_ctx);
        struct tdb_fetch_locked_state state;
-       int res;
 
        /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
        if(DEBUGLEVEL >= 10) {
@@ -110,8 +109,7 @@ static struct db_record *db_tdb_fetch_locked(struct db_context *db,
        state.mem_ctx = mem_ctx;
        state.result = NULL;
 
-       res = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse,
-                              &state);
+       tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);
 
        if (state.result == NULL) {
                db_tdb_fetchlock_parse(key, tdb_null, &state);
index 6c1bfea04f74fa2a7ba421218b7cf648ae5f6161..51bb0d754182a99d880d2c56f11e2e772e346a80 100644 (file)
@@ -429,8 +429,9 @@ static bool debug_parse_params(char **params)
 
        /* Fill in new debug class levels */
        for (; i < debug_num_classes && params[i]; i++) {
-               if ((class_name=strtok(params[i],":")) &&
-                       (class_level=strtok(NULL, "\0")) &&
+               char *saveptr;
+               if ((class_name = strtok_r(params[i],":", &saveptr)) &&
+                       (class_level = strtok_r(NULL, "\0", &saveptr)) &&
             ((ndx = debug_lookup_classname(class_name)) != -1)) {
                                DEBUGLEVEL_CLASS[ndx] = atoi(class_level);
                                DEBUGLEVEL_CLASS_ISSET[ndx] = True;
index 885a1c55b29170d2bdb1afc885b73da7c00343c9..8194cf80cce48ae9760a1bb7d3b277e2d6060e2a 100644 (file)
@@ -92,6 +92,9 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
 #ifdef EWOULDBLOCK
        { EWOULDBLOCK, ERRDOS, 111, NT_STATUS_NETWORK_BUSY },
 #endif
+#ifdef ENOATTR
+       { ENOATTR, ERRDOS, ERRbadfile, NT_STATUS_NOT_FOUND },
+#endif
 
        { 0, 0, 0, NT_STATUS_OK }
 };
index 7a5283a4d60c1ba773437572f1844ca3ef869644..f866b3648fcf977b87e94e7681e051210a773aad 100644 (file)
@@ -153,6 +153,26 @@ AC_HAVE_TYPE([struct sockaddr_in6], [
 #include <netinet/in.h>
 ])
 
+if test x"$ac_cv_type_struct_sockaddr_storage" = x"yes"; then
+AC_CHECK_MEMBER(struct sockaddr_storage.ss_family,
+                AC_DEFINE(HAVE_SS_FAMILY, 1, [Defined if struct sockaddr_storage has ss_family field]),,
+                [
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+               ])
+
+if test x"$ac_cv_member_struct_sockaddr_storage_ss_family" != x"yes"; then
+AC_CHECK_MEMBER(struct sockaddr_storage.__ss_family,
+                AC_DEFINE(HAVE___SS_FAMILY, 1, [Defined if struct sockaddr_storage has __ss_family field]),,
+                [
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+               ])
+fi
+fi
+
 AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror)
 AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename)
 AC_CHECK_FUNCS(waitpid strlcpy strlcat initgroups memmove strdup)
index a01bf1b2904df87b2a5365bb10b8d2a462365b8c..bf5056838d0ca2a30539ca5bc75f1104f38bf562 100644 (file)
@@ -48,8 +48,7 @@ LIBREPLACE_C99_STRUCT_INIT([],[AC_MSG_WARN([c99 structure initializer are not su
 AC_PROG_INSTALL
 
 AC_ISC_POSIX
-AC_EXTENSION_FLAG(_XOPEN_SOURCE_EXTENDED)
-AC_EXTENSION_FLAG(_OSF_SOURCE)
+AC_N_DEFINE(_XOPEN_SOURCE_EXTENDED)
 
 AC_SYS_LARGEFILE
 
@@ -77,6 +76,11 @@ case "$host_os" in
                        CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000"
                fi
                ;;
+       *osf*)
+               # this brings in socklen_t
+               AC_N_DEFINE(_XOPEN_SOURCE,600)
+               AC_N_DEFINE(_OSF_SOURCE)
+               ;;
        #
        # VOS may need to have POSIX support and System V compatibility enabled.
        #
index cb8e21434e9de5b2d031ce9eb457ef9042c42fb2..2aec69896702500a159b858de2dcca4863a045e8 100644 (file)
@@ -265,7 +265,7 @@ AC_DEFUN([AC_LIBREPLACE_LD_SHLIB_ALLOW_UNDEF_FLAG],
                        LD_SHLIB_ALLOW_UNDEF_FLAG="-Wl,--allow-shlib-undefined"
                        ;;
                *osf*)
-                       LD_SHLIB_ALLOW_UNDEF_FLAG="-expect_unresolved '*'"
+                       LD_SHLIB_ALLOW_UNDEF_FLAG="-Wl,-expect_unresolved,\"*\""
                        ;;
                *darwin*)
                        LD_SHLIB_ALLOW_UNDEF_FLAG="-undefined dynamic_lookup"
index 92fecd3db84aad32e3e2840e1a3e019b8a828ecb..1856eacf66e4fc31f1fd1af1abdb7a626b5ff72f 100644 (file)
@@ -87,19 +87,6 @@ fi
 rm -f conftest*
 ])])
 
-AC_DEFUN([AC_EXTENSION_FLAG],
-[
-  cat >>confdefs.h <<\EOF
-#ifndef $1
-# define $1 1
-#endif
-EOF
-AH_VERBATIM([$1], [#ifndef $1
-# define $1 1
-#endif])
-])
-
-
 dnl see if a declaration exists for a function or variable
 dnl defines HAVE_function_DECL if it exists
 dnl AC_HAVE_DECL(var, includes)
@@ -248,11 +235,18 @@ m4_define([AH_CHECK_FUNC_EXT],
 
 dnl Define an AC_DEFINE with ifndef guard.
 dnl AC_N_DEFINE(VARIABLE [, VALUE])
-define(AC_N_DEFINE,
-[cat >> confdefs.h <<\EOF
-[#ifndef] $1
-[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1)
-[#endif]
+AC_DEFUN([AC_N_DEFINE],
+[
+AH_VERBATIM([$1], [
+#ifndef $1
+# undef $1
+#endif
+])
+
+ cat >>confdefs.h <<\EOF
+#ifndef $1
+[#define] $1 m4_if($#, 1, 1, [$2])
+#endif
 EOF
 ])
 
index 799187af7d47d00eb914238a6a699a5207161165..1c05733126d81c208b30435ce04c3ed6e77f8b89 100644 (file)
@@ -73,6 +73,18 @@ AC_VERIFY_C_PROTOTYPE([struct passwd *getpwent_r(struct passwd *src, char *buf,
        #include <unistd.h>
        #include <pwd.h>
        ])
+AC_VERIFY_C_PROTOTYPE([struct passwd *getpwent_r(struct passwd *src, char *buf, size_t buflen)],
+       [
+       #ifndef HAVE_GETPWENT_R_DECL
+       #error missing getpwent_r prototype
+       #endif
+       return NULL;
+       ],[
+       AC_DEFINE(SOLARIS_GETPWENT_R, 1, [getpwent_r irix (similar to solaris) function prototype])
+       ],[],[
+       #include <unistd.h>
+       #include <pwd.h>
+       ])
 AC_CHECK_FUNCS(getgrnam_r getgrgid_r getgrent_r)
 AC_HAVE_DECL(getgrent_r, [
        #include <unistd.h>
@@ -91,6 +103,19 @@ AC_VERIFY_C_PROTOTYPE([struct group *getgrent_r(struct group *src, char *buf, in
        #include <grp.h>
        ])
 
+AC_VERIFY_C_PROTOTYPE([struct group *getgrent_r(struct group *src, char *buf, size_t buflen)],
+       [
+       #ifndef HAVE_GETGRENT_R_DECL
+       #error missing getgrent_r prototype
+       #endif
+       return NULL;
+       ],[
+       AC_DEFINE(SOLARIS_GETGRENT_R, 1, [getgrent_r irix (similar to solaris)  function prototype])
+       ],[],[
+       #include <unistd.h>
+       #include <grp.h>
+       ])
+
 # locale
 AC_CHECK_HEADERS(ctype.h locale.h)
 
index b6ae3c7c6f83f770add7888b6782d1a8fd1dfc99..fe6e46817f66ec30edefd419cb2225b0ab031dd3 100644 (file)
@@ -227,14 +227,19 @@ typedef unsigned short int sa_family_t;
 #ifdef HAVE_STRUCT_SOCKADDR_IN6
 #define sockaddr_storage sockaddr_in6
 #define ss_family sin6_family
+#define HAVE_SS_FAMILY 1
 #else
 #define sockaddr_storage sockaddr_in
 #define ss_family sin_family
+#define HAVE_SS_FAMILY 1
 #endif
 #endif
 
-#ifdef HAVE_AIX_SOCKADDR_STORAGE
+#ifndef HAVE_SS_FAMILY
+#ifdef HAVE___SS_FAMILY
 #define ss_family __ss_family
+#define HAVE_SS_FAMILY 1
+#endif
 #endif
 
 #ifndef HAVE_STRUCT_ADDRINFO
diff --git a/source3/lib/replace/system/printing.h b/source3/lib/replace/system/printing.h
deleted file mode 100644 (file)
index 7eb02d0..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _system_printing_h
-#define _system_printing_h
-
-/* 
-   Unix SMB/CIFS implementation.
-
-   printing system include wrappers
-
-   Copyright (C) Andrew Tridgell 2004
-   
-     ** NOTE! The following LGPL license applies to the replace
-     ** library. This does NOT imply that all of Samba is released
-     ** under the LGPL
-   
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 3 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef AIX
-#define DEFAULT_PRINTING PRINT_AIX
-#define PRINTCAP_NAME "/etc/qconfig"
-#endif
-
-#ifdef HPUX
-#define DEFAULT_PRINTING PRINT_HPUX
-#endif
-
-#ifdef QNX
-#define DEFAULT_PRINTING PRINT_QNX
-#endif
-
-#ifndef DEFAULT_PRINTING
-#define DEFAULT_PRINTING PRINT_BSD
-#endif
-#ifndef PRINTCAP_NAME
-#define PRINTCAP_NAME "/etc/printcap"
-#endif
-
-#endif
index 269a2ff5d625cd26c7daf720efb90edf9c97fb2f..5b95ae395ce3b19d634c25174d056790148f5ef5 100644 (file)
@@ -37,7 +37,6 @@
 #include "system/locale.h"
 #include "system/network.h"
 #include "system/passwd.h"
-#include "system/printing.h"
 #include "system/readline.h"
 #include "system/select.h"
 #include "system/shmem.h"
index eb6dcae6fb1f0c57357a54cfe67acbfe7a901da4..fa50955ef64cedee89a0d247fd78d74736617e74 100644 (file)
@@ -1917,11 +1917,6 @@ int sys_fremovexattr (int filedes, const char *name)
 #endif
 }
 
-#if !defined(HAVE_SETXATTR)
-#define XATTR_CREATE  0x1       /* set value, fail if attr already exists */
-#define XATTR_REPLACE 0x2       /* set value, fail if attr does not exist */
-#endif
-
 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
 {
 #if defined(HAVE_SETXATTR)
index bc3eaa8d5e95b8cd600bc7ea62e15534a4dc3a5b..e5ac3752f5ed52bc73a790008e25ea3fe49fcb0d 100644 (file)
@@ -2182,7 +2182,7 @@ void dump_data_pw(const char *msg, const uchar * data, size_t len)
 
 const char *tab_depth(int level, int depth)
 {
-       if( DEBUGLVL(level) ) {
+       if( CHECK_DEBUGLVL(level) ) {
                dbgtext("%*s", depth*4, "");
        }
        return "";
@@ -3273,3 +3273,93 @@ void *talloc_zeronull(const void *context, size_t size, const char *name)
        return talloc_named_const(context, size, name);
 }
 #endif
+
+/* Split a path name into filename and stream name components. Canonicalise
+ * such that an implicit $DATA token is always explicit.
+ *
+ * The "specification" of this function can be found in the
+ * run_local_stream_name() function in torture.c, I've tried those
+ * combinations against a W2k3 server.
+ */
+
+NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
+                               char **pbase, char **pstream)
+{
+       char *base = NULL;
+       char *stream = NULL;
+       char *sname; /* stream name */
+       const char *stype; /* stream type */
+
+       DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
+
+       sname = strchr_m(fname, ':');
+
+       if (lp_posix_pathnames() || (sname == NULL)) {
+               if (pbase != NULL) {
+                       base = talloc_strdup(mem_ctx, fname);
+                       NT_STATUS_HAVE_NO_MEMORY(base);
+               }
+               goto done;
+       }
+
+       if (pbase != NULL) {
+               base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
+               NT_STATUS_HAVE_NO_MEMORY(base);
+       }
+
+       sname += 1;
+
+       stype = strchr_m(sname, ':');
+
+       if (stype == NULL) {
+               sname = talloc_strdup(mem_ctx, sname);
+               stype = "$DATA";
+       }
+       else {
+               if (StrCaseCmp(stype, ":$DATA") != 0) {
+                       /*
+                        * If there is an explicit stream type, so far we only
+                        * allow $DATA. Is there anything else allowed? -- vl
+                        */
+                       DEBUG(10, ("[%s] is an invalid stream type\n", stype));
+                       TALLOC_FREE(base);
+                       return NT_STATUS_OBJECT_NAME_INVALID;
+               }
+               sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
+               stype += 1;
+       }
+
+       if (sname == NULL) {
+               TALLOC_FREE(base);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (sname[0] == '\0') {
+               /*
+                * no stream name, so no stream
+                */
+               goto done;
+       }
+
+       if (pstream != NULL) {
+               stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
+               if (stream == NULL) {
+                       TALLOC_FREE(sname);
+                       TALLOC_FREE(base);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               /*
+                * upper-case the type field
+                */
+               strupper_m(strchr_m(stream, ':')+1);
+       }
+
+ done:
+       if (pbase != NULL) {
+               *pbase = base;
+       }
+       if (pstream != NULL) {
+               *pstream = stream;
+       }
+       return NT_STATUS_OK;
+}
index 10428113ae8b4b6d4ab13dcc7478b1f6775ae540..1a7cc0222901c077028a6dac40019a43054bad70 100644 (file)
@@ -1054,44 +1054,7 @@ ssize_t read_socket_with_timeout(int fd,
 
 ssize_t read_data(int fd,char *buffer,size_t N, enum smb_read_errors *pre)
 {
-       ssize_t ret;
-       size_t total=0;
-       char addr[INET6_ADDRSTRLEN];
-
-       set_smb_read_error(pre,SMB_READ_OK);
-
-       while (total < N) {
-               ret = sys_read(fd,buffer + total,N - total);
-
-               if (ret == 0) {
-                       DEBUG(10,("read_data: read of %d returned 0. "
-                               "Error = %s\n",
-                               (int)(N - total), strerror(errno) ));
-                       set_smb_read_error(pre,SMB_READ_EOF);
-                       return 0;
-               }
-
-               if (ret == -1) {
-                       if (fd == get_client_fd()) {
-                               /* Try and give an error message saying
-                                * what client failed. */
-                               DEBUG(0,("read_data: read failure for %d "
-                                       "bytes to client %s. Error = %s\n",
-                                       (int)(N - total),
-                                       get_peer_addr(fd,addr,sizeof(addr)),
-                                       strerror(errno) ));
-                       } else {
-                               DEBUG(0,("read_data: read failure for %d. "
-                                       "Error = %s\n",
-                                       (int)(N - total),
-                                       strerror(errno) ));
-                       }
-                       set_smb_read_error(pre,SMB_READ_ERROR);
-                       return -1;
-               }
-               total += ret;
-       }
-       return (ssize_t)total;
+       return read_socket_with_timeout(fd, buffer, N, N, 0, pre);
 }
 
 /****************************************************************************
@@ -1163,12 +1126,7 @@ ssize_t read_smb_length_return_keepalive(int fd,
        bool ok = false;
 
        while (!ok) {
-               if (timeout > 0) {
-                       ok = (read_socket_with_timeout(fd,inbuf,4,4,
-                                               timeout,pre) == 4);
-               } else {
-                       ok = (read_data(fd,inbuf,4,pre) == 4);
-               }
+               ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout,pre) == 4);
                if (!ok) {
                        return -1;
                }
@@ -1274,16 +1232,8 @@ ssize_t receive_smb_raw(int fd,
                        len = MIN(len,maxlen);
                }
 
-               if (timeout > 0) {
-                       ret = read_socket_with_timeout(fd,
-                                       buffer+4,
-                                       len,
-                                       len,
-                                       timeout,
-                                       pre);
-               } else {
-                       ret = read_data(fd,buffer+4,len,pre);
-               }
+               ret = read_socket_with_timeout(fd, buffer+4, len, len, timeout,
+                                              pre);
 
                if (ret != len) {
                        cond_set_smb_read_error(pre,SMB_READ_ERROR);
@@ -2080,14 +2030,15 @@ const char *get_mydnsfullname(void)
                        data_blob_string_const("get_mydnsfullname"),
                        data_blob_string_const(res->ai_canonname));
 
-       freeaddrinfo(res);
-
        if (!memcache_lookup(NULL, SINGLETON_CACHE,
                        data_blob_string_const("get_mydnsfullname"),
                        &tmp)) {
-               return NULL;
+               tmp = data_blob_talloc(talloc_tos(), res->ai_canonname,
+                               strlen(res->ai_canonname) + 1);
        }
 
+       freeaddrinfo(res);
+
        return (const char *)tmp.data;
 }
 
index 3e3268104c0458822bef39d546203f628565018b..bcb9197141c71ea0bbf5ba9e374f722873c1c7d7 100644 (file)
@@ -2415,13 +2415,13 @@ void base64_decode_inplace(char *s)
 }
 
 /**
- * Encode a base64 string into a malloc()ed string caller to free.
+ * Encode a base64 string into a talloc()ed string caller to free.
  *
  * From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c
  * with adjustments
  **/
 
-char *base64_encode_data_blob(DATA_BLOB data)
+char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
 {
        int bits = 0;
        int char_count = 0;
@@ -2434,7 +2434,7 @@ char *base64_encode_data_blob(DATA_BLOB data)
        out_cnt = 0;
        len = data.length;
        output_len = data.length * 2;
-       result = TALLOC_ARRAY(talloc_tos(), char, output_len); /* get us plenty of space */
+       result = TALLOC_ARRAY(mem_ctx, char, output_len); /* get us plenty of space */
        SMB_ASSERT(result != NULL);
 
        while (len-- && out_cnt < (data.length * 2) - 5) {
index 204c2044a8d2576f988d9d49011a93b34f7c972b..3cae02ad2ee096c2cae125c1b707f1fdcc891e03 100644 (file)
@@ -51,6 +51,8 @@ const char *samba_version_string(void)
         */
        assert(res != -1);
 
+       SAFE_FREE(samba_version);
+
        samba_version = tmp_version;
 #endif
 
index 44bcdf76eaf219ee6d298a4ddc8af9c233e7a465..8cc2f1215e24fe8a616b92b8addc8b6bff64518b 100644 (file)
@@ -29,7 +29,8 @@ char *ads_build_path(const char *realm, const char *sep, const char *field, int
        int numbits = 0;
        char *ret;
        int len;
-       
+       char *saveptr;
+
        r = SMB_STRDUP(realm);
 
        if (!r || !*r) {
@@ -51,11 +52,11 @@ char *ads_build_path(const char *realm, const char *sep, const char *field, int
        }
 
        strlcpy(ret,field, len);
-       p=strtok(r,sep); 
+       p=strtok_r(r, sep, &saveptr);
        if (p) {
                strlcat(ret, p, len);
        
-               while ((p=strtok(NULL,sep))) {
+               while ((p=strtok_r(NULL, sep, &saveptr)) != NULL) {
                        char *s;
                        if (reverse)
                                asprintf(&s, "%s%s,%s", field, p, ret);
index d20e10b14168c7e348565fdebd1281af958d5ab9..4d998acad80537c809f89a519357332dba0cc15c 100644 (file)
@@ -48,6 +48,10 @@ static WERROR libnet_conf_add_string_to_array(TALLOC_CTX *mem_ctx,
        }
 
        new_array[count] = talloc_strdup(new_array, string);
+       if (new_array[count] == NULL) {
+               TALLOC_FREE(new_array);
+               return WERR_NOMEM;
+       }
 
        *array = new_array;
 
@@ -134,6 +138,10 @@ static WERROR libnet_conf_reg_open_service_key(TALLOC_CTX *mem_ctx,
        }
 
        path = talloc_asprintf(mem_ctx, "%s\\%s", KEY_SMBCONF, servicename);
+       if (path == NULL) {
+               werr = WERR_NOMEM;
+               goto done;
+       }
 
        werr = libnet_conf_reg_open_path(mem_ctx, ctx, path, desired_access,
                                         key);
@@ -191,7 +199,7 @@ static WERROR libnet_conf_reg_create_service_key(TALLOC_CTX *mem_ctx,
        /* create a new talloc ctx for creation. it will hold
         * the intermediate parent key (SMBCONF) for creation
         * and will be destroyed when leaving this function... */
-       if (!(create_ctx = talloc_new(mem_ctx))) {
+       if (!(create_ctx = talloc_stackframe())) {
                werr = WERR_NOMEM;
                goto done;
        }
@@ -316,8 +324,12 @@ static char *libnet_conf_format_registry_value(TALLOC_CTX *mem_ctx,
        case REG_MULTI_SZ: {
                 uint32 j;
                 for (j = 0; j < value->v.multi_sz.num_strings; j++) {
-                        result = talloc_asprintf(mem_ctx, "\"%s\" ",
+                        result = talloc_asprintf(mem_ctx, "%s \"%s\" ",
+                                                result,
                                                 value->v.multi_sz.strings[j]);
+                       if (result == NULL) {
+                               break;
+                       }
                 }
                 break;
         }
@@ -357,7 +369,7 @@ static WERROR libnet_conf_reg_get_values(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-       tmp_ctx = talloc_new(mem_ctx);
+       tmp_ctx = talloc_stackframe();
        if (tmp_ctx == NULL) {
                werr = WERR_NOMEM;
                goto done;
@@ -540,7 +552,7 @@ WERROR libnet_conf_get_config(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-       tmp_ctx = talloc_new(mem_ctx);
+       tmp_ctx = talloc_stackframe();
        if (tmp_ctx == NULL) {
                werr = WERR_NOMEM;
                goto done;
@@ -615,7 +627,7 @@ WERROR libnet_conf_get_share_names(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-       tmp_ctx = talloc_new(mem_ctx);
+       tmp_ctx = talloc_stackframe();
        if (tmp_ctx == NULL) {
                werr = WERR_NOMEM;
                goto done;
index a9978ba4b872c659926e3c02bc6a69786c6412fb..538cca7994c283f37f068da9dbe3a5078dc1ded5 100644 (file)
@@ -684,10 +684,15 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
        const_acct_name = acct_name;
 
        if (r->in.join_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE) {
+               uint32 acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
+                       SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
+                       SAMR_STANDARD_DELETE | SAMR_USER_SETPASS |
+                       SAMR_USER_GETATTR | SAMR_USER_SETATTR;
+
                status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx,
                                                     &domain_pol,
                                                     acct_name, ACB_WSTRUST,
-                                                    0xe005000b, &user_pol,
+                                                    acct_flags, &user_pol,
                                                     &user_rid);
                if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
                        if (!(r->in.join_flags &
index 4560521d4a2b72bc845a7a28d93e62f9c505037c..f3926b777b92e9381e416200fe7fbb80427eb3f1 100644 (file)
@@ -872,13 +872,27 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
                        !strequal(star_smbserver_name,
                                cli->desthost)) {
                        char *realm = NULL;
+                       char *machine = NULL;
+                       char *host = NULL;
                        DEBUG(3,("cli_session_setup_spnego: got a "
                                "bad server principal, trying to guess ...\n"));
 
+                       host = strchr_m(cli->desthost, '.');
+                       if (host) {
+                               machine = SMB_STRNDUP(cli->desthost,
+                                       host - cli->desthost);
+                       } else {
+                               machine = SMB_STRDUP(cli->desthost);
+                       }
+                       if (machine == NULL) {
+                               return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+                       }
+
                        realm = kerberos_get_default_realm_from_ccache();
                        if (realm && *realm) {
                                if (asprintf(&principal, "%s$@%s",
-                                               cli->desthost, realm) < 0) {
+                                               machine, realm) < 0) {
+                                       SAFE_FREE(machine);
                                        SAFE_FREE(realm);
                                        return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
                                }
@@ -886,6 +900,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
                                        "server principal=%s\n",
                                        principal ? principal : "<null>"));
                        }
+                       SAFE_FREE(machine);
                        SAFE_FREE(realm);
                }
 
index ecef293d0790b951178cc34566dd07872572ecc1..042b3bdfb041cbe7b53b65e13e7d9ac87921db73 100644 (file)
@@ -180,12 +180,8 @@ bool cli_receive_smb(struct cli_state *cli)
 
 ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len)
 {
-       if (cli->timeout > 0) {
-               return read_socket_with_timeout(cli->fd, buffer, len,
-                                               len, cli->timeout, &cli->smb_rw_error);
-       } else {
-               return read_data(cli->fd, buffer, len, &cli->smb_rw_error);
-       }
+       return read_socket_with_timeout(cli->fd, buffer, len, len,
+                                       cli->timeout, &cli->smb_rw_error);
 }
 
 /****************************************************************************
index 2fd8294d046ed1eb7421a42025359e8295482686..2eb580a52d416aa071e5a85e586cb2ec3538360e 100644 (file)
@@ -4689,7 +4689,15 @@ dos_attr_parse(SMBCCTX *context,
        frame = talloc_stackframe();
        while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) {
                if (StrnCaseCmp(tok, "MODE:", 5) == 0) {
-                       dad->mode = strtol(tok+5, NULL, 16);
+                        long request = strtol(tok+5, NULL, 16);
+                        if (request == 0) {
+                                dad->mode = (request |
+                                             (IS_DOS_DIR(dad->mode)
+                                              ? FILE_ATTRIBUTE_DIRECTORY
+                                              : FILE_ATTRIBUTE_NORMAL));
+                        } else {
+                                dad->mode = request;
+                        }
                        continue;
                }
 
@@ -5931,7 +5939,7 @@ smbc_setxattr_ctx(SMBCCTX *context,
                 } else {
                         ret = cacl_set(talloc_tos(), srv->cli,
                                        ipc_srv->cli, &ipc_srv->pol, path,
-                                       namevalue, SMBC_XATTR_MODE_CHOWN, 0);
+                                       namevalue, SMBC_XATTR_MODE_CHGRP, 0);
                 }
                TALLOC_FREE(frame);
                 return ret;
index 732dc78c75ea6687f30a35419f7514ecd65b8c9f..1ca7d56a83621b1083dae20a2a8f68a0aa7919af 100644 (file)
@@ -40,7 +40,7 @@ static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX
           already have valid creds. If not we must set them up. */
 
        if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
-               uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+               uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
 
                result = rpccli_netlogon_setup_creds(cli, 
                                        cli->cli->desthost, /* server name */
index 4191871bb1a200bedf84b35075d663cb1eab1f01..341d00f3fe0aac5d0b77cedce5b83f88c43077d8 100644 (file)
@@ -1539,11 +1539,6 @@ int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
 
 static int byte_range_lock_destructor(struct byte_range_lock *br_lck)
 {
-       TDB_DATA key;
-
-       key.dptr = (uint8 *)&br_lck->key;
-       key.dsize = sizeof(struct file_id);
-
        if (br_lck->read_only) {
                SMB_ASSERT(!br_lck->modified);
        }
index 31234f23ecfc86b2edf66d9e62e69bfb216410b8..cf135dfd0302c68ff26d2306e06a65163b3dada4 100644 (file)
@@ -90,6 +90,17 @@ static int vfswrap_statvfs(struct vfs_handle_struct *handle,  const char *path,
        return sys_statvfs(path, statbuf);
 }
 
+static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle)
+{
+#if defined(DARWINOS)
+       struct vfs_statvfs_struct statbuf;
+       ZERO_STRUCT(statbuf);
+       sys_statvfs(handle->conn->connectpath, &statbuf);
+       return statbuf.FsCapabilities;
+#endif
+       return FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
+}
+
 /* Directory operations */
 
 static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *fname, const char *mask, uint32 attr)
@@ -942,6 +953,62 @@ static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle, S
        return file_id_create_dev(dev, inode);
 }
 
+static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
+                                  struct files_struct *fsp,
+                                  const char *fname,
+                                  TALLOC_CTX *mem_ctx,
+                                  unsigned int *pnum_streams,
+                                  struct stream_struct **pstreams)
+{
+       SMB_STRUCT_STAT sbuf;
+       unsigned int num_streams = 0;
+       struct stream_struct *streams = NULL;
+       int ret;
+
+       if ((fsp != NULL) && (fsp->is_directory)) {
+               /*
+                * No default streams on directories
+                */
+               goto done;
+       }
+
+       if ((fsp != NULL) && (fsp->fh->fd != -1)) {
+               ret = SMB_VFS_FSTAT(fsp, &sbuf);
+       }
+       else {
+               ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
+       }
+
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+
+       if (S_ISDIR(sbuf.st_mode)) {
+               goto done;
+       }
+
+       streams = talloc(mem_ctx, struct stream_struct);
+
+       if (streams == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       streams->size = sbuf.st_size;
+       streams->alloc_size = get_allocation_size(handle->conn, fsp, &sbuf);
+
+       streams->name = talloc_strdup(streams, "::$DATA");
+       if (streams->name == NULL) {
+               TALLOC_FREE(streams);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       num_streams = 1;
+ done:
+       *pnum_streams = num_streams;
+       *pstreams = streams;
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
                                    files_struct *fsp,
                                    uint32 security_info, SEC_DESC **ppdesc)
@@ -1273,6 +1340,8 @@ static vfs_op_tuple vfs_default_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_statvfs),   SMB_VFS_OP_STATVFS,
         SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_fs_capabilities), SMB_VFS_OP_FS_CAPABILITIES,
+        SMB_VFS_LAYER_OPAQUE},
 
        /* Directory operations */
 
@@ -1367,6 +1436,8 @@ static vfs_op_tuple vfs_default_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_file_id_create),    SMB_VFS_OP_FILE_ID_CREATE,
         SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_streaminfo),        SMB_VFS_OP_STREAMINFO,
+        SMB_VFS_LAYER_OPAQUE},
 
        /* NT ACL operations. */
 
index fef65efa7790cd52ea79673e2fd5f1a7cb1bfc13..da1716719ae5a9d09ec1d08e0e0db9a49c1e5ae0 100644 (file)
@@ -269,6 +269,7 @@ static bool recycle_create_dir(vfs_handle_struct *handle, const char *dname)
        char *token;
        char *tok_str;
        bool ret = False;
+       char *saveptr;
 
        mode = recycle_directory_mode(handle);
 
@@ -286,7 +287,8 @@ static bool recycle_create_dir(vfs_handle_struct *handle, const char *dname)
        }
 
        /* Create directory tree if neccessary */
-       for(token = strtok(tok_str, "/"); token; token = strtok(NULL, "/")) {
+       for(token = strtok_r(tok_str, "/", &saveptr); token;
+           token = strtok_r(NULL, "/", &saveptr)) {
                safe_strcat(new_dir, token, len);
                if (recycle_directory_exist(handle, new_dir))
                        DEBUG(10, ("recycle: dir %s already exists\n", new_dir));
diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c
new file mode 100644 (file)
index 0000000..fa85ea4
--- /dev/null
@@ -0,0 +1,641 @@
+/*
+ * Store streams in a separate subdirectory
+ *
+ * Copyright (C) Volker Lendecke, 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+/*
+ * Excerpt from a mail from tridge:
+ *
+ * Volker, what I'm thinking of is this:
+ * /mount-point/.streams/XX/YY/aaaa.bbbb/namedstream1
+ * /mount-point/.streams/XX/YY/aaaa.bbbb/namedstream2
+ *
+ * where XX/YY is a 2 level hash based on the fsid/inode. "aaaa.bbbb"
+ * is the fsid/inode. "namedstreamX" is a file named after the stream
+ * name.
+ */
+
+static uint32_t hash_fn(DATA_BLOB key)
+{
+       uint32_t value; /* Used to compute the hash value.  */
+       uint32_t i;     /* Used to cycle through random values. */
+
+       /* Set the initial value from the key size. */
+       for (value = 0x238F13AF * key.length, i=0; i < key.length; i++)
+               value = (value + (key.data[i] << (i*5 % 24)));
+
+       return (1103515243 * value + 12345);
+}
+
+/*
+ * With the hashing scheme based on the inode we need to protect against
+ * streams showing up on files with re-used inodes. This can happen if we
+ * create a stream directory from within Samba, and a local process or NFS
+ * client deletes the file without deleting the streams directory. When the
+ * inode is re-used and the stream directory is still around, the streams in
+ * there would be show up as belonging to the new file.
+ *
+ * There are several workarounds for this, probably the easiest one is on
+ * systems which have a true birthtime stat element: When the file has a later
+ * birthtime than the streams directory, then we have to recreate the
+ * directory.
+ *
+ * The other workaround is to somehow mark the file as generated by Samba with
+ * something that a NFS client would not do. The closest one is a special
+ * xattr value being set. On systems which do not support xattrs, it might be
+ * an option to put in a special ACL entry for a non-existing group.
+ */
+
+#define SAMBA_XATTR_MARKER "user.SAMBA_STREAMS"
+
+static bool file_is_valid(vfs_handle_struct *handle, const char *path)
+{
+       char buf;
+
+       DEBUG(10, ("file_is_valid (%s) called\n", path));
+
+       if (SMB_VFS_NEXT_GETXATTR(handle, path, SAMBA_XATTR_MARKER,
+                                 &buf, sizeof(buf)) != sizeof(buf)) {
+               DEBUG(10, ("GETXATTR failed: %s\n", strerror(errno)));
+               return false;
+       }
+
+       if (buf != '1') {
+               DEBUG(10, ("got wrong buffer content: '%c'\n", buf));
+               return false;
+       }
+
+       return true;
+}
+
+static bool mark_file_valid(vfs_handle_struct *handle, const char *path)
+{
+       char buf = '1';
+       int ret;
+
+       DEBUG(10, ("marking file %s as valid\n", path));
+
+       ret = SMB_VFS_NEXT_SETXATTR(handle, path, SAMBA_XATTR_MARKER,
+                                   &buf, sizeof(buf), 0);
+
+       if (ret == -1) {
+               DEBUG(10, ("SETXATTR failed: %s\n", strerror(errno)));
+               return false;
+       }
+
+       return true;
+}
+
+static char *stream_dir(vfs_handle_struct *handle, const char *base_path,
+                       const SMB_STRUCT_STAT *base_sbuf, bool create_it)
+{
+       uint32_t hash;
+       char *result = NULL;
+       SMB_STRUCT_STAT sbuf;
+       uint8_t first, second;
+       char *tmp;
+       char *id_hex;
+       struct file_id id;
+       uint8 id_buf[16];
+
+       const char *rootdir = lp_parm_const_string(
+               SNUM(handle->conn), "streams", "directory",
+               handle->conn->connectpath);
+
+       if (base_sbuf == NULL) {
+               if (SMB_VFS_NEXT_STAT(handle, base_path, &sbuf) == -1) {
+                       /*
+                        * base file is not there
+                        */
+                       goto fail;
+               }
+               base_sbuf = &sbuf;
+       }
+
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, base_sbuf->st_dev,
+                                   base_sbuf->st_ino);
+
+       push_file_id_16((char *)id_buf, &id);
+
+       hash = hash_fn(data_blob_const(id_buf, sizeof(id_buf)));
+
+       first = hash & 0xff;
+       second = (hash >> 8) & 0xff;
+
+       id_hex = hex_encode(talloc_tos(), id_buf, sizeof(id_buf));
+
+       if (id_hex == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       result = talloc_asprintf(talloc_tos(), "%s/%2.2X/%2.2X/%s", rootdir,
+                                first, second, id_hex);
+
+       TALLOC_FREE(id_hex);
+
+       if (result == NULL) {
+               errno = ENOMEM;
+               return NULL;
+       }
+
+       if (SMB_VFS_NEXT_STAT(handle, result, &sbuf) == 0) {
+               char *newname;
+
+               if (!S_ISDIR(sbuf.st_mode)) {
+                       errno = EINVAL;
+                       goto fail;
+               }
+
+               if (file_is_valid(handle, base_path)) {
+                       return result;
+               }
+
+               /*
+                * Someone has recreated a file under an existing inode
+                * without deleting the streams directory. For now, just move
+                * it away.
+                */
+
+       again:
+               newname = talloc_asprintf(talloc_tos(), "lost-%lu", random());
+               if (newname == NULL) {
+                       errno = ENOMEM;
+                       goto fail;
+               }
+
+               if (SMB_VFS_NEXT_RENAME(handle, result, newname) == -1) {
+                       if ((errno == EEXIST) || (errno == ENOTEMPTY)) {
+                               TALLOC_FREE(newname);
+                               goto again;
+                       }
+                       goto fail;
+               }
+
+               TALLOC_FREE(newname);
+       }
+
+       if (!create_it) {
+               errno = ENOENT;
+               goto fail;
+       }
+
+       if ((SMB_VFS_NEXT_MKDIR(handle, rootdir, 0755) != 0)
+           && (errno != EEXIST)) {
+               goto fail;
+       }
+
+       tmp = talloc_asprintf(result, "%s/%2.2X", rootdir, first);
+       if (tmp == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       if ((SMB_VFS_NEXT_MKDIR(handle, tmp, 0755) != 0)
+           && (errno != EEXIST)) {
+               goto fail;
+       }
+
+       TALLOC_FREE(tmp);
+
+       tmp = talloc_asprintf(result, "%s/%2.2X/%2.2X", rootdir, first,
+                             second);
+       if (tmp == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       if ((SMB_VFS_NEXT_MKDIR(handle, tmp, 0755) != 0)
+           && (errno != EEXIST)) {
+               goto fail;
+       }
+
+       TALLOC_FREE(tmp);
+
+       if ((SMB_VFS_NEXT_MKDIR(handle, result, 0755) != 0)
+           && (errno != EEXIST)) {
+               goto fail;
+       }
+
+       if (!mark_file_valid(handle, base_path)) {
+               goto fail;
+       }
+
+       return result;
+
+ fail:
+       TALLOC_FREE(result);
+       return NULL;
+}
+
+static char *stream_name(vfs_handle_struct *handle, const char *fname,
+                        bool create_dir)
+{
+       char *base = NULL;
+       char *sname = NULL;
+       char *id_hex = NULL;
+       char *dirname, *stream_fname;
+
+       if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), fname,
+                                                   &base, &sname))) {
+               DEBUG(10, ("split_ntfs_stream_name failed\n"));
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       dirname = stream_dir(handle, base, NULL, create_dir);
+
+       if (dirname == NULL) {
+               goto fail;
+       }
+
+       stream_fname = talloc_asprintf(talloc_tos(), "%s/:%s", dirname, sname);
+
+       if (stream_fname == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       DEBUG(10, ("stream filename = %s\n", stream_fname));
+
+       TALLOC_FREE(base);
+       TALLOC_FREE(sname);
+       TALLOC_FREE(id_hex);
+
+       return stream_fname;
+
+ fail:
+       DEBUG(5, ("stream_name failed: %s\n", strerror(errno)));
+       TALLOC_FREE(base);
+       TALLOC_FREE(sname);
+       TALLOC_FREE(id_hex);
+       return NULL;
+}
+
+static NTSTATUS walk_streams(vfs_handle_struct *handle,
+                            const char *fname,
+                            const SMB_STRUCT_STAT *sbuf,
+                            char **pdirname,
+                            bool (*fn)(const char *dirname,
+                                       const char *dirent,
+                                       void *private_data),
+                            void *private_data)
+{
+       char *dirname;
+       SMB_STRUCT_DIR *dirhandle = NULL;
+       char *dirent;
+
+       dirname = stream_dir(handle, fname, sbuf, false);
+
+       if (dirname == NULL) {
+               if (errno == ENOENT) {
+                       /*
+                        * no stream around
+                        */
+                       return NT_STATUS_OK;
+               }
+               return map_nt_error_from_unix(errno);
+       }
+
+       DEBUG(10, ("walk_streams: dirname=%s\n", dirname));
+
+       dirhandle = SMB_VFS_NEXT_OPENDIR(handle, dirname, NULL, 0);
+
+       if (dirhandle == NULL) {
+               TALLOC_FREE(dirname);
+               return map_nt_error_from_unix(errno);
+       }
+
+       while ((dirent = vfs_readdirname(handle->conn, dirhandle)) != NULL) {
+
+               if (ISDOT(dirent) || ISDOTDOT(dirent)) {
+                       continue;
+               }
+
+               DEBUG(10, ("walk_streams: dirent=%s\n", dirent));
+
+               if (!fn(dirname, dirent, private_data)) {
+                       break;
+               }
+       }
+
+       SMB_VFS_NEXT_CLOSEDIR(handle, dirhandle);
+
+       if (pdirname != NULL) {
+               *pdirname = dirname;
+       }
+       else {
+               TALLOC_FREE(dirname);
+       }
+
+       return NT_STATUS_OK;
+}
+
+static int streams_depot_stat(vfs_handle_struct *handle, const char *fname,
+                             SMB_STRUCT_STAT *sbuf)
+{
+       char *stream_fname;
+       int ret = -1;
+
+       DEBUG(10, ("streams_depot_stat called for [%s]\n", fname));
+
+       if (!is_ntfs_stream_name(fname)) {
+               return SMB_VFS_NEXT_STAT(handle, fname, sbuf);
+       }
+
+       stream_fname = stream_name(handle, fname, false);
+       if (stream_fname == NULL) {
+               goto done;
+       }
+
+       ret = SMB_VFS_NEXT_STAT(handle, stream_fname, sbuf);
+
+ done:
+       TALLOC_FREE(stream_fname);
+       return ret;
+}
+
+static int streams_depot_lstat(vfs_handle_struct *handle, const char *fname,
+                              SMB_STRUCT_STAT *sbuf)
+{
+       char *stream_fname;
+       int ret = -1;
+
+       if (!is_ntfs_stream_name(fname)) {
+               return SMB_VFS_NEXT_LSTAT(handle, fname, sbuf);
+       }
+
+       stream_fname = stream_name(handle, fname, false);
+       if (stream_fname == NULL) {
+               goto done;
+       }
+
+       ret = SMB_VFS_NEXT_LSTAT(handle, stream_fname, sbuf);
+
+ done:
+       TALLOC_FREE(stream_fname);
+       return ret;
+}
+
+static int streams_depot_open(vfs_handle_struct *handle,  const char *fname,
+                             files_struct *fsp, int flags, mode_t mode)
+{
+       TALLOC_CTX *frame;
+       char *base = NULL;
+       SMB_STRUCT_STAT base_sbuf;
+       char *stream_fname;
+       int ret = -1;
+
+       if (!is_ntfs_stream_name(fname)) {
+               return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       }
+
+       frame = talloc_stackframe();
+
+       if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), fname,
+                                                   &base, NULL))) {
+               errno = ENOMEM;
+               goto done;
+       }
+
+       ret = SMB_VFS_NEXT_STAT(handle, base, &base_sbuf);
+
+       if (ret == -1) {
+               goto done;
+       }
+
+       TALLOC_FREE(base);
+
+       stream_fname = stream_name(handle, fname, true);
+       if (stream_fname == NULL) {
+               goto done;
+       }
+
+       ret = SMB_VFS_NEXT_OPEN(handle, stream_fname, fsp, flags, mode);
+
+ done:
+       TALLOC_FREE(frame);
+       return ret;
+}
+
+static int streams_depot_unlink(vfs_handle_struct *handle,  const char *fname)
+{
+       int ret = -1;
+       SMB_STRUCT_STAT sbuf;
+
+       DEBUG(10, ("streams_depot_unlink called for %s\n", fname));
+
+       if (is_ntfs_stream_name(fname)) {
+               char *stream_fname;
+
+               stream_fname = stream_name(handle, fname, false);
+               if (stream_fname == NULL) {
+                       return -1;
+               }
+
+               ret = SMB_VFS_NEXT_UNLINK(handle, stream_fname);
+
+               TALLOC_FREE(stream_fname);
+               return ret;
+       }
+
+       /*
+        * We potentially need to delete the per-inode streams directory
+        */
+
+       if (SMB_VFS_NEXT_STAT(handle, fname, &sbuf) == -1) {
+               return -1;
+       }
+
+       if (sbuf.st_nlink == 1) {
+               char *dirname = stream_dir(handle, fname, &sbuf, false);
+
+               if (dirname != NULL) {
+                       SMB_VFS_NEXT_RMDIR(handle, dirname);
+               }
+               TALLOC_FREE(dirname);
+       }
+
+       return SMB_VFS_NEXT_UNLINK(handle, fname);
+}
+
+static bool add_one_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
+                          struct stream_struct **streams,
+                          const char *name, SMB_OFF_T size,
+                          SMB_OFF_T alloc_size)
+{
+       struct stream_struct *tmp;
+
+       tmp = TALLOC_REALLOC_ARRAY(mem_ctx, *streams, struct stream_struct,
+                                  (*num_streams)+1);
+       if (tmp == NULL) {
+               return false;
+       }
+
+       tmp[*num_streams].name = talloc_strdup(tmp, name);
+       if (tmp[*num_streams].name == NULL) {
+               return false;
+       }
+
+       tmp[*num_streams].size = size;
+       tmp[*num_streams].alloc_size = alloc_size;
+
+       *streams = tmp;
+       *num_streams += 1;
+       return true;
+}
+
+struct streaminfo_state {
+       TALLOC_CTX *mem_ctx;
+       vfs_handle_struct *handle;
+       unsigned int num_streams;
+       struct stream_struct *streams;
+       NTSTATUS status;
+};
+
+static bool collect_one_stream(const char *dirname,
+                              const char *dirent,
+                              void *private_data)
+{
+       struct streaminfo_state *state =
+               (struct streaminfo_state *)private_data;
+       char *full_sname;
+       SMB_STRUCT_STAT sbuf;
+
+       if (asprintf(&full_sname, "%s/%s", dirname, dirent) == -1) {
+               state->status = NT_STATUS_NO_MEMORY;
+               return false;
+       }
+       if (SMB_VFS_NEXT_STAT(state->handle, full_sname, &sbuf) == -1) {
+               DEBUG(10, ("Could not stat %s: %s\n", full_sname,
+                          strerror(errno)));
+               SAFE_FREE(full_sname);
+               return true;
+       }
+
+       SAFE_FREE(full_sname);
+
+       if (!add_one_stream(state->mem_ctx,
+                           &state->num_streams, &state->streams,
+                           dirent, sbuf.st_size,
+                           get_allocation_size(
+                                   state->handle->conn, NULL, &sbuf))) {
+               state->status = NT_STATUS_NO_MEMORY;
+               return false;
+       }
+
+       return true;
+}
+
+static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
+                                        struct files_struct *fsp,
+                                        const char *fname,
+                                        TALLOC_CTX *mem_ctx,
+                                        unsigned int *pnum_streams,
+                                        struct stream_struct **pstreams)
+{
+       SMB_STRUCT_STAT sbuf;
+       int ret;
+       NTSTATUS status;
+       struct streaminfo_state state;
+
+       if ((fsp != NULL) && (fsp->fh->fd != -1)) {
+               if (is_ntfs_stream_name(fsp->fsp_name)) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               ret = SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf);
+       }
+       else {
+               if (is_ntfs_stream_name(fname)) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               ret = SMB_VFS_NEXT_STAT(handle, fname, &sbuf);
+       }
+
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+
+       state.streams = NULL;
+       state.num_streams = 0;
+
+       if (!S_ISDIR(sbuf.st_mode)) {
+               if (!add_one_stream(mem_ctx,
+                                   &state.num_streams, &state.streams,
+                                   "::$DATA", sbuf.st_size,
+                                   get_allocation_size(handle->conn, fsp,
+                                                       &sbuf))) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
+       state.mem_ctx = mem_ctx;
+       state.handle = handle;
+       state.status = NT_STATUS_OK;
+
+       status = walk_streams(handle, fname, &sbuf, NULL, collect_one_stream,
+                             &state);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(state.streams);
+               return status;
+       }
+
+       if (!NT_STATUS_IS_OK(state.status)) {
+               TALLOC_FREE(state.streams);
+               return state.status;
+       }
+
+       *pnum_streams = state.num_streams;
+       *pstreams = state.streams;
+       return NT_STATUS_OK;
+}
+
+static uint32_t streams_depot_fs_capabilities(struct vfs_handle_struct *handle)
+{
+       return SMB_VFS_NEXT_FS_CAPABILITIES(handle) | FILE_NAMED_STREAMS;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple streams_depot_ops[] = {
+       {SMB_VFS_OP(streams_depot_fs_capabilities), SMB_VFS_OP_FS_CAPABILITIES,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_depot_open), SMB_VFS_OP_OPEN,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_depot_stat), SMB_VFS_OP_STAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_depot_lstat), SMB_VFS_OP_LSTAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_depot_unlink), SMB_VFS_OP_UNLINK,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_depot_streaminfo), SMB_VFS_OP_STREAMINFO,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_streams_depot_init(void);
+NTSTATUS vfs_streams_depot_init(void)
+{
+       return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "streams_depot",
+                               streams_depot_ops);
+}
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
new file mode 100644 (file)
index 0000000..766e7d1
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ * Store streams in xattrs
+ *
+ * Copyright (C) Volker Lendecke, 2008
+ *
+ * Partly based on James Peach's Darwin module, which is
+ *
+ * Copyright (C) James Peach 2006-2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+struct stream_io {
+       char *base;
+       char *xattr_name;
+};
+
+static SMB_INO_T stream_inode(const SMB_STRUCT_STAT *sbuf, const char *sname)
+{
+       struct MD5Context ctx;
+        unsigned char hash[16];
+       SMB_INO_T result;
+       char *upper_sname;
+
+       DEBUG(10, ("stream_inode called for %lu/%lu [%s]\n",
+                  (unsigned long)sbuf->st_dev,
+                  (unsigned long)sbuf->st_ino, sname));
+
+       upper_sname = talloc_strdup_upper(talloc_tos(), sname);
+       SMB_ASSERT(upper_sname != NULL);
+
+        MD5Init(&ctx);
+        MD5Update(&ctx, (unsigned char *)&(sbuf->st_dev),
+                 sizeof(sbuf->st_dev));
+        MD5Update(&ctx, (unsigned char *)&(sbuf->st_ino),
+                 sizeof(sbuf->st_ino));
+        MD5Update(&ctx, (unsigned char *)upper_sname,
+                 talloc_get_size(upper_sname)-1);
+        MD5Final(hash, &ctx);
+
+       TALLOC_FREE(upper_sname);
+
+        /* Hopefully all the variation is in the lower 4 (or 8) bytes! */
+       memcpy(&result, hash, sizeof(result));
+
+       DEBUG(10, ("stream_inode returns %lu\n", (unsigned long)result));
+
+       return result;
+}
+
+static ssize_t get_xattr_size(connection_struct *conn, const char *fname,
+                             const char *xattr_name)
+{
+       NTSTATUS status;
+       struct ea_struct ea;
+       ssize_t result;
+
+       status = get_ea_value(talloc_tos(), conn, NULL, fname,
+                             xattr_name, &ea);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return -1;
+       }
+
+       result = ea.value.length-1;
+       TALLOC_FREE(ea.value.data);
+       return result;
+}
+
+
+static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
+                              SMB_STRUCT_STAT *sbuf)
+{
+       struct stream_io *io = (struct stream_io *)
+               VFS_FETCH_FSP_EXTENSION(handle, fsp);
+
+       DEBUG(10, ("streams_xattr_fstat called for %d\n", fsp->fh->fd));
+
+       if (io == NULL) {
+               return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
+       }
+
+       if (SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf) == -1) {
+               return -1;
+       }
+
+       sbuf->st_size = get_xattr_size(handle->conn, io->base, io->xattr_name);
+       if (sbuf->st_size == -1) {
+               return -1;
+       }
+
+       DEBUG(10, ("sbuf->st_size = %d\n", (int)sbuf->st_size));
+
+       sbuf->st_ino = stream_inode(sbuf, io->xattr_name);
+       sbuf->st_mode &= ~S_IFMT;
+        sbuf->st_mode |= S_IFREG;
+        sbuf->st_blocks = sbuf->st_size % STAT_ST_BLOCKSIZE + 1;
+
+       return 0;
+}
+
+static int streams_xattr_stat(vfs_handle_struct *handle, const char *fname,
+                             SMB_STRUCT_STAT *sbuf)
+{
+       NTSTATUS status;
+       char *base = NULL, *sname = NULL;
+       int result = -1;
+       char *xattr_name;
+
+       if (!is_ntfs_stream_name(fname)) {
+               return SMB_VFS_NEXT_STAT(handle, fname, sbuf);
+       }
+
+       status = split_ntfs_stream_name(talloc_tos(), fname, &base, &sname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (SMB_VFS_STAT(handle->conn, base, sbuf) == -1) {
+               goto fail;
+       }
+
+       xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
+                                    SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
+       if (xattr_name == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       sbuf->st_size = get_xattr_size(handle->conn, base, xattr_name);
+       if (sbuf->st_size == -1) {
+               errno = ENOENT;
+               goto fail;
+       }
+
+       sbuf->st_ino = stream_inode(sbuf, xattr_name);
+       sbuf->st_mode &= ~S_IFMT;
+        sbuf->st_mode |= S_IFREG;
+        sbuf->st_blocks = sbuf->st_size % STAT_ST_BLOCKSIZE + 1;
+
+       result = 0;
+ fail:
+       TALLOC_FREE(base);
+       TALLOC_FREE(sname);
+       return result;
+}
+
+static int streams_xattr_lstat(vfs_handle_struct *handle, const char *fname,
+                              SMB_STRUCT_STAT *sbuf)
+{
+       NTSTATUS status;
+       char *base, *sname;
+       int result = -1;
+       char *xattr_name;
+
+       if (!is_ntfs_stream_name(fname)) {
+               return SMB_VFS_NEXT_LSTAT(handle, fname, sbuf);
+       }
+
+       status = split_ntfs_stream_name(talloc_tos(), fname, &base, &sname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = EINVAL;
+               goto fail;
+       }
+
+       if (SMB_VFS_LSTAT(handle->conn, base, sbuf) == -1) {
+               goto fail;
+       }
+
+       xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
+                                    SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
+       if (xattr_name == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       sbuf->st_size = get_xattr_size(handle->conn, base, xattr_name);
+       if (sbuf->st_size == -1) {
+               errno = ENOENT;
+               goto fail;
+       }
+
+       sbuf->st_ino = stream_inode(sbuf, xattr_name);
+       sbuf->st_mode &= ~S_IFMT;
+        sbuf->st_mode |= S_IFREG;
+        sbuf->st_blocks = sbuf->st_size % STAT_ST_BLOCKSIZE + 1;
+
+       result = 0;
+ fail:
+       TALLOC_FREE(base);
+       TALLOC_FREE(sname);
+       return result;
+}
+
+static int streams_xattr_open(vfs_handle_struct *handle,  const char *fname,
+                             files_struct *fsp, int flags, mode_t mode)
+{
+       TALLOC_CTX *frame;
+       NTSTATUS status;
+       struct stream_io *sio;
+       char *base, *sname;
+       struct ea_struct ea;
+       char *xattr_name;
+       int baseflags;
+       int hostfd = -1;
+
+       DEBUG(10, ("streams_xattr_open called for %s\n", fname));
+
+       if (!is_ntfs_stream_name(fname)) {
+               return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
+       }
+
+       frame = talloc_stackframe();
+
+       status = split_ntfs_stream_name(talloc_tos(), fname,
+                                       &base, &sname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = EINVAL;
+               goto fail;
+       }
+
+       xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
+                                    SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
+       if (xattr_name == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       /*
+        * We use baseflags to turn off nasty side-effects when opening the
+        * underlying file.
+         */
+        baseflags = flags;
+        baseflags &= ~O_TRUNC;
+        baseflags &= ~O_EXCL;
+        baseflags &= ~O_CREAT;
+
+        hostfd = SMB_VFS_OPEN(handle->conn, base, fsp, baseflags, mode);
+
+        /* It is legit to open a stream on a directory, but the base
+         * fd has to be read-only.
+         */
+        if ((hostfd == -1) && (errno == EISDIR)) {
+                baseflags &= ~O_ACCMODE;
+                baseflags |= O_RDONLY;
+                hostfd = SMB_VFS_OPEN(handle->conn, fname, fsp, baseflags,
+                                     mode);
+        }
+
+        if (hostfd == -1) {
+               goto fail;
+        }
+
+       status = get_ea_value(talloc_tos(), handle->conn, NULL, base,
+                             xattr_name, &ea);
+
+       DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
+
+       if (!NT_STATUS_IS_OK(status)
+           && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+               /*
+                * The base file is not there. This is an error even if we got
+                * O_CREAT, the higher levels should have created the base
+                * file for us.
+                */
+               DEBUG(10, ("streams_xattr_open: base file %s not around, "
+                          "returning ENOENT\n", base));
+               errno = ENOENT;
+               goto fail;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               /*
+                * The attribute does not exist
+                */
+
+                if (flags & O_CREAT) {
+                       /*
+                        * Darn, xattrs need at least 1 byte
+                        */
+                        char null = '\0';
+
+                       DEBUG(10, ("creating attribute %s on file %s\n",
+                                  xattr_name, base));
+
+                        if (SMB_VFS_SETXATTR(
+                               handle->conn, base, xattr_name,
+                               &null, sizeof(null),
+                               flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
+                               goto fail;
+                       }
+               }
+       }
+
+       if (flags & O_TRUNC) {
+               char null = '\0';
+               if (SMB_VFS_SETXATTR(
+                           handle->conn, base, xattr_name,
+                           &null, sizeof(null),
+                           flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
+                       goto fail;
+               }
+       }
+
+        sio = (struct stream_io *)VFS_ADD_FSP_EXTENSION(handle, fsp,
+                                                       struct stream_io);
+        if (sio == NULL) {
+                errno = ENOMEM;
+                goto fail;
+        }
+
+        sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
+                                       xattr_name);
+        sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
+                                 base);
+
+       if ((sio->xattr_name == NULL) || (sio->base == NULL)) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       TALLOC_FREE(frame);
+       return hostfd;
+
+ fail:
+       if (hostfd >= 0) {
+               /*
+                * BUGBUGBUG -- we would need to call fd_close_posix here, but
+                * we don't have a full fsp yet
+                */
+               SMB_VFS_CLOSE(fsp, hostfd);
+       }
+
+       TALLOC_FREE(frame);
+       return -1;
+}
+
+static int streams_xattr_unlink(vfs_handle_struct *handle,  const char *fname)
+{
+       NTSTATUS status;
+       char *base = NULL;
+       char *sname = NULL;
+       int ret = -1;
+       char *xattr_name;
+
+       if (!is_ntfs_stream_name(fname)) {
+               return SMB_VFS_NEXT_UNLINK(handle, fname);
+       }
+
+       status = split_ntfs_stream_name(talloc_tos(), fname, &base, &sname);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = EINVAL;
+               goto fail;
+       }
+
+       xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
+                                    SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
+       if (xattr_name == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       ret = SMB_VFS_REMOVEXATTR(handle->conn, base, xattr_name);
+
+       if ((ret == -1) && (errno == ENOATTR)) {
+               errno = ENOENT;
+               goto fail;
+       }
+
+       ret = 0;
+
+ fail:
+       TALLOC_FREE(base);
+       TALLOC_FREE(sname);
+       return ret;
+}
+
+static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp,
+                                  const char *fname,
+                                  bool (*fn)(struct ea_struct *ea,
+                                             void *private_data),
+                                  void *private_data)
+{
+       NTSTATUS status;
+       char **names;
+       size_t i, num_names;
+       size_t prefix_len = strlen(SAMBA_XATTR_DOSSTREAM_PREFIX);
+
+       status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
+                                       &names, &num_names);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       for (i=0; i<num_names; i++) {
+               struct ea_struct ea;
+
+               if (strncmp(names[i], SAMBA_XATTR_DOSSTREAM_PREFIX,
+                           prefix_len) != 0) {
+                       continue;
+               }
+
+               status = get_ea_value(names, conn, fsp, fname, names[i], &ea);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("Could not get ea %s for file %s: %s\n",
+                                  names[i], fname, nt_errstr(status)));
+                       continue;
+               }
+
+               ea.name = talloc_asprintf(ea.value.data, ":%s",
+                                         names[i] + prefix_len);
+               if (ea.name == NULL) {
+                       DEBUG(0, ("talloc failed\n"));
+                       continue;
+               }
+
+               if (!fn(&ea, private_data)) {
+                       TALLOC_FREE(ea.value.data);
+                       return NT_STATUS_OK;
+               }
+
+               TALLOC_FREE(ea.value.data);
+       }
+
+       TALLOC_FREE(names);
+       return NT_STATUS_OK;
+}
+
+static bool add_one_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
+                          struct stream_struct **streams,
+                          const char *name, SMB_OFF_T size,
+                          SMB_OFF_T alloc_size)
+{
+       struct stream_struct *tmp;
+
+       tmp = TALLOC_REALLOC_ARRAY(mem_ctx, *streams, struct stream_struct,
+                                  (*num_streams)+1);
+       if (tmp == NULL) {
+               return false;
+       }
+
+       tmp[*num_streams].name = talloc_strdup(tmp, name);
+       if (tmp[*num_streams].name == NULL) {
+               return false;
+       }
+
+       tmp[*num_streams].size = size;
+       tmp[*num_streams].alloc_size = alloc_size;
+
+       *streams = tmp;
+       *num_streams += 1;
+       return true;
+}
+
+struct streaminfo_state {
+       TALLOC_CTX *mem_ctx;
+       vfs_handle_struct *handle;
+       unsigned int num_streams;
+       struct stream_struct *streams;
+       NTSTATUS status;
+};
+
+static bool collect_one_stream(struct ea_struct *ea, void *private_data)
+{
+       struct streaminfo_state *state =
+               (struct streaminfo_state *)private_data;
+
+       if (!add_one_stream(state->mem_ctx,
+                           &state->num_streams, &state->streams,
+                           ea->name, ea->value.length-1,
+                           smb_roundup(state->handle->conn,
+                                       ea->value.length-1))) {
+               state->status = NT_STATUS_NO_MEMORY;
+               return false;
+       }
+
+       return true;
+}
+
+static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle,
+                                        struct files_struct *fsp,
+                                        const char *fname,
+                                        TALLOC_CTX *mem_ctx,
+                                        unsigned int *pnum_streams,
+                                        struct stream_struct **pstreams)
+{
+       SMB_STRUCT_STAT sbuf;
+       int ret;
+       NTSTATUS status;
+       struct streaminfo_state state;
+
+       if ((fsp != NULL) && (fsp->fh->fd != -1)) {
+               if (is_ntfs_stream_name(fsp->fsp_name)) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               ret = SMB_VFS_FSTAT(fsp, &sbuf);
+       }
+       else {
+               if (is_ntfs_stream_name(fname)) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
+       }
+
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+
+       state.streams = NULL;
+       state.num_streams = 0;
+
+       if (!S_ISDIR(sbuf.st_mode)) {
+               if (!add_one_stream(mem_ctx,
+                                   &state.num_streams, &state.streams,
+                                   "::$DATA", sbuf.st_size,
+                                   get_allocation_size(handle->conn, fsp,
+                                                       &sbuf))) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
+       state.mem_ctx = mem_ctx;
+       state.handle = handle;
+       state.status = NT_STATUS_OK;
+
+       status = walk_xattr_streams(handle->conn, fsp, fname,
+                                   collect_one_stream, &state);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(state.streams);
+               return status;
+       }
+
+       if (!NT_STATUS_IS_OK(state.status)) {
+               TALLOC_FREE(state.streams);
+               return state.status;
+       }
+
+       *pnum_streams = state.num_streams;
+       *pstreams = state.streams;
+       return NT_STATUS_OK;
+}
+
+static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle)
+{
+       return SMB_VFS_NEXT_FS_CAPABILITIES(handle) | FILE_NAMED_STREAMS;
+}
+
+static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
+                                   files_struct *fsp, const void *data,
+                                   size_t n, SMB_OFF_T offset)
+{
+        struct stream_io *sio =
+               (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+       struct ea_struct ea;
+       NTSTATUS status;
+       int ret;
+
+       DEBUG(10, ("streams_xattr_pwrite called for %d bytes\n", (int)n));
+
+       if (sio == NULL) {
+               return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
+       }
+
+       status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
+                             sio->base, sio->xattr_name, &ea);
+       if (!NT_STATUS_IS_OK(status)) {
+               return -1;
+       }
+
+        if ((offset + n) > ea.value.length-1) {
+               uint8 *tmp;
+
+               tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), ea.value.data, uint8,
+                                          offset + n + 1);
+
+               if (tmp == NULL) {
+                       TALLOC_FREE(ea.value.data);
+                        errno = ENOMEM;
+                        return -1;
+                }
+               ea.value.data = tmp;
+               ea.value.length = offset + n + 1;
+               ea.value.data[offset+n] = 0;
+        }
+
+        memcpy(ea.value.data + offset, data, n);
+
+       ret = SMB_VFS_SETXATTR(fsp->conn, fsp->base_fsp->fsp_name,
+                               sio->xattr_name,
+                               ea.value.data, ea.value.length, 0);
+
+       TALLOC_FREE(ea.value.data);
+
+       if (ret == -1) {
+               return -1;
+       }
+
+       return n;
+}
+
+static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
+                                  files_struct *fsp, void *data,
+                                  size_t n, SMB_OFF_T offset)
+{
+        struct stream_io *sio =
+               (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+       struct ea_struct ea;
+       NTSTATUS status;
+        size_t length, overlap;
+
+       if (sio == NULL) {
+               return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
+       }
+
+       status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
+                             sio->base, sio->xattr_name, &ea);
+       if (!NT_STATUS_IS_OK(status)) {
+               return -1;
+       }
+
+       length = ea.value.length-1;
+
+        /* Attempt to read past EOF. */
+        if (length <= offset) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        overlap = (offset + n) > length ? (length - offset) : n;
+        memcpy(data, ea.value.data + offset, overlap);
+
+       TALLOC_FREE(ea.value.data);
+        return overlap;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple streams_xattr_ops[] = {
+       {SMB_VFS_OP(streams_xattr_fs_capabilities), SMB_VFS_OP_FS_CAPABILITIES,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_open), SMB_VFS_OP_OPEN,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_stat), SMB_VFS_OP_STAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_fstat), SMB_VFS_OP_FSTAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_lstat), SMB_VFS_OP_LSTAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_pread), SMB_VFS_OP_PREAD,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_pwrite), SMB_VFS_OP_PWRITE,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_lstat), SMB_VFS_OP_LSTAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_unlink), SMB_VFS_OP_UNLINK,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(streams_xattr_streaminfo), SMB_VFS_OP_STREAMINFO,
+        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_streams_xattr_init(void);
+NTSTATUS vfs_streams_xattr_init(void)
+{
+       return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "streams_xattr",
+                               streams_xattr_ops);
+}
index 29864a8f94303ad73b402ab7d8caecc2e5a69f24..208066bedca39029c1b443775b41c85e07363bcd 100644 (file)
@@ -110,7 +110,7 @@ static NTSTATUS xattr_tdb_load_attrs(TALLOC_CTX *mem_ctx,
 
        status = xattr_tdb_pull_attrs(mem_ctx, &data, presult);
        TALLOC_FREE(data.dptr);
-       return NT_STATUS_OK;
+       return status;
 }
 
 /*
@@ -165,6 +165,9 @@ static ssize_t xattr_tdb_getattr(struct db_context *db_ctx,
        ssize_t result = -1;
        NTSTATUS status;
 
+       DEBUG(10, ("xattr_tdb_getattr called for file %s, name %s\n",
+                  file_id_string_tos(id), name));
+
        status = xattr_tdb_load_attrs(talloc_tos(), db_ctx, id, &attribs);
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -250,6 +253,9 @@ static int xattr_tdb_setattr(struct db_context *db_ctx,
        struct tdb_xattrs *attribs;
        uint32_t i;
 
+       DEBUG(10, ("xattr_tdb_setattr called for file %s, name %s\n",
+                  file_id_string_tos(id), name));
+
        rec = xattr_tdb_lock_attrs(talloc_tos(), db_ctx, id);
 
        if (rec == NULL) {
@@ -269,6 +275,11 @@ static int xattr_tdb_setattr(struct db_context *db_ctx,
 
        for (i=0; i<attribs->num_xattrs; i++) {
                if (strcmp(attribs->xattrs[i].name, name) == 0) {
+                       if (flags & XATTR_CREATE) {
+                               TALLOC_FREE(rec);
+                               errno = EEXIST;
+                               return -1;
+                       }
                        break;
                }
        }
@@ -276,6 +287,12 @@ static int xattr_tdb_setattr(struct db_context *db_ctx,
        if (i == attribs->num_xattrs) {
                struct tdb_xattr *tmp;
 
+               if (flags & XATTR_REPLACE) {
+                       TALLOC_FREE(rec);
+                       errno = ENOATTR;
+                       return -1;
+               }
+
                tmp = TALLOC_REALLOC_ARRAY(
                        attribs, attribs->xattrs, struct tdb_xattr,
                        attribs->num_xattrs + 1);
@@ -558,7 +575,8 @@ static bool xattr_tdb_init(int snum, struct db_context **p_db)
        struct db_context *db;
        const char *dbname;
 
-       dbname = lp_parm_const_string(snum, "ea", "tdb", lock_path("eas.tdb"));
+       dbname = lp_parm_const_string(snum, "xattr", "tdb",
+                                     lock_path("xattr.tdb"));
 
        if (dbname == NULL) {
                errno = ENOTSUP;
@@ -660,7 +678,7 @@ static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path)
  * Destructor for the VFS private data
  */
 
-static void close_ea_db(void **data)
+static void close_xattr_db(void **data)
 {
        struct db_context **p_db = (struct db_context **)data;
        TALLOC_FREE(*p_db);
@@ -688,14 +706,14 @@ static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service,
        }
 
        if (!xattr_tdb_init(snum, &db)) {
-               DEBUG(5, ("Could not init ea tdb\n"));
+               DEBUG(5, ("Could not init xattr tdb\n"));
                lp_do_parameter(snum, "ea support", "False");
                return 0;
        }
 
        lp_do_parameter(snum, "ea support", "True");
 
-       SMB_VFS_HANDLE_SET_DATA(handle, db, close_ea_db,
+       SMB_VFS_HANDLE_SET_DATA(handle, db, close_xattr_db,
                                struct db_context, return -1);
 
        return 0;
index 0ff0afd12d7337992223f46aeb457c239e92e842..10833e80890305c00402e6487a54a28b7751929d 100644 (file)
@@ -399,6 +399,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
                                        char *component, *dc, *q1;
                                        char *q_orig = q;
                                        int str_offset;
+                                       char *saveptr;
 
                                        domain = get_mydnsdomname(talloc_tos());
                                        if (!domain) {
@@ -444,7 +445,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
                                        str_offset = q - q_orig;
                                        dc = domain;
                                        q1 = q;
-                                       while ((component = strtok(dc, "."))) {
+                                       while ((component = strtok_r(dc, ".", &saveptr)) != NULL) {
                                                dc = NULL;
                                                if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) {
                                                        return;
index 321a7db669431217565abc2d212657bbf9c7f46b..42a994352382dece099f6707b391dea2f29ed374 100644 (file)
@@ -72,10 +72,10 @@ wbcErr wbcRequestResponse(int cmd,
                wbc_status = WBC_ERR_SUCCESS;
                break;
        case NSS_STATUS_UNAVAIL:
-               return WBC_ERR_WINBIND_NOT_AVAILABLE;
+               wbc_status = WBC_ERR_WINBIND_NOT_AVAILABLE;
                break;
        case NSS_STATUS_NOTFOUND:
-               return WBC_ERR_DOMAIN_NOT_FOUND;
+               wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
                break;
        default:
                wbc_status = WBC_ERR_NSS_ERROR;
index 0d3fbbf77c64f9604368e60629ddb3cf50bee0ad..c1d26af98977690fdfd483a81cd69747191d0652 100644 (file)
@@ -4709,6 +4709,7 @@ static void lp_add_auto_services(char *str)
        char *s;
        char *p;
        int homes;
+       char *saveptr;
 
        if (!str)
                return;
@@ -4719,7 +4720,8 @@ static void lp_add_auto_services(char *str)
 
        homes = lp_servicenumber(HOMES_NAME);
 
-       for (p = strtok(s, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
+       for (p = strtok_r(s, LIST_SEP, &saveptr); p;
+            p = strtok_r(NULL, LIST_SEP, &saveptr)) {
                char *home;
 
                if (lp_servicenumber(p) >= 0)
@@ -5725,6 +5727,7 @@ bool lp_load(const char *pszFname,
                         */
                        config_backend = CONFIG_BACKEND_REGISTRY;
                        /* start over */
+                       init_globals(false);
                        return lp_load(pszFname, global_only, save_defaults,
                                       add_ipc, initialize_globals);
                }
index f8aba3996d47ec00de09f7d02d10a298994775ac..23144d5a9550dc9e6ba2bea5eaf94d6bccaf4427 100644 (file)
@@ -28,6 +28,7 @@ static void add_auto_printers(void)
        const char *p;
        int pnum = lp_servicenumber(PRINTERS_NAME);
        char *str;
+       char *saveptr;
 
        if (pnum < 0)
                return;
@@ -35,7 +36,8 @@ static void add_auto_printers(void)
        if ((str = SMB_STRDUP(lp_auto_services())) == NULL)
                return;
 
-       for (p = strtok(str, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
+       for (p = strtok_r(str, LIST_SEP, &saveptr); p;
+            p = strtok_r(NULL, LIST_SEP, &saveptr)) {
                if (lp_servicenumber(p) >= 0)
                        continue;
                
index 6dcddb6f1b6e5dcb02c134d874755e09f06c7440..afa3b4850a584e392f9560c34a80eb7ba4e223c2 100644 (file)
@@ -127,6 +127,7 @@ static bool parse_lpq_bsd(char *line,print_queue_struct *buf,bool first)
        int  count = 0;
        TALLOC_CTX *ctx = talloc_tos();
        char *line2 = NULL;
+       char *saveptr;
 
        line2 = talloc_strdup(ctx, line);
        if (!line2) {
@@ -144,10 +145,11 @@ static bool parse_lpq_bsd(char *line,print_queue_struct *buf,bool first)
 #endif /* OSF1 */
 
        /* FIXME: Use next_token_talloc rather than strtok! */
-       tok[0] = strtok(line2," \t");
+       tok[0] = strtok_r(line2," \t", &saveptr);
        count++;
 
-       while ((count < MAXTOK) && ((tok[count] = strtok(NULL," \t")) != NULL)) {
+       while ((count < MAXTOK)
+              && ((tok[count] = strtok_r(NULL, " \t", &saveptr)) != NULL)) {
                count++;
        }
 
index fd85ca08336ba8e7f04a2172a7ec0b073e8dc462..57590cc39efd7a71bd281086f86431f2a5b2ab5d 100644 (file)
@@ -59,8 +59,9 @@ bool aix_cache_reload(void)
                                continue;
 
                        if ((p = strchr_m(line, ':'))) {
+                               char *saveptr;
                                *p = '\0';
-                               p = strtok(line, ":");
+                               p = strtok_r(line, ":", &saveptr);
                                if (strcmp(p, "bsh") != 0) {
                                        name = talloc_strdup(ctx, p);
                                        if (!name) {
index 788af28d5dd62bcdf33e58f3900b0e0d9c40a362..9c4009368d3b4f6f7e5fc1d07021dc5da443d23f 100644 (file)
@@ -453,7 +453,6 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
        TALLOC_CTX *mem_ctx;
        char *path, *end;
        WERROR err;
-       REGSUBKEY_CTR *subkeys;
 
        if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
 
@@ -517,11 +516,6 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
         * Actually create the subkey
         */
 
-       if (!(subkeys = TALLOC_ZERO_P(mem_ctx, REGSUBKEY_CTR))) {
-               err = WERR_NOMEM;
-               goto done;
-       }
-
        err = fill_subkey_cache(create_parent);
        if (!W_ERROR_IS_OK(err)) goto done;
 
diff --git a/source3/registry/reg_backend_current_version.c b/source3/registry/reg_backend_current_version.c
new file mode 100644 (file)
index 0000000..a9d281c
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Virtual Windows Registry Layer
+ *  Copyright (C) Gerald Carter     2002-2005
+ *  Copyright (C) Michael Adam      2008
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * CurrentVersion registry backend.
+ *
+ * This is a virtual overlay, dynamically presenting version information.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+extern REGISTRY_OPS regdb_ops;
+
+#define KEY_CURRENT_VERSION_NORM "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION"
+
+static int current_version_fetch_values(const char *key, REGVAL_CTR *values)
+{
+       const char *sysroot_string = "c:\\Windows";
+       fstring sysversion;
+       fstring value;
+       uint32 value_length;
+       char *path = NULL;
+       TALLOC_CTX *ctx = talloc_tos();
+
+       path = talloc_strdup(ctx, key);
+       if (path == NULL) {
+               return -1;
+       }
+       path = normalize_reg_path(ctx, path);
+       if (path == NULL) {
+               return -1;
+       }
+
+       if (strncmp(path, KEY_CURRENT_VERSION_NORM, strlen(path)) != 0) {
+               return 0;
+       }
+
+       value_length = push_ucs2(value, value, sysroot_string, sizeof(value),
+                                STR_TERMINATE|STR_NOALIGN );
+       regval_ctr_addvalue(values, "SystemRoot", REG_SZ, value, value_length);
+
+       fstr_sprintf(sysversion, "%d.%d", lp_major_announce_version(),
+                    lp_minor_announce_version());
+       value_length = push_ucs2(value, value, sysversion, sizeof(value),
+                                STR_TERMINATE|STR_NOALIGN);
+       regval_ctr_addvalue(values, "CurrentVersion", REG_SZ, value,
+                           value_length);
+
+       return regval_ctr_numvals(values);
+}
+
+static int current_version_fetch_subkeys(const char *key,
+                                        REGSUBKEY_CTR *subkey_ctr)
+{
+       return regdb_ops.fetch_subkeys(key, subkey_ctr);
+}
+
+REGISTRY_OPS current_version_reg_ops = {
+       .fetch_values = current_version_fetch_values,
+       .fetch_subkeys = current_version_fetch_subkeys,
+};
similarity index 98%
rename from source3/registry/reg_db.c
rename to source3/registry/reg_backend_db.c
index c4bfc2b6c9c9c7c51b19ba629cab3f199d67a436..e162fb587f573f15b26d785c6f3a1bc82694c56e 100644 (file)
@@ -44,17 +44,17 @@ static const char *builtin_registry_paths[] = {
        KEY_SHARES,
        KEY_EVENTLOG,
        KEY_SMBCONF,
-       "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib",
-       "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009",
+       KEY_PERFLIB,
+       KEY_PERFLIB_009,
        "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors",
-       "HKLM\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
+       KEY_PROD_OPTIONS,
        "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\DefaultUserConfiguration",
-       "HKLM\\SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Parameters",
-       "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Netlogon\\Parameters",
-       "HKU",
-       "HKCR",
-       "HKPD",
-       "HKPT",
+       KEY_TCPIP_PARAMS,
+       KEY_NETLOGON_PARAMS,
+       KEY_HKU,
+       KEY_HKCR,
+       KEY_HKPD,
+       KEY_HKPT,
         NULL };
 
 struct builtin_regkey_value {
diff --git a/source3/registry/reg_backend_hkpt_params.c b/source3/registry/reg_backend_hkpt_params.c
new file mode 100644 (file)
index 0000000..2ed5e78
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Virtual Windows Registry Layer
+ *  Copyright (C) Gerald Carter     2002-2005
+ *  Copyright (C) Michael Adam      2008
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * HKPT parameters registry backend.
+ *
+ * This replaces the former dynamic hkpt parameters overlay.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+extern REGISTRY_OPS regdb_ops;
+
+static int hkpt_params_fetch_values(const char *key, REGVAL_CTR *regvals)
+{
+       uint32 base_index;
+       uint32 buffer_size;
+       char *buffer = NULL;
+
+       /* This is ALMOST the same as perflib_009_params, but HKPT has
+          a "Counters" entry instead of a "Counter" key. <Grrrr> */
+
+       base_index = reg_perfcount_get_base_index();
+       buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
+       regval_ctr_addvalue(regvals, "Counters", REG_MULTI_SZ, buffer,
+                           buffer_size);
+
+       if(buffer_size > 0) {
+               SAFE_FREE(buffer);
+       }
+
+       buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
+       regval_ctr_addvalue(regvals, "Help", REG_MULTI_SZ, buffer, buffer_size);
+       if(buffer_size > 0) {
+               SAFE_FREE(buffer);
+       }
+
+       return regval_ctr_numvals( regvals );
+}
+
+static int hkpt_params_fetch_subkeys(const char *key,
+                                        REGSUBKEY_CTR *subkey_ctr)
+{
+       return regdb_ops.fetch_subkeys(key, subkey_ctr);
+}
+
+REGISTRY_OPS hkpt_params_reg_ops = {
+       .fetch_values = hkpt_params_fetch_values,
+       .fetch_subkeys = hkpt_params_fetch_subkeys,
+};
index 507d2c5df8d3447983572d2112a004b63a56f0b7..71f88144c831ae7c04da833e574f63f1496a0fb4 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_REGISTRY
 
+extern REGISTRY_OPS regdb_ops;
 
-static int netlogon_params_fetch_reg_values(const char *key,
-                                           REGVAL_CTR *regvals)
+static int netlogon_params_fetch_values(const char *key, REGVAL_CTR *regvals)
 {
        uint32 dwValue;
-       
-       if ( !pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue) )
+
+       if (!pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue)) {
                dwValue = 0;
-               
-       regval_ctr_addvalue( regvals, "RefusePasswordChange", REG_DWORD,
-               (char*)&dwValue, sizeof(dwValue) );
+       }
+
+       regval_ctr_addvalue(regvals, "RefusePasswordChange", REG_DWORD,
+                           (char*)&dwValue, sizeof(dwValue));
 
-       return regval_ctr_numvals( regvals );
+       return regval_ctr_numvals(regvals);
 }
 
+static int netlogon_params_fetch_subkeys(const char *key,
+                                        REGSUBKEY_CTR *subkey_ctr)
+{
+       return regdb_ops.fetch_subkeys(key, subkey_ctr);
+}
 
 REGISTRY_OPS netlogon_params_reg_ops = {
-       .fetch_values = netlogon_params_fetch_reg_values,
+       .fetch_values = netlogon_params_fetch_values,
+       .fetch_subkeys = netlogon_params_fetch_subkeys,
 };
diff --git a/source3/registry/reg_backend_perflib.c b/source3/registry/reg_backend_perflib.c
new file mode 100644 (file)
index 0000000..999bca2
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Virtual Windows Registry Layer
+ *  Copyright (C) Gerald Carter     2002-2005
+ *  Copyright (C) Michael Adam      2008
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * perflib registry backend.
+ *
+ * This is a virtual overlay, dynamically presenting perflib values.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+extern REGISTRY_OPS regdb_ops;
+
+#define KEY_PERFLIB_NORM       "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PERFLIB"
+#define KEY_PERFLIB_009_NORM   "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PERFLIB/009"
+
+static int perflib_params( REGVAL_CTR *regvals )
+{
+       int base_index = -1;
+       int last_counter = -1;
+       int last_help = -1;
+       int version = 0x00010001;
+       
+       base_index = reg_perfcount_get_base_index();
+       regval_ctr_addvalue(regvals, "Base Index", REG_DWORD, (char *)&base_index, sizeof(base_index));
+       last_counter = reg_perfcount_get_last_counter(base_index);
+       regval_ctr_addvalue(regvals, "Last Counter", REG_DWORD, (char *)&last_counter, sizeof(last_counter));
+       last_help = reg_perfcount_get_last_help(last_counter);
+       regval_ctr_addvalue(regvals, "Last Help", REG_DWORD, (char *)&last_help, sizeof(last_help));
+       regval_ctr_addvalue(regvals, "Version", REG_DWORD, (char *)&version, sizeof(version));
+
+       return regval_ctr_numvals( regvals );
+}
+
+static int perflib_009_params( REGVAL_CTR *regvals )
+{
+       int base_index;
+       int buffer_size;
+       char *buffer = NULL;
+
+       base_index = reg_perfcount_get_base_index();
+       buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
+       regval_ctr_addvalue(regvals, "Counter", REG_MULTI_SZ, buffer, buffer_size);
+       if(buffer_size > 0)
+               SAFE_FREE(buffer);
+       buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
+       regval_ctr_addvalue(regvals, "Help", REG_MULTI_SZ, buffer, buffer_size);
+       if(buffer_size > 0)
+               SAFE_FREE(buffer);
+       
+       return regval_ctr_numvals( regvals );
+}
+
+static int perflib_fetch_values(const char *key, REGVAL_CTR *regvals)
+{
+       char *path = NULL;
+       TALLOC_CTX *ctx = talloc_tos();
+
+       path = talloc_strdup(ctx, key);
+       if (path == NULL) {
+               return -1;
+       }
+       path = normalize_reg_path(ctx, path);
+       if (path == NULL) {
+               return -1;
+       }
+
+       if (strncmp(path, KEY_PERFLIB_NORM, strlen(path)) == 0) {
+               return perflib_params(regvals);
+       } else if (strncmp(path, KEY_PERFLIB_009_NORM, strlen(path)) == 0) {
+               return perflib_009_params(regvals);
+       } else {
+               return 0;
+       }
+}
+
+static int perflib_fetch_subkeys(const char *key,
+                                        REGSUBKEY_CTR *subkey_ctr)
+{
+       return regdb_ops.fetch_subkeys(key, subkey_ctr);
+}
+
+REGISTRY_OPS perflib_reg_ops = {
+       .fetch_values = perflib_fetch_values,
+       .fetch_subkeys = perflib_fetch_subkeys,
+};
similarity index 99%
rename from source3/registry/reg_printing.c
rename to source3/registry/reg_backend_printing.c
index 5be07960024f83f6c7e046272ee9cbfe86b3a135..a4da103d404952606dc01caf11e251fa26d8121f 100644 (file)
@@ -1262,9 +1262,8 @@ static bool regprint_store_reg_values( const char *key, REGVAL_CTR *values )
  */
 
 REGISTRY_OPS printing_ops = {
-       regprint_fetch_reg_keys,
-       regprint_fetch_reg_values,
-       regprint_store_reg_keys,
-       regprint_store_reg_values,
-       NULL, NULL, NULL, NULL, NULL
+       .fetch_subkeys = regprint_fetch_reg_keys,
+       .fetch_values = regprint_fetch_reg_values,
+       .store_subkeys = regprint_store_reg_keys,
+       .store_values = regprint_store_reg_values,
 };
diff --git a/source3/registry/reg_backend_prod_options.c b/source3/registry/reg_backend_prod_options.c
new file mode 100644 (file)
index 0000000..7ac5c5b
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Virtual Windows Registry Layer
+ *  Copyright (C) Gerald Carter     2002-2005
+ *  Copyright (C) Michael Adam      2008
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Product options registry backend.
+ *
+ * This replaces the former dynamic product options overlay.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+extern REGISTRY_OPS regdb_ops;
+
+static int prod_options_fetch_values(const char *key, REGVAL_CTR *regvals)
+{
+       const char *value_ascii = "";
+       fstring value;
+       int value_length;
+
+       switch (lp_server_role()) {
+               case ROLE_DOMAIN_PDC:
+               case ROLE_DOMAIN_BDC:
+                       value_ascii = "LanmanNT";
+                       break;
+               case ROLE_STANDALONE:
+                       value_ascii = "ServerNT";
+                       break;
+               case ROLE_DOMAIN_MEMBER:
+                       value_ascii = "WinNT";
+                       break;
+       }
+
+       value_length = push_ucs2(value, value, value_ascii, sizeof(value),
+                                STR_TERMINATE|STR_NOALIGN );
+       regval_ctr_addvalue(regvals, "ProductType", REG_SZ, value,
+                           value_length);
+
+       return regval_ctr_numvals( regvals );
+}
+
+static int prod_options_fetch_subkeys(const char *key,
+                                     REGSUBKEY_CTR *subkey_ctr)
+{
+       return regdb_ops.fetch_subkeys(key, subkey_ctr);
+}
+
+REGISTRY_OPS prod_options_reg_ops = {
+       .fetch_values = prod_options_fetch_values,
+       .fetch_subkeys = prod_options_fetch_subkeys,
+};
similarity index 96%
rename from source3/registry/reg_shares.c
rename to source3/registry/reg_backend_shares.c
index 4ac6e1d1514bef7bb7126174cc8a4ab4c351825f..ee9e5dc5a1848e675e34c1bcc85795567f3ad3d7 100644 (file)
@@ -155,11 +155,10 @@ static bool shares_store_value( const char *key, REGVAL_CTR *val )
  */
  
 REGISTRY_OPS shares_reg_ops = {
-       shares_subkey_info,
-       shares_value_info,
-       shares_store_subkey,
-       shares_store_value,
-       NULL, NULL, NULL, NULL, NULL
+       .fetch_subkeys = shares_subkey_info,
+       .fetch_values = shares_value_info,
+       .store_subkeys = shares_store_subkey,
+       .store_values = shares_store_value,
 };
 
 
similarity index 96%
rename from source3/registry/reg_smbconf.c
rename to source3/registry/reg_backend_smbconf.c
index 8dfb745a7e7f9c2c927f49e2df6ee662f6a7861f..a6e478200f1afcd39d108fa3712f15a1beb77ebf 100644 (file)
@@ -265,13 +265,11 @@ static WERROR smbconf_set_secdesc(const char *key,
  */
 
 REGISTRY_OPS smbconf_reg_ops = {
-       smbconf_fetch_keys,
-       smbconf_fetch_values,
-       smbconf_store_keys,
-       smbconf_store_values,
-       smbconf_reg_access_check,
-       smbconf_get_secdesc,
-       smbconf_set_secdesc,
-       NULL,
-       NULL
+       .fetch_subkeys = smbconf_fetch_keys,
+       .fetch_values = smbconf_fetch_values,
+       .store_subkeys = smbconf_store_keys,
+       .store_values = smbconf_store_values,
+       .reg_access_check = smbconf_reg_access_check,
+       .get_secdesc = smbconf_get_secdesc,
+       .set_secdesc = smbconf_set_secdesc,
 };
diff --git a/source3/registry/reg_backend_tcpip_params.c b/source3/registry/reg_backend_tcpip_params.c
new file mode 100644 (file)
index 0000000..db7df5d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Virtual Windows Registry Layer
+ *  Copyright (C) Gerald Carter     2002-2005
+ *  Copyright (C) Michael Adam      2008
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * TCP/IP parameters registry backend.
+ *
+ * This replaces the former dynamic tcpip parameters overlay.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+extern REGISTRY_OPS regdb_ops;
+
+static int tcpip_params_fetch_values(const char *key, REGVAL_CTR *regvals)
+{
+       fstring value;
+       int value_length;
+       char *hname;
+       char *mydomainname = NULL;
+
+       hname = myhostname();
+       value_length = push_ucs2(value, value, hname, sizeof(value),
+                                STR_TERMINATE|STR_NOALIGN);
+       regval_ctr_addvalue(regvals, "Hostname",REG_SZ, value, value_length);
+
+       mydomainname = get_mydnsdomname(talloc_tos());
+       if (!mydomainname) {
+               return -1;
+       }
+
+       value_length = push_ucs2(value, value, mydomainname, sizeof(value),
+                                STR_TERMINATE|STR_NOALIGN);
+       regval_ctr_addvalue(regvals, "Domain", REG_SZ, value, value_length);
+
+       return regval_ctr_numvals(regvals);
+}
+
+static int tcpip_params_fetch_subkeys(const char *key,
+                                        REGSUBKEY_CTR *subkey_ctr)
+{
+       return regdb_ops.fetch_subkeys(key, subkey_ctr);
+}
+
+REGISTRY_OPS tcpip_params_reg_ops = {
+       .fetch_values = tcpip_params_fetch_values,
+       .fetch_subkeys = tcpip_params_fetch_subkeys,
+};
index 74670aac30ec211c9b50bd1646cf3cdcc3fa2725..f9851c781012b92c3ede67272da398ba370727d1 100644 (file)
@@ -37,6 +37,11 @@ bool reghook_cache_init( void )
 {
        if (cache_tree == NULL) {
                cache_tree = pathtree_init(&default_hook, NULL);
+               if (cache_tree !=0) {
+                       DEBUG(10, ("reghook_cache_init: new tree with default "
+                                  "ops %p for key [%s]\n", (void *)&regdb_ops,
+                                  KEY_TREE_ROOT));
+               }
        }
 
        return (cache_tree != NULL);
@@ -56,7 +61,7 @@ bool reghook_cache_add( REGISTRY_HOOK *hook )
                return false;
        }
 
-       key = talloc_asprintf(ctx, "//%s", hook->keyname);
+       key = talloc_asprintf(ctx, "\\%s", hook->keyname);
        if (!key) {
                return false;
        }
@@ -65,7 +70,8 @@ bool reghook_cache_add( REGISTRY_HOOK *hook )
                return false;
        }
 
-       DEBUG(10,("reghook_cache_add: Adding key [%s]\n", key));
+       DEBUG(10, ("reghook_cache_add: Adding ops %p for key [%s]\n",
+                  (void *)hook->ops, key));
 
        return pathtree_add( cache_tree, key, hook );
 }
@@ -102,6 +108,9 @@ REGISTRY_HOOK* reghook_cache_find( const char *keyname )
        DEBUG(10,("reghook_cache_find: Searching for keyname [%s]\n", key));
        
        hook = (REGISTRY_HOOK *)pathtree_find( cache_tree, key ) ;
+
+       DEBUG(10, ("reghook_cache_find: found ops %p for key [%s]\n",
+                  hook ? (void *)hook->ops : 0, key));
        
        SAFE_FREE( key );
        
similarity index 96%
rename from source3/registry/reg_frontend_hilvl.c
rename to source3/registry/reg_dispatcher.c
index cd02eeef74f25e892f4df8f20fc611b9202ac85d..e6e76134570512f1efaa812bbe8de8ff6fb6b0a7 100644 (file)
@@ -87,9 +87,6 @@ bool store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
 
 bool store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
 {
-       if ( check_dynamic_reg_values( key ) )
-               return false;
-
        if ( key->hook && key->hook->ops && key->hook->ops->store_values )
                return key->hook->ops->store_values( key->name, val );
 
@@ -119,17 +116,12 @@ int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
 {
        int result = -1;
 
+       DEBUG(10, ("fetch_reg_values called for key '%s' (ops %p)\n", key->name,
+                  (key->hook && key->hook->ops) ? (void *)key->hook->ops : NULL));
+
        if ( key->hook && key->hook->ops && key->hook->ops->fetch_values )
                result = key->hook->ops->fetch_values( key->name, val );
 
-       /* if the backend lookup returned no data, try the dynamic overlay */
-
-       if ( result == 0 ) {
-               result = fetch_dynamic_reg_values( key, val );
-
-               return ( result != -1 ) ? result : 0;
-       }
-
        return result;
 }
 
diff --git a/source3/registry/reg_dynamic.c b/source3/registry/reg_dynamic.c
deleted file mode 100644 (file)
index 07c9673..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/* 
- *  Unix SMB/CIFS implementation.
- *  Virtual Windows Registry Layer
- *  Copyright (C) Gerald Carter                     2002-2005
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *  
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *  
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Implementation of registry frontend view functions. */
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_REGISTRY
-
-struct reg_dyn_values {
-       const char *path;
-       int (*fetch_values) ( REGVAL_CTR *val );
-};
-
-#if 0
-/***********************************************************************
-***********************************************************************/
-
-static int netlogon_params( REGVAL_CTR *regvals )
-{
-       uint32 dwValue;
-       
-       if ( !pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue) )
-               dwValue = 0;
-               
-       regval_ctr_addvalue( regvals, "RefusePasswordChange", REG_DWORD,
-               (char*)&dwValue, sizeof(dwValue) );
-
-       return regval_ctr_numvals( regvals );
-}
-#endif
-
-/***********************************************************************
-***********************************************************************/
-
-static int prod_options( REGVAL_CTR *regvals )
-{
-       const char              *value_ascii = "";
-       fstring                 value;
-       int                     value_length;
-       
-       switch (lp_server_role()) {
-               case ROLE_DOMAIN_PDC:
-               case ROLE_DOMAIN_BDC:
-                       value_ascii = "LanmanNT";
-                       break;
-               case ROLE_STANDALONE:
-                       value_ascii = "ServerNT";
-                       break;
-               case ROLE_DOMAIN_MEMBER:
-                       value_ascii = "WinNT";
-                       break;
-       }
-               
-       value_length = push_ucs2( value, value, value_ascii, sizeof(value), 
-               STR_TERMINATE|STR_NOALIGN );
-       regval_ctr_addvalue( regvals, "ProductType", REG_SZ, value, 
-               value_length );
-       
-       return regval_ctr_numvals( regvals );
-}
-
-/***********************************************************************
-***********************************************************************/
-
-static int tcpip_params( REGVAL_CTR *regvals )
-{
-       fstring                 value;
-       int                     value_length;
-       char                    *hname;
-       char *mydomainname = NULL;
-
-       hname = myhostname();
-       value_length = push_ucs2( value, value, hname, sizeof(value), STR_TERMINATE|STR_NOALIGN);               
-       regval_ctr_addvalue( regvals, "Hostname",REG_SZ, value, value_length );
-
-       mydomainname = get_mydnsdomname(talloc_tos());
-       if (!mydomainname) {
-               return -1;
-       }
-
-       value_length = push_ucs2( value, value, mydomainname, sizeof(value), STR_TERMINATE|STR_NOALIGN);                
-       regval_ctr_addvalue( regvals, "Domain", REG_SZ, value, value_length );
-
-       return regval_ctr_numvals( regvals );
-}
-
-/***********************************************************************
-***********************************************************************/
-
-static int perflib_params( REGVAL_CTR *regvals )
-{
-       int base_index = -1;
-       int last_counter = -1;
-       int last_help = -1;
-       int version = 0x00010001;
-       
-       base_index = reg_perfcount_get_base_index();
-       regval_ctr_addvalue(regvals, "Base Index", REG_DWORD, (char *)&base_index, sizeof(base_index));
-       last_counter = reg_perfcount_get_last_counter(base_index);
-       regval_ctr_addvalue(regvals, "Last Counter", REG_DWORD, (char *)&last_counter, sizeof(last_counter));
-       last_help = reg_perfcount_get_last_help(last_counter);
-       regval_ctr_addvalue(regvals, "Last Help", REG_DWORD, (char *)&last_help, sizeof(last_help));
-       regval_ctr_addvalue(regvals, "Version", REG_DWORD, (char *)&version, sizeof(version));
-
-       return regval_ctr_numvals( regvals );
-}
-
-/***********************************************************************
-***********************************************************************/
-
-static int perflib_009_params( REGVAL_CTR *regvals )
-{
-       int base_index;
-       int buffer_size;
-       char *buffer = NULL;
-
-       base_index = reg_perfcount_get_base_index();
-       buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
-       regval_ctr_addvalue(regvals, "Counter", REG_MULTI_SZ, buffer, buffer_size);
-       if(buffer_size > 0)
-               SAFE_FREE(buffer);
-       buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
-       regval_ctr_addvalue(regvals, "Help", REG_MULTI_SZ, buffer, buffer_size);
-       if(buffer_size > 0)
-               SAFE_FREE(buffer);
-       
-       return regval_ctr_numvals( regvals );
-}
-
-/***********************************************************************
-***********************************************************************/
-
-static int hkpt_params( REGVAL_CTR *regvals )
-{
-       uint32 base_index;
-       uint32 buffer_size;
-       char *buffer = NULL;
-
-       /* This is ALMOST the same as perflib_009_params, but HKPT has
-          a "Counters" entry instead of a "Counter" key. <Grrrr> */
-          
-       base_index = reg_perfcount_get_base_index();
-       buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
-       regval_ctr_addvalue(regvals, "Counters", REG_MULTI_SZ, buffer, buffer_size);
-       
-       if(buffer_size > 0)
-               SAFE_FREE(buffer);
-               
-       buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
-       regval_ctr_addvalue(regvals, "Help", REG_MULTI_SZ, buffer, buffer_size);
-       if(buffer_size > 0)
-               SAFE_FREE(buffer);
-       
-       return regval_ctr_numvals( regvals );
-}
-
-/***********************************************************************
-***********************************************************************/
-
-static int current_version( REGVAL_CTR *values )
-{
-       const char *sysroot_string = "c:\\Windows";
-       fstring sysversion;
-       fstring value;
-       uint32 value_length;
-       
-       value_length = push_ucs2( value, value, sysroot_string, sizeof(value), 
-               STR_TERMINATE|STR_NOALIGN );
-       regval_ctr_addvalue( values, "SystemRoot", REG_SZ, value, value_length );
-       
-       fstr_sprintf( sysversion, "%d.%d", lp_major_announce_version(), lp_minor_announce_version() );
-       value_length = push_ucs2( value, value, sysversion, sizeof(value), 
-               STR_TERMINATE|STR_NOALIGN );
-       regval_ctr_addvalue( values, "CurrentVersion", REG_SZ, value, value_length );
-       
-               
-       return regval_ctr_numvals( values );
-}
-
-
-/***********************************************************************
- Structure holding the registry paths and pointers to the value 
- enumeration functions
-***********************************************************************/
-
-static struct reg_dyn_values dynamic_values[] = {
-#if 0
-       { "HKLM/SYSTEM/CURRENTCONTROLSET/SERVICES/NETLOGON/PARAMETERS", &netlogon_params  },
-#endif
-       { "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRODUCTOPTIONS",       &prod_options     },
-       { "HKLM/SYSTEM/CURRENTCONTROLSET/SERVICES/TCPIP/PARAMETERS",    &tcpip_params     },
-       { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PERFLIB",  &perflib_params   }, 
-       { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PERFLIB/009", &perflib_009_params }, 
-       { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION",          &current_version }, 
-       { "HKPT", &hkpt_params },
-       { NULL, NULL }
-};
-
-/***********************************************************************
-***********************************************************************/
-
-int fetch_dynamic_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
-{
-       int i;
-       char *path = NULL;
-       TALLOC_CTX *ctx = talloc_tos();
-
-       path = talloc_strdup(ctx, key->name);
-       if (!path) {
-               return -1;
-       }
-       path = normalize_reg_path(ctx, path);
-       if (!path) {
-               return -1;
-       }
-
-       for ( i=0; dynamic_values[i].path; i++ ) {
-               if ( strcmp( path, dynamic_values[i].path ) == 0 )
-                       return dynamic_values[i].fetch_values( val );
-       }
-
-       return -1;
-}
-
-/***********************************************************************
-***********************************************************************/
-
-bool check_dynamic_reg_values( REGISTRY_KEY *key )
-{
-       int i;
-       char *path = NULL;
-       TALLOC_CTX *ctx = talloc_tos();
-
-       path = talloc_strdup(ctx, key->name);
-       if (!path) {
-               return false;
-       }
-       path = normalize_reg_path(ctx, path);
-       if (!path) {
-               return false;
-       }
-
-       for ( i=0; dynamic_values[i].path; i++ ) {
-               /* can't write to dynamic keys */
-               if ( strcmp( path, dynamic_values[i].path ) == 0 )
-                       return true;
-       }
-
-       return false;
-}
similarity index 80%
rename from source3/registry/reg_frontend.c
rename to source3/registry/reg_init_full.c
index 6674b0ba205c91d389c92e2cca3254e42523da03..b6a644bb11f6adc3bcd8cc4c587759afd89b3265 100644 (file)
@@ -2,6 +2,7 @@
  *  Unix SMB/CIFS implementation.
  *  Virtual Windows Registry Layer
  *  Copyright (C) Gerald Carter                     2002-2005
+ *  Copyright (C) Michael Adam                      2008
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,7 +18,7 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-/* Implementation of registry frontend view functions. */
+/* Initialize the registry with all available backends. */
 
 #include "includes.h"
 
@@ -29,6 +30,11 @@ extern REGISTRY_OPS eventlog_ops;
 extern REGISTRY_OPS shares_reg_ops;
 extern REGISTRY_OPS smbconf_reg_ops;
 extern REGISTRY_OPS netlogon_params_reg_ops;
+extern REGISTRY_OPS prod_options_reg_ops;
+extern REGISTRY_OPS tcpip_params_reg_ops;
+extern REGISTRY_OPS hkpt_params_reg_ops;
+extern REGISTRY_OPS current_version_reg_ops;
+extern REGISTRY_OPS perflib_reg_ops;
 extern REGISTRY_OPS regdb_ops;         /* these are the default */
 
 /* array of REGISTRY_HOOK's which are read into a tree for easy access */
@@ -42,12 +48,18 @@ REGISTRY_HOOK reg_hooks[] = {
   { KEY_SHARES,                &shares_reg_ops },
   { KEY_SMBCONF,               &smbconf_reg_ops },
   { KEY_NETLOGON_PARAMS,       &netlogon_params_reg_ops },
+  { KEY_PROD_OPTIONS,          &prod_options_reg_ops },
+  { KEY_TCPIP_PARAMS,          &tcpip_params_reg_ops },
+  { KEY_HKPT,                  &hkpt_params_reg_ops },
+  { KEY_CURRENT_VERSION,       &current_version_reg_ops },
+  { KEY_PERFLIB,               &perflib_reg_ops },
 #endif
   { NULL, NULL }
 };
 
 /***********************************************************************
  Open the registry database and initialize the REGISTRY_HOOK cache
+ with all available backens.
  ***********************************************************************/
  
 bool init_registry( void )
@@ -89,21 +101,3 @@ bool init_registry( void )
        TALLOC_FREE(frame);
        return ret;
 }
-
-WERROR regkey_open_internal( TALLOC_CTX *ctx, REGISTRY_KEY **regkey,
-                            const char *path,
-                             const struct nt_user_token *token,
-                            uint32 access_desired )
-{
-       struct registry_key *key;
-       WERROR err;
-
-       err = reg_open_path(NULL, path, access_desired, token, &key);
-       if (!W_ERROR_IS_OK(err)) {
-               return err;
-       }
-
-       *regkey = talloc_move(ctx, &key->key);
-       TALLOC_FREE(key);
-       return WERR_OK;
-}
diff --git a/source3/registry/reg_util_legacy.c b/source3/registry/reg_util_legacy.c
new file mode 100644 (file)
index 0000000..3e68025
--- /dev/null
@@ -0,0 +1,47 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  Virtual Windows Registry Layer
+ *  Copyright (C) Gerald Carter                     2002-2005
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Implementation of registry frontend view functions. */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
+/**
+ * legacy open key function that should be replaced by uses of
+ * reg_open_path
+ */
+WERROR regkey_open_internal( TALLOC_CTX *ctx, REGISTRY_KEY **regkey,
+                            const char *path,
+                             const struct nt_user_token *token,
+                            uint32 access_desired )
+{
+       struct registry_key *key;
+       WERROR err;
+
+       err = reg_open_path(NULL, path, access_desired, token, &key);
+       if (!W_ERROR_IS_OK(err)) {
+               return err;
+       }
+
+       *regkey = talloc_move(ctx, &key->key);
+       TALLOC_FREE(key);
+       return WERR_OK;
+}
index f4cb424527b01a8652e0f1345bfc0e6d1065ce0f..81b2ea5d68c5e4ccdc03acdc1cd1c0b47b0f2d46 100644 (file)
@@ -2596,7 +2596,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state
                                                const char *password,
                                                NTSTATUS *perr)
 {
-       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
+       uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
        struct rpc_pipe_client *netlogon_pipe = NULL;
        struct rpc_pipe_client *result = NULL;
 
@@ -2630,7 +2630,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
                                                 const char *domain,
                                                NTSTATUS *perr)
 {
-       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
+       uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
        struct rpc_pipe_client *netlogon_pipe = NULL;
        struct rpc_pipe_client *result = NULL;
 
index bf8313816cbbb90b274cfb2996cefac191576cfc..7cf8726052fa5b4e81850346d10dc3c8984d0844 100644 (file)
@@ -1643,7 +1643,7 @@ NTSTATUS rpccli_samr_lookup_names(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
 
 NTSTATUS rpccli_samr_create_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                   POLICY_HND *domain_pol, const char *acct_name,
-                                  uint32 acb_info, uint32 access_mask,
+                                  uint32 acb_info, uint32 acct_flags,
                                   POLICY_HND *user_pol, uint32 *rid)
 {
        prs_struct qbuf, rbuf;
@@ -1658,7 +1658,7 @@ NTSTATUS rpccli_samr_create_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *me
 
        /* Marshall data and send request */
 
-       init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, access_mask);
+       init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, acct_flags);
 
        CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CREATE_USER,
                q, r,
index 614a80dd6fe29ef7a47ca98cdefc47bcc48862a1..23add3dffdd7e217e02cc282ed45667ef936aa5c 100644 (file)
@@ -5172,7 +5172,7 @@ reads or writes a structure.
 void init_samr_q_create_user(SAMR_Q_CREATE_USER * q_u,
                             POLICY_HND *pol,
                             const char *name,
-                            uint32 acb_info, uint32 access_mask)
+                            uint32 acb_info, uint32 acct_flags)
 {
        DEBUG(5, ("samr_init_samr_q_create_user\n"));
 
@@ -5182,7 +5182,7 @@ void init_samr_q_create_user(SAMR_Q_CREATE_USER * q_u,
        init_uni_hdr(&q_u->hdr_name, &q_u->uni_name);
 
        q_u->acb_info = acb_info;
-       q_u->access_mask = access_mask;
+       q_u->acct_flags = acct_flags;
 }
 
 /*******************************************************************
@@ -5213,7 +5213,7 @@ bool samr_io_q_create_user(const char *desc, SAMR_Q_CREATE_USER * q_u,
                return False;
        if(!prs_uint32("acb_info   ", ps, depth, &q_u->acb_info))
                return False;
-       if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask))
+       if(!prs_uint32("acct_flags", ps, depth, &q_u->acct_flags))
                return False;
 
        return True;
index bde7936343360c5717a0ec63fcc7ba9bc1da4465..c8f732153c1231f44df221668eff339f2545b93b 100644 (file)
@@ -44,16 +44,16 @@ void copy_id20_to_sam_passwd(struct samu *to, SAM_USER_INFO_20 *from)
        char *new_string;
        DATA_BLOB mung;
 
-       if (from == NULL || to == NULL) 
+       if (from == NULL || to == NULL)
                return;
-       
+
        if (from->hdr_munged_dial.buffer) {
                old_string = pdb_get_munged_dial(to);
                mung.length = from->hdr_munged_dial.uni_str_len;
                mung.data = (uint8 *) from->uni_munged_dial.buffer;
                mung.free = NULL;
                new_string = (mung.length == 0) ?
-                       NULL : base64_encode_data_blob(mung);
+                       NULL : base64_encode_data_blob(talloc_tos(), mung);
                DEBUG(10,("INFO_20 UNI_MUNGED_DIAL: %s -> %s\n",old_string, new_string));
                if (STRING_CHANGED_NC(old_string,new_string))
                        pdb_set_munged_dial(to   , new_string, PDB_CHANGED);
@@ -196,7 +196,7 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
                mung.data = (uint8 *) from->uni_munged_dial.buffer;
                mung.free = NULL;
                newstr = (mung.length == 0) ?
-                       NULL : base64_encode_data_blob(mung);
+                       NULL : base64_encode_data_blob(talloc_tos(), mung);
                DEBUG(10,("INFO_21 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
                if (STRING_CHANGED_NC(old_string,newstr))
                        pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
@@ -421,7 +421,7 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
                mung.data = (uint8 *) from->uni_munged_dial.buffer;
                mung.free = NULL;
                newstr = (mung.length == 0) ?
-                       NULL : base64_encode_data_blob(mung);
+                       NULL : base64_encode_data_blob(talloc_tos(), mung);
                DEBUG(10,("INFO_23 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
                if (STRING_CHANGED_NC(old_string, newstr))
                        pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
@@ -633,7 +633,7 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from)
                mung.data = (uint8 *) from->uni_munged_dial.buffer;
                mung.free = NULL;
                newstr = (mung.length == 0) ?
-                       NULL : base64_encode_data_blob(mung);
+                       NULL : base64_encode_data_blob(talloc_tos(), mung);
                DEBUG(10,("INFO_25 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
                if (STRING_CHANGED_NC(old_string,newstr))
                        pdb_set_munged_dial(to   , newstr, PDB_CHANGED);
index 171027fa496d54a7853e09df581e8a6d2b1fbf09..5b42c6bc0e0dd4ccf26d7be3cf4479360163b5ed 100644 (file)
@@ -1450,7 +1450,7 @@ static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        const char *acct_name;
        uint32 acb_info;
-       uint32 user_rid;
+       uint32 acct_flags, user_rid;
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
 
        if ((argc < 2) || (argc > 3)) {
@@ -1459,7 +1459,7 @@ static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli,
        }
 
        acct_name = argv[1];
-       
+
        if (argc > 2)
                 sscanf(argv[2], "%x", &access_mask);
 
@@ -1483,10 +1483,13 @@ static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli,
        /* Create domain user */
 
        acb_info = ACB_NORMAL;
-       access_mask = 0xe005000b;
+       acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
+                       SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
+                       SAMR_STANDARD_DELETE | SAMR_USER_SETPASS |
+                       SAMR_USER_GETATTR | SAMR_USER_SETATTR;
 
        result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
-                                         acct_name, acb_info, access_mask,
+                                         acct_name, acb_info, acct_flags,
                                          &user_pol, &user_rid);
 
        if (!NT_STATUS_IS_OK(result))
index a7969bddd1eeb82341a31facd253863b11a80c47..d98cb992769df3893e79b96d039e0f727f2b8135 100644 (file)
@@ -1222,9 +1222,10 @@ void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
 {
        char    *ptr;
+       char *saveptr;
 
        /* get the next token */
-       ptr = strtok(str, delim);
+       ptr = strtok_r(str, delim, &saveptr);
 
        /* a string of 'NULL' is used to represent an empty
           parameter because two consecutive delimiters
@@ -1251,7 +1252,8 @@ static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
 {
        char    *str, *str2;
        uint32  len, i;
-       
+       char *saveptr;
+
        /* fill in the UNISTR fields */
        str = get_driver_3_param (args, ":", &info->name);
        str = get_driver_3_param (NULL, ":", &info->driverpath);
@@ -1266,13 +1268,13 @@ static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
        str = str2;                     
 
        /* begin to strip out each filename */
-       str = strtok(str, ",");         
+       str = strtok_r(str, ",", &saveptr);
        len = 0;
        while (str != NULL)
        {
                /* keep a cumlative count of the str lengths */
                len += strlen(str)+1;
-               str = strtok(NULL, ",");
+               str = strtok_r(NULL, ",", &saveptr);
        }
 
        /* allocate the space; add one extra slot for a terminating NULL.
index 081e0fb15e9aa80e26d10d46897ae15b4961b1f5..7b499918b068b40f5664b06fd64b6f77567441b9 100644 (file)
@@ -605,7 +605,7 @@ static NTSTATUS do_cmd(struct cli_state *cli,
                }
 
                if (cmd_entry->pipe_idx == PI_NETLOGON) {
-                       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+                       uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
                        uint32 sec_channel_type;
                        uchar trust_password[16];
        
index 5a170b21172d7ee5f9887ca6a527fc2c7d78072a..c6232cf30179a781f56ffb06fea713611bd66cfe 100755 (executable)
@@ -186,7 +186,7 @@ cat >$SERVERCONFFILE<<EOF
        map hidden = yes
        map system = yes
        create mask = 755
-       vfs objects = $BINDIR/xattr_tdb.so
+       vfs objects = $BINDIR/xattr_tdb.so $BINDIR/streams_xattr.so
 [hideunread]
        copy = tmp
        hide unreadable = yes
index 0b4a52d4b50cbc7191bcb7ed6ad655435dfb6b4e..91863b7a6bf68f85130b7aad9b645f6ebdc2c9cf 100755 (executable)
@@ -50,7 +50,7 @@ skipped="BASE-CHARSET BASE-DELAYWRITE BASE-TCONDEV"
 skipped="$skipped RAW-ACLS RAW-COMPOSITE RAW-CONTEXT"
 skipped="$skipped RAW-IOCTL"
 skipped="$skipped RAW-QFILEINFO RAW-QFSINFO RAW-SEARCH"
-skipped="$skipped RAW-SFILEINFO RAW-STREAMS"
+skipped="$skipped RAW-SFILEINFO"
 
 echo "WARNING: Skipping tests $skipped"
 
index b1daae4df8c790c4a0bb4aee8b86412811551965..d4e144d5ff8ca5d8ce1b36320cb8dfd2da34fee1 100644 (file)
@@ -526,7 +526,7 @@ SEC_DESC *svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *
        SAFE_FREE(path);
 
        if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
-               DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
+               DEBUG(0,("svcctl_get_secdesc: talloc() failed!\n"));
                TALLOC_FREE( key );
                return NULL;
        }
@@ -582,7 +582,7 @@ bool svcctl_set_secdesc( TALLOC_CTX *ctx, const char *name, SEC_DESC *sec_desc,
        SAFE_FREE(path);
 
        if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
-               DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
+               DEBUG(0,("svcctl_set_secdesc: talloc() failed!\n"));
                TALLOC_FREE( key );
                return False;
        }
index 4c385d7611837f74823fa43f6d09aab48c3e07c2..4bd23a35fc804a43756acbf93e3b865b09705aab 100644 (file)
@@ -155,6 +155,75 @@ static void notify_deferred_opens(struct share_mode_lock *lck)
        }
 }
 
+/****************************************************************************
+ Delete all streams
+****************************************************************************/
+
+static NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
+{
+       struct stream_struct *stream_info;
+       int i;
+       unsigned int num_streams;
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status;
+
+       status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
+                                   &num_streams, &stream_info);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
+               DEBUG(10, ("no streams around\n"));
+               TALLOC_FREE(frame);
+               return NT_STATUS_OK;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
+                          nt_errstr(status)));
+               goto fail;
+       }
+
+       DEBUG(10, ("delete_all_streams found %d streams\n",
+                  num_streams));
+
+       if (num_streams == 0) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_OK;
+       }
+
+       for (i=0; i<num_streams; i++) {
+               int res;
+               char *streamname;
+
+               if (strequal(stream_info[i].name, "::$DATA")) {
+                       continue;
+               }
+
+               streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
+                                            stream_info[i].name);
+
+               if (streamname == NULL) {
+                       DEBUG(0, ("talloc_aprintf failed\n"));
+                       status = NT_STATUS_NO_MEMORY;
+                       goto fail;
+               }
+
+               res = SMB_VFS_UNLINK(conn, streamname);
+
+               TALLOC_FREE(streamname);
+
+               if (res == -1) {
+                       status = map_nt_error_from_unix(errno);
+                       DEBUG(10, ("Could not delete stream %s: %s\n",
+                                  streamname, strerror(errno)));
+                       break;
+               }
+       }
+
+ fail:
+       TALLOC_FREE(frame);
+       return status;
+}
+
 /****************************************************************************
  Deal with removing a share mode on last close.
 ****************************************************************************/
@@ -305,6 +374,19 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
                goto done;
        }
 
+       if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
+           && !is_ntfs_stream_name(fsp->fsp_name)) {
+
+               status = delete_all_streams(conn, fsp->fsp_name);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(5, ("delete_all_streams failed: %s\n",
+                                 nt_errstr(status)));
+                       goto done;
+               }
+       }
+
+
        if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
                /*
                 * This call can potentially fail as another smbd may
@@ -570,12 +652,37 @@ static NTSTATUS close_stat(files_struct *fsp)
   
 NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
 {
+       NTSTATUS status;
+       struct files_struct *base_fsp = fsp->base_fsp;
+
        if(fsp->is_directory) {
-               return close_directory(fsp, close_type);
+               status = close_directory(fsp, close_type);
        } else if (fsp->is_stat) {
-               return close_stat(fsp);
+               status = close_stat(fsp);
        } else if (fsp->fake_file_handle != NULL) {
-               return close_fake_file(fsp);
+               status = close_fake_file(fsp);
+       } else {
+               status = close_normal_file(fsp, close_type);
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
-       return close_normal_file(fsp, close_type);
+
+       if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) {
+
+               /*
+                * fsp was a stream, the base fsp can't be a stream as well
+                *
+                * For SHUTDOWN_CLOSE this is not possible here, because
+                * SHUTDOWN_CLOSE only happens from files.c which walks the
+                * complete list of files. If we mess with more than one fsp
+                * those loops will become confused.
+                */
+
+               SMB_ASSERT(base_fsp->base_fsp == NULL);
+               close_file(base_fsp, close_type);
+       }
+
+       return status;
 }
index be4960cab819481720e7ce3015b0fa597d6dae4c..10e958304905c05ca8714d81c508c338fb224871 100644 (file)
 
 static bool scan_directory(connection_struct *conn, const char *path,
                           char *name, char **found_name);
+static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
+                                 connection_struct *conn,
+                                 const char *orig_path,
+                                 const char *basepath,
+                                 const char *streamname,
+                                 SMB_STRUCT_STAT *pst,
+                                 char **path);
 
 /****************************************************************************
  Mangle the 2nd name and check if it is then equal to the first name.
@@ -119,6 +126,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
        char *start, *end;
        char *dirpath = NULL;
        char *name = NULL;
+       char *stream = NULL;
        bool component_was_mangled = False;
        bool name_has_wildcard = False;
        NTSTATUS result;
@@ -206,6 +214,20 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
+       if (!lp_posix_pathnames()) {
+               stream = strchr_m(name, ':');
+
+               if (stream != NULL) {
+                       char *tmp = talloc_strdup(ctx, stream);
+                       if (tmp == NULL) {
+                               TALLOC_FREE(name);
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       *stream = '\0';
+                       stream = tmp;
+               }
+       }
+
        /*
         * Large directory fix normalization. If we're case sensitive, and
         * the case preserving parameters are set to "no", normalize the case of
@@ -653,6 +675,20 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
        DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
 
  done:
+       if (stream != NULL) {
+               char *tmp = NULL;
+
+               result = build_stream_path(ctx, conn, orig_path, name, stream,
+                                          pst, &tmp);
+               if (!NT_STATUS_IS_OK(result)) {
+                       goto fail;
+               }
+
+               DEBUG(10, ("build_stream_path returned %s\n", tmp));
+
+               TALLOC_FREE(name);
+               name = tmp;
+       }
        *pp_conv_path = name;
        TALLOC_FREE(dirpath);
        return NT_STATUS_OK;
@@ -823,3 +859,90 @@ static bool scan_directory(connection_struct *conn, const char *path,
        errno = ENOENT;
        return False;
 }
+
+static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
+                                 connection_struct *conn,
+                                 const char *orig_path,
+                                 const char *basepath,
+                                 const char *streamname,
+                                 SMB_STRUCT_STAT *pst,
+                                 char **path)
+{
+       SMB_STRUCT_STAT st;
+       char *result = NULL;
+       NTSTATUS status;
+       unsigned int i, num_streams;
+       struct stream_struct *streams = NULL;
+
+       result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname);
+       if (result == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (SMB_VFS_STAT(conn, result, &st) == 0) {
+               *pst = st;
+               *path = result;
+               return NT_STATUS_OK;
+       }
+
+       if (errno != ENOENT) {
+               status = map_nt_error_from_unix(errno);
+               DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status)));
+               goto fail;
+       }
+
+       status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx,
+                                   &num_streams, &streams);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               SET_STAT_INVALID(*pst);
+               *path = result;
+               return NT_STATUS_OK;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
+               goto fail;
+       }
+
+       for (i=0; i<num_streams; i++) {
+               DEBUG(10, ("comparing [%s] and [%s]: ",
+                          streamname, streams[i].name));
+               if (fname_equal(streamname, streams[i].name,
+                               conn->case_sensitive)) {
+                       DEBUGADD(10, ("equal\n"));
+                       break;
+               }
+               DEBUGADD(10, ("not equal\n"));
+       }
+
+       if (i == num_streams) {
+               SET_STAT_INVALID(*pst);
+               *path = result;
+               TALLOC_FREE(streams);
+               return NT_STATUS_OK;
+       }
+
+       TALLOC_FREE(result);
+
+       result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name);
+       if (result == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
+       }
+
+       SET_STAT_INVALID(*pst);
+
+       if (SMB_VFS_STAT(conn, result, pst) == 0) {
+               stat_cache_add(orig_path, result, conn->case_sensitive);
+       }
+
+       *path = result;
+       TALLOC_FREE(streams);
+       return NT_STATUS_OK;
+
+ fail:
+       TALLOC_FREE(result);
+       TALLOC_FREE(streams);
+       return status;
+}
index 4ae735633b57b52a32ea0a1f6d908d7689362e00..8ffa0f7751cb4ce1cd0d1d0c9cb0a2143ab71da4 100644 (file)
@@ -288,12 +288,13 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx,
        char **alt_path = NULL;
        int count = 0, i;
        struct referral *reflist;
+       char *saveptr;
 
        temp = talloc_strdup(ctx, target);
        if (!temp) {
                return False;
        }
-       prot = strtok(temp,":");
+       prot = strtok_r(temp, ":", &saveptr);
        if (!prot) {
                DEBUG(0,("parse_msdfs_symlink: invalid path !\n"));
                return False;
@@ -306,7 +307,7 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx,
 
        /* parse out the alternate paths */
        while((count<MAX_REFERRAL_COUNT) &&
-             ((alt_path[count] = strtok(NULL,",")) != NULL)) {
+             ((alt_path[count] = strtok_r(NULL, ",", &saveptr)) != NULL)) {
                count++;
        }
 
index e8df732ea23f3f59e30a03cb257f902b59dde181..9381174af0c542baaa51dfc7659ce01effa7f86a 100644 (file)
@@ -271,6 +271,9 @@ void send_nt_replies(connection_struct *conn,
 
 /****************************************************************************
  Is it an NTFS stream name ?
+ An NTFS file name is <path>.<extention>:<stream name>:<stream type>
+ $DATA can be used as both a stream name and a stream type. A missing stream
+ name or type implies $DATA.
 ****************************************************************************/
 
 bool is_ntfs_stream_name(const char *fname)
index 9d48bcc98b563e2af37a8e6a2d73364450f0aa9c..aa4bc48f3d1197e71c43eff0bae8e769be7f36c2 100644 (file)
@@ -1842,7 +1842,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
        set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created);
 
        /* Handle strange delete on close create semantics. */
-       if ((create_options & FILE_DELETE_ON_CLOSE) && can_set_initial_delete_on_close(lck)) {
+       if ((create_options & FILE_DELETE_ON_CLOSE)
+           && (is_ntfs_stream_name(fname)
+               || can_set_initial_delete_on_close(lck))) {
                status = can_set_delete_on_close(fsp, True, new_dos_attributes);
 
                if (!NT_STATUS_IS_OK(status)) {
@@ -2104,7 +2106,7 @@ NTSTATUS open_directory(connection_struct *conn,
                 (unsigned int)create_disposition,
                 (unsigned int)file_attributes));
 
-       if (is_ntfs_stream_name(fname)) {
+       if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS) && is_ntfs_stream_name(fname)) {
                DEBUG(2, ("open_directory: %s is a stream name!\n", fname));
                return NT_STATUS_NOT_A_DIRECTORY;
        }
@@ -2443,6 +2445,116 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx
        return result;
 }
 
+/*
+ * If a main file is opened for delete, all streams need to be checked for
+ * !FILE_SHARE_DELETE. Do this by opening with DELETE_ACCESS.
+ * If that works, delete them all by setting the delete on close and close.
+ */
+
+static NTSTATUS open_streams_for_delete(connection_struct *conn,
+                                       const char *fname)
+{
+       struct stream_struct *stream_info;
+       files_struct **streams;
+       int i;
+       unsigned int num_streams;
+       TALLOC_CTX *frame = talloc_stackframe();
+       NTSTATUS status;
+
+       status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(),
+                                   &num_streams, &stream_info);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)
+           || NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               DEBUG(10, ("no streams around\n"));
+               TALLOC_FREE(frame);
+               return NT_STATUS_OK;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n",
+                          nt_errstr(status)));
+               goto fail;
+       }
+
+       DEBUG(10, ("open_streams_for_delete found %d streams\n",
+                  num_streams));
+
+       if (num_streams == 0) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_OK;
+       }
+
+       streams = TALLOC_ARRAY(talloc_tos(), files_struct *, num_streams);
+       if (streams == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
+       }
+
+       for (i=0; i<num_streams; i++) {
+               char *streamname;
+
+               if (strequal(stream_info[i].name, "::$DATA")) {
+                       streams[i] = NULL;
+                       continue;
+               }
+
+               streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
+                                            stream_info[i].name);
+
+               if (streamname == NULL) {
+                       DEBUG(0, ("talloc_aprintf failed\n"));
+                       status = NT_STATUS_NO_MEMORY;
+                       goto fail;
+               }
+
+               status = create_file_unixpath
+                       (conn,                  /* conn */
+                        NULL,                  /* req */
+                        streamname,            /* fname */
+                        DELETE_ACCESS,         /* access_mask */
+                        FILE_SHARE_READ | FILE_SHARE_WRITE
+                        | FILE_SHARE_DELETE,   /* share_access */
+                        FILE_OPEN,             /* create_disposition*/
+                        NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE, /* create_options */
+                        FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+                        0,                     /* oplock_request */
+                        0,                     /* allocation_size */
+                        NULL,                  /* sd */
+                        NULL,                  /* ea_list */
+                        &streams[i],           /* result */
+                        NULL,                  /* pinfo */
+                        NULL);                 /* psbuf */
+
+               TALLOC_FREE(streamname);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("Could not open stream %s: %s\n",
+                                  streamname, nt_errstr(status)));
+                       break;
+               }
+       }
+
+       /*
+        * don't touch the variable "status" beyond this point :-)
+        */
+
+       for (i -= 1 ; i >= 0; i--) {
+               if (streams[i] == NULL) {
+                       continue;
+               }
+
+               DEBUG(10, ("Closing stream # %d, %s\n", i,
+                          streams[i]->fsp_name));
+               close_file(streams[i], NORMAL_CLOSE);
+       }
+
+ fail:
+       TALLOC_FREE(frame);
+       return status;
+}
+
 /*
  * Wrapper around open_file_ntcreate and open_directory
  */
@@ -2466,6 +2578,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
 {
        SMB_STRUCT_STAT sbuf;
        int info = FILE_WAS_OPENED;
+       files_struct *base_fsp = NULL;
        files_struct *fsp = NULL;
        NTSTATUS status;
 
@@ -2495,7 +2608,23 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
                sbuf = *psbuf;
        }
        else {
-               SET_STAT_INVALID(sbuf);
+               if (SMB_VFS_STAT(conn, fname, &sbuf) == -1) {
+                       SET_STAT_INVALID(sbuf);
+               }
+       }
+
+       if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
+           && (access_mask & DELETE_ACCESS)
+           && !is_ntfs_stream_name(fname)) {
+               /*
+                * We can't open a file with DELETE access if any of the
+                * streams is open without FILE_SHARE_DELETE
+                */
+               status = open_streams_for_delete(conn, fname);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto fail;
+               }
        }
 
        /* This is the correct thing to do (check every time) but can_delete
@@ -2528,12 +2657,61 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
        }
 #endif
 
+       if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
+           && is_ntfs_stream_name(fname)
+           && (!(create_options & NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE))) {
+               char *base;
+               uint32 base_create_disposition;
+
+               if (create_options & FILE_DIRECTORY_FILE) {
+                       status = NT_STATUS_NOT_A_DIRECTORY;
+                       goto fail;
+               }
+
+               status = split_ntfs_stream_name(talloc_tos(), fname,
+                                               &base, NULL);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("split_ntfs_stream_name failed: %s\n",
+                                  nt_errstr(status)));
+                       goto fail;
+               }
+
+               SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
+
+               switch (create_disposition) {
+               case FILE_OPEN:
+                       base_create_disposition = FILE_OPEN;
+                       break;
+               default:
+                       base_create_disposition = FILE_OPEN_IF;
+                       break;
+               }
+
+               status = create_file_unixpath(conn, NULL, base, 0,
+                                             FILE_SHARE_READ
+                                             | FILE_SHARE_WRITE
+                                             | FILE_SHARE_DELETE,
+                                             base_create_disposition,
+                                             0, 0, 0, 0, NULL, NULL,
+                                             &base_fsp, NULL, NULL);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("create_file_unixpath for base %s failed: "
+                                  "%s\n", base, nt_errstr(status)));
+                       goto fail;
+               }
+       }
+
        /*
         * If it's a request for a directory open, deal with it separately.
         */
 
        if (create_options & FILE_DIRECTORY_FILE) {
 
+               if (create_options & FILE_NON_DIRECTORY_FILE) {
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       goto fail;
+               }
+
                /* Can't open a temp directory. IFS kit test. */
                if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
                        status = NT_STATUS_INVALID_PARAMETER;
@@ -2664,6 +2842,16 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
 
        DEBUG(10, ("create_file: info=%d\n", info));
 
+       /*
+        * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In
+        * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would
+        * also close fsp->base_fsp which we have to also do explicitly in
+        * this routine here, as not in all "goto fail:" we have the fsp set
+        * up already to be initialized with the base_fsp.
+        */
+
+       fsp->base_fsp = base_fsp;
+
        *result = fsp;
        if (pinfo != NULL) {
                *pinfo = info;
@@ -2685,6 +2873,10 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
                close_file(fsp, ERROR_CLOSE);
                fsp = NULL;
        }
+       if (base_fsp != NULL) {
+               close_file(base_fsp, ERROR_CLOSE);
+               base_fsp = NULL;
+       }
        return status;
 }
 
@@ -2812,19 +3004,18 @@ NTSTATUS create_file(connection_struct *conn,
                        status = NT_STATUS_NO_MEMORY;
                        goto fail;
                }
-       } else {
-               /*
-                * Check to see if this is a mac fork of some kind.
-                */
+       }
 
-               if (is_ntfs_stream_name(fname)) {
-                       enum FAKE_FILE_TYPE fake_file_type;
+       /*
+        * Check to see if this is a mac fork of some kind.
+        */
 
-                       fake_file_type = is_fake_file(fname);
+       if (is_ntfs_stream_name(fname)) {
+               enum FAKE_FILE_TYPE fake_file_type;
 
-                       if (fake_file_type == FAKE_FILE_TYPE_NONE) {
-                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
-                       }
+               fake_file_type = is_fake_file(fname);
+
+               if (fake_file_type != FAKE_FILE_TYPE_NONE) {
 
                        /*
                         * Here we go! support for changing the disk quotas
@@ -2843,8 +3034,7 @@ NTSTATUS create_file(connection_struct *conn,
                                goto fail;
                        }
 
-                       SET_STAT_INVALID(sbuf);
-
+                       ZERO_STRUCT(sbuf);
                        goto done;
                }
        }
@@ -2889,6 +3079,8 @@ NTSTATUS create_file(connection_struct *conn,
                fname = converted_fname;
        }
 
+       TALLOC_FREE(case_state);
+
        /* All file access must go through check_name() */
 
        status = check_name(conn, fname);
index 6b517c3d862cc15be2191e844bb9d47888c129bc..85e1ccf0a7f27c7fa365205475517f666ef06f65 100644 (file)
@@ -759,6 +759,7 @@ bool authorise_login(int snum, fstring user, DATA_BLOB password,
        if (!ok) {
                char *auser;
                char *user_list = NULL;
+               char *saveptr;
 
                if ( session_userlist )
                        user_list = SMB_STRDUP(session_userlist);
@@ -768,8 +769,9 @@ bool authorise_login(int snum, fstring user, DATA_BLOB password,
                if (!user_list)
                        return(False);
 
-               for (auser=strtok(user_list,LIST_SEP); !ok && auser;
-                    auser = strtok(NULL,LIST_SEP)) {
+               for (auser = strtok_r(user_list, LIST_SEP, &saveptr);
+                    !ok && auser;
+                    auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
                        fstring user2;
                        fstrcpy(user2,auser);
                        if (!user_ok(user2,snum))
@@ -792,6 +794,7 @@ bool authorise_login(int snum, fstring user, DATA_BLOB password,
                TALLOC_CTX *ctx = talloc_tos();
                char *auser;
                char *user_list = talloc_strdup(ctx, lp_username(snum));
+               char *saveptr;
 
                if (!user_list) {
                        goto check_guest;
@@ -806,8 +809,9 @@ bool authorise_login(int snum, fstring user, DATA_BLOB password,
                        goto check_guest;
                }
 
-               for (auser=strtok(user_list,LIST_SEP); auser && !ok;
-                    auser = strtok(NULL,LIST_SEP)) {
+               for (auser = strtok_r(user_list, LIST_SEP, &saveptr);
+                    auser && !ok;
+                    auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
                        if (*auser == '@') {
                                auser = validate_group(auser+1,password,snum);
                                if (auser) {
index a5bdb9665032a6db29d1eaede6ce9cc27df16a82..d961f98cc00fae79564dc5e56723a25a2e193853 100644 (file)
@@ -23,7 +23,6 @@
 extern struct auth_context *negprot_global_auth_context;
 extern int smb_echo_count;
 
-const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
 static enum smb_read_errors smb_read_error = SMB_READ_OK;
 
 /*
@@ -156,16 +155,8 @@ static ssize_t read_packet_remainder(int fd,
                return len;
        }
 
-       if (timeout > 0) {
-               ret = read_socket_with_timeout(fd,
-                                               buffer,
-                                               len,
-                                               len,
-                                               timeout,
-                                               get_srv_read_error());
-       } else {
-               ret = read_data(fd, buffer, len, get_srv_read_error());
-       }
+       ret = read_socket_with_timeout(fd, buffer, len, len, timeout,
+                                      get_srv_read_error());
 
        if (ret != len) {
                cond_set_smb_read_error(get_srv_read_error(),
@@ -207,19 +198,10 @@ static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
 
        memcpy(writeX_header, lenbuf, sizeof(lenbuf));
 
-       if (timeout > 0) {
-               ret = read_socket_with_timeout(fd,
-                                       writeX_header + 4,
-                                       STANDARD_WRITE_AND_X_HEADER_SIZE,
-                                       STANDARD_WRITE_AND_X_HEADER_SIZE,
-                                       timeout,
-                                       get_srv_read_error());
-       } else {
-               ret = read_data(fd,
-                               writeX_header+4,
-                               STANDARD_WRITE_AND_X_HEADER_SIZE,
-                               get_srv_read_error());
-       }
+       ret = read_socket_with_timeout(fd, writeX_header + 4,
+                                      STANDARD_WRITE_AND_X_HEADER_SIZE,
+                                      STANDARD_WRITE_AND_X_HEADER_SIZE,
+                                      timeout, get_srv_read_error());
 
        if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) {
                cond_set_smb_read_error(get_srv_read_error(),
index 381ddfe1517b4f83d8030af1715127a86cd6394e..4ea81a3819053120ded61f8dcee8f08b5085afd9 100644 (file)
@@ -167,6 +167,7 @@ static NTSTATUS check_path_syntax_internal(char *path,
        }
 
        *d = '\0';
+
        return ret;
 }
 
@@ -2289,14 +2290,22 @@ static NTSTATUS do_unlink(connection_struct *conn,
        /* On open checks the open itself will check the share mode, so
           don't do it here as we'll get it wrong. */
 
-       status = open_file_ntcreate(conn, req, fname, &sbuf,
-                                   DELETE_ACCESS,
-                                   FILE_SHARE_NONE,
-                                   FILE_OPEN,
-                                   0,
-                                   FILE_ATTRIBUTE_NORMAL,
-                                   req != NULL ? 0 : INTERNAL_OPEN_ONLY,
-                                   NULL, &fsp);
+       status = create_file_unixpath
+               (conn,                  /* conn */
+                req,                   /* req */
+                fname,                 /* fname */
+                DELETE_ACCESS,         /* access_mask */
+                FILE_SHARE_NONE,       /* share_access */
+                FILE_OPEN,             /* create_disposition*/
+                FILE_NON_DIRECTORY_FILE, /* create_options */
+                FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+                0,                     /* oplock_request */
+                0,                     /* allocation_size */
+                NULL,                  /* sd */
+                NULL,                  /* ea_list */
+                &fsp,                  /* result */
+                NULL,                  /* pinfo */
+                &sbuf);                /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("open_file_ntcreate failed: %s\n",
@@ -3366,7 +3375,6 @@ void error_to_writebrawerr(struct smb_request *req)
 void reply_writebraw(struct smb_request *req)
 {
        connection_struct *conn = req->conn;
-       int outsize = 0;
        char *buf = NULL;
        ssize_t nwritten=0;
        ssize_t total_written=0;
@@ -3476,8 +3484,7 @@ void reply_writebraw(struct smb_request *req)
         * it to send more bytes */
 
        memcpy(buf, req->inbuf, smb_size);
-       outsize = srv_set_message(buf,
-                       Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+       srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
        SCVAL(buf,smb_com,SMBwritebraw);
        SSVALS(buf,smb_vwv0,0xFFFF);
        show_msg(buf);
index ed8061e2f79c6e90b51b7eac7ab9bea42fc6541e..a8aa25405a9d81d1450dc2c3d76b68976f5ffb8f 100644 (file)
@@ -1171,16 +1171,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
         * assumes that all the filesystem mounted withing a share path have
         * the same characteristics, which is likely but not guaranteed.
         */
-       {
-               vfs_statvfs_struct svfs;
-
-               conn->fs_capabilities =
-                   FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
 
-               if (SMB_VFS_STATVFS(conn, conn->connectpath, &svfs) == 0) {
-                       conn->fs_capabilities = svfs.FsCapabilities;
-               }
-       }
+       conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
 
        /*
         * Print out the 'connected as' stuff here as we need
index 23d6f129969e34517efcebd732a8eb980610abcc..fb845220cd761b054ec216c57e452a3ef573e64b 100644 (file)
@@ -5,7 +5,7 @@
    Copyright (C) Stefan (metze) Metzmacher     2003
    Copyright (C) Volker Lendecke               2005-2007
    Copyright (C) Steve French                  2005
-   Copyright (C) James Peach                   2007
+   Copyright (C) James Peach                   2006-2007
 
    Extensively modified by Andrew Tridgell, 1995
 
@@ -105,17 +105,22 @@ static bool samba_private_attr_name(const char *unix_ea_name)
 
        for (i = 0; prohibited_ea_names[i]; i++) {
                if (strequal( prohibited_ea_names[i], unix_ea_name))
-                       return True;
+                       return true;
        }
-       return False;
+       if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
+                       strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
+               return true;
+       }
+       return false;
 }
 
 /****************************************************************************
  Get one EA value. Fill in a struct ea_struct.
 ****************************************************************************/
 
-static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
-                               const char *fname, char *ea_name, struct ea_struct *pea)
+NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
+                     files_struct *fsp, const char *fname,
+                     const char *ea_name, struct ea_struct *pea)
 {
        /* Get the value of this xattr. Max size is 64k. */
        size_t attr_size = 256;
@@ -126,7 +131,7 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str
 
        val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
        if (!val) {
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
 
        if (fsp && fsp->fh->fd != -1) {
@@ -141,7 +146,7 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str
        }
 
        if (sizeret == -1) {
-               return False;
+               return map_nt_error_from_unix(errno);
        }
 
        DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
@@ -149,93 +154,192 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str
 
        pea->flags = 0;
        if (strnequal(ea_name, "user.", 5)) {
-               pea->name = &ea_name[5];
+               pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
        } else {
-               pea->name = ea_name;
+               pea->name = talloc_strdup(mem_ctx, ea_name);
+       }
+       if (pea->name == NULL) {
+               TALLOC_FREE(val);
+               return NT_STATUS_NO_MEMORY;
        }
        pea->value.data = (unsigned char *)val;
        pea->value.length = (size_t)sizeret;
-       return True;
+       return NT_STATUS_OK;
 }
 
-/****************************************************************************
- Return a linked list of the total EA's. Plus the total size
-****************************************************************************/
-
-static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
-                                       const char *fname, size_t *pea_total_len)
+NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
+                               files_struct *fsp, const char *fname,
+                               char ***pnames, size_t *pnum_names)
 {
        /* Get a list of all xattrs. Max namesize is 64k. */
        size_t ea_namelist_size = 1024;
-       char *ea_namelist;
+       char *ea_namelist = NULL;
+
        char *p;
+       char **names, **tmp;
+       size_t num_names;
        ssize_t sizeret;
-       int i;
-       struct ea_list *ea_list_head = NULL;
-
-       *pea_total_len = 0;
 
        if (!lp_ea_support(SNUM(conn))) {
-               return NULL;
+               *pnames = NULL;
+               *pnum_names = 0;
+               return NT_STATUS_OK;
        }
 
-       for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
-            ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
+       /*
+        * TALLOC the result early to get the talloc hierarchy right.
+        */
 
-               if (!ea_namelist) {
-                       return NULL;
+       names = TALLOC_ARRAY(mem_ctx, char *, 1);
+       if (names == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       while (ea_namelist_size <= 65536) {
+
+               ea_namelist = TALLOC_REALLOC_ARRAY(
+                       names, ea_namelist, char, ea_namelist_size);
+               if (ea_namelist == NULL) {
+                       DEBUG(0, ("talloc failed\n"));
+                       TALLOC_FREE(names);
+                       return NT_STATUS_NO_MEMORY;
                }
 
                if (fsp && fsp->fh->fd != -1) {
-                       sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist, ea_namelist_size);
+                       sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
+                                                    ea_namelist_size);
                } else {
-                       sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
+                       sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
+                                                   ea_namelist_size);
                }
 
-               if (sizeret == -1 && errno == ERANGE) {
+               if ((sizeret == -1) && (errno == ERANGE)) {
                        ea_namelist_size *= 2;
-               } else {
+               }
+               else {
                        break;
                }
        }
 
-       if (sizeret == -1)
-               return NULL;
+       if (sizeret == -1) {
+               TALLOC_FREE(names);
+               return map_nt_error_from_unix(errno);
+       }
 
-       DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
+       DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
+                  (unsigned int)sizeret));
 
-       if (sizeret) {
-               for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
-                       struct ea_list *listp;
+       if (sizeret == 0) {
+               TALLOC_FREE(names);
+               *pnames = NULL;
+               *pnum_names = 0;
+               return NT_STATUS_OK;
+       }
 
-                       if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
-                               continue;
+       /*
+        * Ensure the result is 0-terminated
+        */
 
-                       listp = TALLOC_P(mem_ctx, struct ea_list);
-                       if (!listp)
-                               return NULL;
+       if (ea_namelist[sizeret-1] != '\0') {
+               TALLOC_FREE(names);
+               return NT_STATUS_INTERNAL_ERROR;
+       }
 
-                       if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
-                               return NULL;
-                       }
+       /*
+        * count the names
+        */
+       num_names = 0;
 
-                       {
-                               fstring dos_ea_name;
-                               push_ascii_fstring(dos_ea_name, listp->ea.name);
-                               *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
-                               DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
-                                       (unsigned int)*pea_total_len, dos_ea_name,
-                                       (unsigned int)listp->ea.value.length ));
-                       }
-                       DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
+       for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
+               num_names += 1;
+       }
+
+       tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
+       if (tmp == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               TALLOC_FREE(names);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       names = tmp;
+       num_names = 0;
+
+       for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
+               names[num_names++] = p;
+       }
+
+       *pnames = names;
+       *pnum_names = num_names;
+       return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Return a linked list of the total EA's. Plus the total size
+****************************************************************************/
+
+static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
+                                       const char *fname, size_t *pea_total_len)
+{
+       /* Get a list of all xattrs. Max namesize is 64k. */
+       size_t i, num_names;
+       char **names;
+       struct ea_list *ea_list_head = NULL;
+       NTSTATUS status;
+
+       *pea_total_len = 0;
+
+       if (!lp_ea_support(SNUM(conn))) {
+               return NULL;
+       }
+
+       status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
+                                       &names, &num_names);
+
+       if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
+               return NULL;
+       }
+
+       for (i=0; i<num_names; i++) {
+               struct ea_list *listp;
+               fstring dos_ea_name;
+
+               if (strnequal(names[i], "system.", 7)
+                   || samba_private_attr_name(names[i]))
+                       continue;
+
+               listp = TALLOC_P(mem_ctx, struct ea_list);
+               if (listp == NULL) {
+                       return NULL;
                }
-               /* Add on 4 for total length. */
-               if (*pea_total_len) {
-                       *pea_total_len += 4;
+
+               if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
+                                                 fname, names[i],
+                                                 &listp->ea))) {
+                       return NULL;
                }
+
+               push_ascii_fstring(dos_ea_name, listp->ea.name);
+
+               *pea_total_len +=
+                       4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
+
+               DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
+                         "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
+                         (unsigned int)listp->ea.value.length));
+
+               DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
+
+       }
+
+       /* Add on 4 for total length. */
+       if (*pea_total_len) {
+               *pea_total_len += 4;
        }
 
-       DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
+       DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
+                  (unsigned int)*pea_total_len));
+
        return ea_list_head;
 }
 
@@ -2355,6 +2459,40 @@ unsigned char *create_volume_objectid(connection_struct *conn, unsigned char obj
        return objid;
 }
 
+static void samba_extended_info_version(struct smb_extended_info *extended_info)
+{
+       SMB_ASSERT(extended_info != NULL);
+
+       extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
+       extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
+                                      | ((SAMBA_VERSION_MINOR & 0xff) << 16)
+                                      | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
+#ifdef SAMBA_VERSION_REVISION
+       extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
+#endif
+#ifdef SAMBA_VERSION_RC_RELEASE
+       extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
+#else
+#ifdef SAMBA_VERSION_PRE_RELEASE
+       extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
+#endif
+#endif
+#ifdef SAMBA_VERSION_VENDOR_PATCH
+       extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
+#endif
+       /* FIXME: samba_gitcommitdate should contain the git commit date. */
+#ifdef SAMBA_VERSION_GIT_COMMIT_TIME
+       unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
+#endif
+
+       memset(extended_info->samba_version_string, 0,
+              sizeof(extended_info->samba_version_string));
+
+       snprintf (extended_info->samba_version_string,
+                 sizeof(extended_info->samba_version_string),
+                 "%s", samba_version_string());
+}
+
 /****************************************************************************
  Reply to a TRANS2_QFSINFO (query filesystem info).
 ****************************************************************************/
@@ -2693,7 +2831,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                case SMB_FS_OBJECTID_INFORMATION:
                {
                        unsigned char objid[16];
+                       struct smb_extended_info extended_info;
                        memcpy(pdata,create_volume_objectid(conn, objid),16);
+                       samba_extended_info_version (&extended_info);
+                       SIVAL(pdata,16,extended_info.samba_magic);
+                       SIVAL(pdata,20,extended_info.samba_version);
+                       SIVAL(pdata,24,extended_info.samba_subversion);
+                       SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
+                       memcpy(pdata+36,extended_info.samba_version_string,28);
                        data_len = 64;
                        break;
                }
@@ -3468,6 +3613,72 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
        return pdata;
 }
 
+static NTSTATUS marshall_stream_info(unsigned int num_streams,
+                                    const struct stream_struct *streams,
+                                    char *data,
+                                    unsigned int max_data_bytes,
+                                    unsigned int *data_size)
+{
+       unsigned int i;
+       unsigned int ofs = 0;
+
+       for (i=0; i<num_streams; i++) {
+               unsigned int next_offset;
+               size_t namelen;
+               smb_ucs2_t *namebuf;
+
+               namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
+                                           streams[i].name);
+
+               if ((namelen == (size_t)-1) || (namelen <= 2)) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               /*
+                * name_buf is now null-terminated, we need to marshall as not
+                * terminated
+                */
+
+               namelen -= 2;
+
+               if (ofs + 24 + namelen > max_data_bytes) {
+                       TALLOC_FREE(namebuf);
+                       return NT_STATUS_BUFFER_TOO_SMALL;
+               }
+
+               SIVAL(data, ofs+4, namelen);
+               SOFF_T(data, ofs+8, streams[i].size);
+               SOFF_T(data, ofs+16, streams[i].alloc_size);
+               memcpy(data+ofs+24, namebuf, namelen);
+               TALLOC_FREE(namebuf);
+
+               next_offset = ofs + 24 + namelen;
+
+               if (i == num_streams-1) {
+                       SIVAL(data, ofs, 0);
+               }
+               else {
+                       unsigned int align = ndr_align_size(next_offset, 8);
+
+                       if (next_offset + align > max_data_bytes) {
+                               return NT_STATUS_BUFFER_TOO_SMALL;
+                       }
+
+                       memset(data+next_offset, 0, align);
+                       next_offset += align;
+
+                       SIVAL(data, ofs, next_offset - ofs);
+                       ofs = next_offset;
+               }
+
+               ofs = next_offset;
+       }
+
+       *data_size = ofs;
+
+       return NT_STATUS_OK;
+}
+
 /****************************************************************************
  Reply to a TRANSACT2_QFILEINFO on a PIPE !
 ****************************************************************************/
@@ -3743,17 +3954,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
                }
        }
 
-       nlink = sbuf.st_nlink;
-
-       if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
-               /* NTFS does not seem to count ".." */
-               nlink -= 1;
-       }
-
-       if ((nlink > 0) && delete_pending) {
-               nlink -= 1;
-       }
-
        if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
                reply_nterror(req, NT_STATUS_INVALID_LEVEL);
                return;
@@ -3772,6 +3972,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
        if (!mode)
                mode = FILE_ATTRIBUTE_NORMAL;
 
+       nlink = sbuf.st_nlink;
+
+       if (nlink && (mode&aDIR)) {
+               nlink = 1;
+       }
+
+       if ((nlink > 0) && delete_pending) {
+               nlink -= 1;
+       }
+
        fullpathname = fname;
        if (!(mode & aDIR))
                file_size = get_file_size(sbuf);
@@ -4166,28 +4376,49 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        data_size = 4;
                        break;
 
-#if 0
                /*
-                * NT4 server just returns "invalid query" to this - if we try to answer
-                * it then NTws gets a BSOD! (tridge).
-                * W2K seems to want this. JRA.
+                * NT4 server just returns "invalid query" to this - if we try
+                * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
+                * want this. JRA.
+                */
+               /* The first statement above is false - verified using Thursby
+                * client against NT4 -- gcolley.
                 */
                case SMB_QUERY_FILE_STREAM_INFO:
-#endif
-               case SMB_FILE_STREAM_INFORMATION:
-                       DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
-                       if (mode & aDIR) {
-                               data_size = 0;
-                       } else {
-                               size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
-                               SIVAL(pdata,0,0); /* ??? */
-                               SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
-                               SOFF_T(pdata,8,file_size);
-                               SOFF_T(pdata,16,allocation_size);
-                               data_size = 24 + byte_len;
+               case SMB_FILE_STREAM_INFORMATION: {
+                       unsigned int num_streams;
+                       struct stream_struct *streams;
+                       NTSTATUS status;
+
+                       DEBUG(10,("call_trans2qfilepathinfo: "
+                                 "SMB_FILE_STREAM_INFORMATION\n"));
+
+                       status = SMB_VFS_STREAMINFO(
+                               conn, fsp, fname, talloc_tos(),
+                               &num_streams, &streams);
+
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(10, ("could not get stream info: %s\n",
+                                          nt_errstr(status)));
+                               reply_nterror(req, status);
+                               return;
                        }
-                       break;
 
+                       status = marshall_stream_info(num_streams, streams,
+                                                     pdata, max_data_bytes,
+                                                     &data_size);
+
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(10, ("marshall_stream_info failed: %s\n",
+                                          nt_errstr(status)));
+                               reply_nterror(req, status);
+                               return;
+                       }
+
+                       TALLOC_FREE(streams);
+
+                       break;
+               }
                case SMB_QUERY_COMPRESSION_INFO:
                case SMB_FILE_COMPRESSION_INFORMATION:
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
index e82bbea3b301f6991aae11e6dfbc6a5ec8c9fb7b..5931b2b1d06e2717202e219fb2e0a733953e66af 100644 (file)
@@ -223,7 +223,7 @@ static char *uw_pathname(TALLOC_CTX *ctx,
        }
 
        /* For u-files and non-explicit w-dir, look for "utmp dir" */
-       if (!dirname == 0 || strlen(dirname) == 0) {
+       if ((dirname == NULL) || (strlen(dirname) == 0)) {
                dirname = talloc_strdup(ctx, lp_utmpdir());
                if (!dirname) {
                        return NULL;
index 05b41413b47e78ed8408ed251138785363c198e7..8d67e512fe66bb2c30adf72b45ac52253a287a61 100644 (file)
@@ -890,6 +890,7 @@ static bool run_netbench(int client)
        }
 
        while (fgets(line, sizeof(line)-1, f)) {
+               char *saveptr;
                line_count++;
 
                line[strlen(line)-1] = 0;
@@ -899,9 +900,9 @@ static bool run_netbench(int client)
                all_string_sub(line,"client1", cname, sizeof(line));
 
                /* parse the command parameters */
-               params[0] = strtok(line," ");
+               params[0] = strtok_r(line, " ", &saveptr);
                i = 0;
-               while (params[i]) params[++i] = strtok(NULL," ");
+               while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
 
                params[i] = "";
 
@@ -5098,6 +5099,74 @@ static bool run_local_rbtree(int dummy)
        return ret;
 }
 
+static bool test_stream_name(const char *fname, const char *expected_base,
+                            const char *expected_stream,
+                            NTSTATUS expected_status)
+{
+       NTSTATUS status;
+       char *base = NULL;
+       char *stream = NULL;
+
+       status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
+       if (!NT_STATUS_EQUAL(status, expected_status)) {
+               goto error;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return true;
+       }
+
+       if (base == NULL) goto error;
+
+       if (strcmp(expected_base, base) != 0) goto error;
+
+       if ((expected_stream != NULL) && (stream == NULL)) goto error;
+       if ((expected_stream == NULL) && (stream != NULL)) goto error;
+
+       if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
+               goto error;
+
+       TALLOC_FREE(base);
+       TALLOC_FREE(stream);
+       return true;
+
+ error:
+       d_fprintf(stderr, "test_stream(%s, %s, %s, %s)\n",
+                 fname, expected_base ? expected_base : "<NULL>",
+                 expected_stream ? expected_stream : "<NULL>",
+                 nt_errstr(expected_status));
+       d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
+                 base ? base : "<NULL>", stream ? stream : "<NULL>",
+                 nt_errstr(status));
+       TALLOC_FREE(base);
+       TALLOC_FREE(stream);
+       return false;
+}
+
+static bool run_local_stream_name(int dummy)
+{
+       bool ret = true;
+
+       ret &= test_stream_name(
+               "bla", "bla", NULL, NT_STATUS_OK);
+       ret &= test_stream_name(
+               "bla::$DATA", "bla", NULL, NT_STATUS_OK);
+       ret &= test_stream_name(
+               "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
+       ret &= test_stream_name(
+               "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
+       ret &= test_stream_name(
+               "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
+       ret &= test_stream_name(
+               "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
+       ret &= test_stream_name(
+               "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
+       ret &= test_stream_name(
+               "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
+
+       return ret;
+}
+
 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
 {
        if (a.length != b.length) {
@@ -5328,6 +5397,7 @@ static struct {
        { "LOCAL-GENCACHE", run_local_gencache, 0},
        { "LOCAL-RBTREE", run_local_rbtree, 0},
        { "LOCAL-MEMCACHE", run_local_memcache, 0},
+       { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
        {NULL, NULL, 0}};
 
 
index da5e61caf0610702d67cda1fb0efaf8ff9049139..a98f090e624c437751d705923613b3405bb627d8 100644 (file)
@@ -208,6 +208,7 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
        uint32 num_rids, *name_types, *user_rids;
        uint32 flags = 0x3e8;
        uint32 acb_info = ACB_WSTRUST;
+       uint32 acct_flags;
        uint32 fields_present;
        uchar pwbuf[532];
        SAM_USERINFO_CTR ctr;
@@ -245,8 +246,13 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
 
        /* Don't try to set any acb_info flags other than ACB_WSTRUST */
 
+        acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
+                SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
+                SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
+                SAMR_USER_SETATTR;
+       DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
        status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
-                       acct_name, acb_info, 0xe005000b, &user_pol, &user_rid);
+                       acct_name, acb_info, acct_flags, &user_pol, &user_rid);
 
        if ( !NT_STATUS_IS_OK(status) 
                && !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) 
index 677924649cad14fcd1a1932061964c6a2183863b..b08a93627de4cb7b0f417df21d4406113ea7fd08 100644 (file)
@@ -588,7 +588,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        const char *acct_name;
        uint32 acb_info;
-       uint32 access_mask, user_rid;
+       uint32 acct_flags, user_rid;
 
        if (argc < 1) {
                d_printf("User must be specified\n");
@@ -618,10 +618,13 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
        /* Create domain user */
 
        acb_info = ACB_NORMAL;
-       access_mask = 0xe005000b;
+       acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
+               SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
+               SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
+               SAMR_USER_SETATTR;
 
        result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
-                                         acct_name, acb_info, access_mask,
+                                         acct_name, acb_info, acct_flags,
                                          &user_pol, &user_rid);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
@@ -5341,7 +5344,8 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        char *acct_name;
        uint32 acb_info;
-       uint32 unknown, user_rid;
+       uint32 acct_flags=0;
+       uint32 user_rid;
 
        if (argc != 2) {
                d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
@@ -5375,11 +5379,13 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
 
        /* Create trusting domain's account */
        acb_info = ACB_NORMAL; 
-       unknown = 0xe00500b0; /* No idea what this is - a permission mask?
-                                mimir: yes, most probably it is */
+        acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
+                SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
+                SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
+                SAMR_USER_SETATTR;
 
        result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
-                                         acct_name, acb_info, unknown,
+                                         acct_name, acb_info, acct_flags,
                                          &user_pol, &user_rid);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
index 6e37f3c84c472d08a511f004adcd83dcf54606e0..5c3fb2b2ff6a257be55fd7ca37d1792f6c3ddb24 100644 (file)
@@ -45,7 +45,7 @@ NTSTATUS net_rpc_join_ok(const char *domain, const char *server,
 {
        enum security_types sec;
        unsigned int conn_flags = NET_FLAGS_PDC;
-       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
+       uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
        struct cli_state *cli = NULL;
        struct rpc_pipe_client *pipe_hnd = NULL;
        struct rpc_pipe_client *netlogon_pipe = NULL;
@@ -132,7 +132,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        struct cli_state *cli;
        TALLOC_CTX *mem_ctx;
         uint32 acb_info = ACB_WSTRUST;
-       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|(lp_client_schannel() ? NETLOGON_NEG_SCHANNEL : 0);
+       uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS|(lp_client_schannel() ? NETLOGON_NEG_SCHANNEL : 0);
        uint32 sec_channel_type;
        struct rpc_pipe_client *pipe_hnd = NULL;
 
@@ -160,6 +160,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        uint32 flags = 0x3e8;
        char *acct_name;
        const char *const_acct_name;
+       uint32 acct_flags=0;
 
        /* check what type of join */
        if (argc >= 0) {
@@ -249,9 +250,14 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        strlower_m(acct_name);
        const_acct_name = acct_name;
 
+        acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
+                SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
+                SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
+                SAMR_USER_SETATTR;
+       DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
        result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
                                          acct_name, acb_info,
-                                         0xe005000b, &user_pol, 
+                                         acct_flags, &user_pol, 
                                          &user_rid);
 
        if (!NT_STATUS_IS_OK(result) && 
index 779006884d0e1d968519b491dd1a0e0cbebb9547..e1f0cd3751218226751011cdc1575e0ce6679461 100644 (file)
@@ -237,7 +237,7 @@ NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid,
 
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        uchar trust_password[16];
-       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+       uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
        uint32 sec_channel_type = 0;
 
        if (!secrets_fetch_trust_account_password(domain_name,
@@ -365,7 +365,8 @@ static NTSTATUS sam_account_from_delta(struct samu *account, SAM_ACCOUNT_INFO *d
                old_string = pdb_get_munged_dial(account);
                mung.length = delta->hdr_parameters.uni_str_len;
                mung.data = (uint8 *) delta->uni_parameters.buffer;
-               newstr = (mung.length == 0) ? NULL : base64_encode_data_blob(mung);
+               newstr = (mung.length == 0) ? NULL :
+                       base64_encode_data_blob(talloc_tos(), mung);
 
                if (STRING_CHANGED_NC(old_string, newstr))
                        pdb_set_munged_dial(account, newstr, PDB_CHANGED);
@@ -1422,12 +1423,11 @@ static int fprintf_attr(FILE *add_fd, const char *attr_name,
        base64_blob.data = (unsigned char *)value;
        base64_blob.length = strlen(value);
 
-       base64 = base64_encode_data_blob(base64_blob);
+       base64 = base64_encode_data_blob(value, base64_blob);
        SMB_ASSERT(base64 != NULL);
 
        res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
        TALLOC_FREE(value);
-       TALLOC_FREE(base64);
        return res;
 }
 
index 6a702fc0cfad85eea9fe566b3b6c21984da75118..3e2093a1940456a963c991b508173c4da1e5138b 100644 (file)
@@ -1,23 +1,24 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    Winbind status program.
 
    Copyright (C) Tim Potter      2000-2003
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
-   Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000 
+   Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000
    Copyright (C) Robert O'Callahan 2006 (added cached credential code).
+   Copyright (C) Kai Blin <kai@samba.org> 2008
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -28,7 +29,8 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-#define SQUID_BUFFER_SIZE 2010
+#define INITIAL_BUFFER_SIZE 300
+#define MAX_BUFFER_SIZE 630000
 
 enum stdio_helper_mode {
        SQUID_2_4_BASIC,
@@ -42,28 +44,56 @@ enum stdio_helper_mode {
        NUM_HELPER_MODES
 };
 
-typedef void (*stdio_helper_function)(enum stdio_helper_mode stdio_helper_mode, 
-                                    char *buf, int length);
+enum ntlm_auth_cli_state {
+       CLIENT_INITIAL = 0,
+       CLIENT_RESPONSE,
+       CLIENT_FINISHED,
+       CLIENT_ERROR
+};
+
+enum ntlm_auth_svr_state {
+       SERVER_INITIAL = 0,
+       SERVER_CHALLENGE,
+       SERVER_FINISHED,
+       SERVER_ERROR
+};
+
+struct ntlm_auth_state {
+       TALLOC_CTX *mem_ctx;
+       enum stdio_helper_mode helper_mode;
+       enum ntlm_auth_cli_state cli_state;
+       enum ntlm_auth_svr_state svr_state;
+       struct ntlmssp_state *ntlmssp_state;
+       uint32_t neg_flags;
+       char *want_feature_list;
+       bool have_session_key;
+       DATA_BLOB session_key;
+       DATA_BLOB initial_message;
+};
+
+typedef void (*stdio_helper_function)(struct ntlm_auth_state *state, char *buf,
+                                       int length);
 
-static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode, 
+static void manage_squid_basic_request (struct ntlm_auth_state *state,
                                        char *buf, int length);
 
-static void manage_squid_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode, 
-                                         char *buf, int length);
+static void manage_squid_ntlmssp_request (struct ntlm_auth_state *state,
+                                       char *buf, int length);
 
-static void manage_client_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode, 
-                                          char *buf, int length);
+static void manage_client_ntlmssp_request (struct ntlm_auth_state *state,
+                                       char *buf, int length);
 
-static void manage_gss_spnego_request (enum stdio_helper_mode stdio_helper_mode, 
-                                      char *buf, int length);
+static void manage_gss_spnego_request (struct ntlm_auth_state *state,
+                                       char *buf, int length);
 
-static void manage_gss_spnego_client_request (enum stdio_helper_mode stdio_helper_mode, 
-                                             char *buf, int length);
+static void manage_gss_spnego_client_request (struct ntlm_auth_state *state,
+                                       char *buf, int length);
 
-static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode, 
-                                         char *buf, int length);
+static void manage_ntlm_server_1_request (struct ntlm_auth_state *state,
+                                       char *buf, int length);
 
-static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_mode, char *buf, int length);
+static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state,
+                                       char *buf, int length);
 
 static const struct {
        enum stdio_helper_mode mode;
@@ -123,7 +153,7 @@ static char winbind_separator(void)
                d_printf("winbind separator was NULL!\n");
                return *lp_winbind_separator();
        }
-       
+
        return sep;
 }
 
@@ -679,14 +709,9 @@ static NTSTATUS do_ccache_ntlm_auth(DATA_BLOB initial_msg, DATA_BLOB challenge_m
        return NT_STATUS_MORE_PROCESSING_REQUIRED;
 }
 
-static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode, 
-                                        char *buf, int length) 
+static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state,
+                                               char *buf, int length)
 {
-       static NTLMSSP_STATE *ntlmssp_state = NULL;
-       static char* want_feature_list = NULL;
-       static uint32 neg_flags = 0;
-       static bool have_session_key = False;
-       static DATA_BLOB session_key;
        DATA_BLOB request, reply;
        NTSTATUS nt_status;
 
@@ -699,8 +724,9 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
        if (strlen(buf) > 3) {
                if(strncmp(buf, "SF ", 3) == 0){
                        DEBUG(10, ("Setting flags to negotioate\n"));
-                       SAFE_FREE(want_feature_list);
-                       want_feature_list = SMB_STRNDUP(buf+3, strlen(buf)-3);
+                       TALLOC_FREE(state->want_feature_list);
+                       state->want_feature_list = talloc_strdup(state->mem_ctx,
+                                       buf+3);
                        x_fprintf(x_stdout, "OK\n");
                        return;
                }
@@ -710,9 +736,11 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
        }
 
        if ((strncmp(buf, "PW ", 3) == 0)) {
-               /* The calling application wants us to use a local password (rather than winbindd) */
+               /* The calling application wants us to use a local password
+                * (rather than winbindd) */
 
-               opt_password = SMB_STRNDUP((const char *)request.data, request.length);
+               opt_password = SMB_STRNDUP((const char *)request.data,
+                               request.length);
 
                if (opt_password == NULL) {
                        DEBUG(1, ("Out of memory\n"));
@@ -727,25 +755,33 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
        }
 
        if (strncmp(buf, "YR", 2) == 0) {
-               if (ntlmssp_state)
-                       ntlmssp_end(&ntlmssp_state);
+               if (state->ntlmssp_state)
+                       ntlmssp_end(&state->ntlmssp_state);
+               state->svr_state = SERVER_INITIAL;
        } else if (strncmp(buf, "KK", 2) == 0) {
-               
+               /* No special preprocessing required */
        } else if (strncmp(buf, "GF", 2) == 0) {
                DEBUG(10, ("Requested negotiated NTLMSSP flags\n"));
-               x_fprintf(x_stdout, "GF 0x%08lx\n", have_session_key?neg_flags:0l);
+
+               if (state->svr_state == SERVER_FINISHED) {
+                       x_fprintf(x_stdout, "GF 0x%08x\n", state->neg_flags);
+               }
+               else {
+                       x_fprintf(x_stdout, "BH\n");
+               }
                data_blob_free(&request);
                return;
        } else if (strncmp(buf, "GK", 2) == 0) {
                DEBUG(10, ("Requested NTLMSSP session key\n"));
-               if(have_session_key) {
-                       char *key64 = base64_encode_data_blob(session_key);
+               if(state->have_session_key) {
+                       char *key64 = base64_encode_data_blob(state->mem_ctx,
+                                       state->session_key);
                        x_fprintf(x_stdout, "GK %s\n", key64?key64:"<NULL>");
                        TALLOC_FREE(key64);
                } else {
                        x_fprintf(x_stdout, "BH\n");
                }
-                       
+
                data_blob_free(&request);
                return;
        } else {
@@ -754,65 +790,62 @@ static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mod
                return;
        }
 
-       if (!ntlmssp_state) {
-               if (!NT_STATUS_IS_OK(nt_status = ntlm_auth_start_ntlmssp_server(&ntlmssp_state))) {
+       if (!state->ntlmssp_state) {
+               nt_status = ntlm_auth_start_ntlmssp_server(
+                               &state->ntlmssp_state);
+               if (!NT_STATUS_IS_OK(nt_status)) {
                        x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
                        return;
                }
-               ntlmssp_want_feature_list(ntlmssp_state, want_feature_list);
+               ntlmssp_want_feature_list(state->ntlmssp_state,
+                               state->want_feature_list);
        }
 
        DEBUG(10, ("got NTLMSSP packet:\n"));
        dump_data(10, request.data, request.length);
 
-       nt_status = ntlmssp_update(ntlmssp_state, request, &reply);
-       
+       nt_status = ntlmssp_update(state->ntlmssp_state, request, &reply);
+
        if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               char *reply_base64 = base64_encode_data_blob(reply);
+               char *reply_base64 = base64_encode_data_blob(state->mem_ctx,
+                               reply);
                x_fprintf(x_stdout, "TT %s\n", reply_base64);
                TALLOC_FREE(reply_base64);
                data_blob_free(&reply);
+               state->svr_state = SERVER_CHALLENGE;
                DEBUG(10, ("NTLMSSP challenge\n"));
        } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
                x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
                DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status)));
 
-               ntlmssp_end(&ntlmssp_state);
+               ntlmssp_end(&state->ntlmssp_state);
        } else if (!NT_STATUS_IS_OK(nt_status)) {
                x_fprintf(x_stdout, "NA %s\n", nt_errstr(nt_status));
                DEBUG(10, ("NTLMSSP %s\n", nt_errstr(nt_status)));
        } else {
-               x_fprintf(x_stdout, "AF %s\n", (char *)ntlmssp_state->auth_context);
+               x_fprintf(x_stdout, "AF %s\n",
+                               (char *)state->ntlmssp_state->auth_context);
                DEBUG(10, ("NTLMSSP OK!\n"));
-               
-               if(have_session_key)
-                       data_blob_free(&session_key);
-               session_key = data_blob(ntlmssp_state->session_key.data, 
-                               ntlmssp_state->session_key.length);
-               neg_flags = ntlmssp_state->neg_flags;
-               have_session_key = True;
+
+               if(state->have_session_key)
+                       data_blob_free(&state->session_key);
+               state->session_key = data_blob(
+                               state->ntlmssp_state->session_key.data,
+                               state->ntlmssp_state->session_key.length);
+               state->neg_flags = state->ntlmssp_state->neg_flags;
+               state->have_session_key = true;
+               state->svr_state = SERVER_FINISHED;
        }
 
        data_blob_free(&request);
 }
 
-static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode, 
-                                        char *buf, int length) 
+static void manage_client_ntlmssp_request(struct ntlm_auth_state *state,
+                                               char *buf, int length)
 {
-       /* The statics here are *HORRIBLE* and this entire concept
-          needs to be rewritten. Essentially it's using these statics
-          as the state in a state machine. BLEEEGH ! JRA. */
-
-       static NTLMSSP_STATE *ntlmssp_state = NULL;
-       static DATA_BLOB initial_message;
-       static char* want_feature_list = NULL;
-       static uint32 neg_flags = 0;
-       static bool have_session_key = False;
-       static DATA_BLOB session_key;
        DATA_BLOB request, reply;
        NTSTATUS nt_status;
-       bool first = False;
-       
+
        if (!opt_username || !*opt_username) {
                x_fprintf(x_stderr, "username must be specified!\n\n");
                exit(1);
@@ -827,8 +860,9 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
        if (strlen(buf) > 3) {
                if(strncmp(buf, "SF ", 3) == 0) {
                        DEBUG(10, ("Looking for flags to negotiate\n"));
-                       SAFE_FREE(want_feature_list);
-                       want_feature_list = SMB_STRNDUP(buf+3, strlen(buf)-3);
+                       talloc_free(state->want_feature_list);
+                       state->want_feature_list = talloc_strdup(state->mem_ctx,
+                                       buf+3);
                        x_fprintf(x_stdout, "OK\n");
                        return;
                }
@@ -840,7 +874,8 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
        if (strncmp(buf, "PW ", 3) == 0) {
                /* We asked for a password and obviously got it :-) */
 
-               opt_password = SMB_STRNDUP((const char *)request.data, request.length);
+               opt_password = SMB_STRNDUP((const char *)request.data,
+                               request.length);
 
                if (opt_password == NULL) {
                        DEBUG(1, ("Out of memory\n"));
@@ -854,8 +889,8 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
                return;
        }
 
-       if (!ntlmssp_state && use_cached_creds) {
-               /* check whether credentials are usable. */
+       if (!state->ntlmssp_state && use_cached_creds) {
+               /* check whether cached credentials are usable. */
                DATA_BLOB empty_blob = data_blob_null;
 
                nt_status = do_ccache_ntlm_auth(empty_blob, empty_blob, NULL);
@@ -866,30 +901,39 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
        }
 
        if (opt_password == NULL && !use_cached_creds) {
-               
                /* Request a password from the calling process.  After
-                  sending it, the calling process should retry asking for the negotiate. */
-               
+                  sending it, the calling process should retry asking for the
+                  negotiate. */
+
                DEBUG(10, ("Requesting password\n"));
                x_fprintf(x_stdout, "PW\n");
                return;
        }
 
        if (strncmp(buf, "YR", 2) == 0) {
-               if (ntlmssp_state)
-                       ntlmssp_end(&ntlmssp_state);
+               if (state->ntlmssp_state)
+                       ntlmssp_end(&state->ntlmssp_state);
+               state->cli_state = CLIENT_INITIAL;
        } else if (strncmp(buf, "TT", 2) == 0) {
-               
+               /* No special preprocessing required */
        } else if (strncmp(buf, "GF", 2) == 0) {
                DEBUG(10, ("Requested negotiated NTLMSSP flags\n"));
-               x_fprintf(x_stdout, "GF 0x%08lx\n", have_session_key?neg_flags:0l);
+
+               if(state->cli_state == CLIENT_FINISHED) {
+                       x_fprintf(x_stdout, "GF 0x%08x\n", state->neg_flags);
+               }
+               else {
+                       x_fprintf(x_stdout, "BH\n");
+               }
+
                data_blob_free(&request);
                return;
        } else if (strncmp(buf, "GK", 2) == 0 ) {
                DEBUG(10, ("Requested session key\n"));
 
-               if(have_session_key) {
-                       char *key64 = base64_encode_data_blob(session_key);
+               if(state->cli_state == CLIENT_FINISHED) {
+                       char *key64 = base64_encode_data_blob(state->mem_ctx,
+                                       state->session_key);
                        x_fprintf(x_stdout, "GK %s\n", key64?key64:"<NULL>");
                        TALLOC_FREE(key64);
                }
@@ -905,67 +949,75 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
                return;
        }
 
-       if (!ntlmssp_state) {
-               if (!NT_STATUS_IS_OK(nt_status = ntlm_auth_start_ntlmssp_client(&ntlmssp_state))) {
+       if (!state->ntlmssp_state) {
+               nt_status = ntlm_auth_start_ntlmssp_client(
+                               &state->ntlmssp_state);
+               if (!NT_STATUS_IS_OK(nt_status)) {
                        x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
                        return;
                }
-               ntlmssp_want_feature_list(ntlmssp_state, want_feature_list);
-               first = True;
-               initial_message = data_blob_null;
+               ntlmssp_want_feature_list(state->ntlmssp_state,
+                               state->want_feature_list);
+               state->initial_message = data_blob_null;
        }
 
        DEBUG(10, ("got NTLMSSP packet:\n"));
        dump_data(10, request.data, request.length);
 
-       if (use_cached_creds && !opt_password && !first) {
-               nt_status = do_ccache_ntlm_auth(initial_message, request, &reply);
+       if (use_cached_creds && !opt_password &&
+                       (state->cli_state == CLIENT_RESPONSE)) {
+               nt_status = do_ccache_ntlm_auth(state->initial_message, request,
+                               &reply);
        } else {
-               nt_status = ntlmssp_update(ntlmssp_state, request, &reply);
+               nt_status = ntlmssp_update(state->ntlmssp_state, request,
+                               &reply);
        }
-       
+
        if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               char *reply_base64 = base64_encode_data_blob(reply);
-               if (first) {
+               char *reply_base64 = base64_encode_data_blob(state->mem_ctx,
+                               reply);
+               if (state->cli_state == CLIENT_INITIAL) {
                        x_fprintf(x_stdout, "YR %s\n", reply_base64);
-               } else { 
-                       x_fprintf(x_stdout, "KK %s\n", reply_base64);
-               }
-               TALLOC_FREE(reply_base64);
-               if (first) {
-                       initial_message = reply;
+                       state->initial_message = reply;
+                       state->cli_state = CLIENT_RESPONSE;
                } else {
+                       x_fprintf(x_stdout, "KK %s\n", reply_base64);
                        data_blob_free(&reply);
                }
+               TALLOC_FREE(reply_base64);
                DEBUG(10, ("NTLMSSP challenge\n"));
        } else if (NT_STATUS_IS_OK(nt_status)) {
-               char *reply_base64 = base64_encode_data_blob(reply);
+               char *reply_base64 = base64_encode_data_blob(talloc_tos(),
+                               reply);
                x_fprintf(x_stdout, "AF %s\n", reply_base64);
                TALLOC_FREE(reply_base64);
 
-               if(have_session_key)
-                       data_blob_free(&session_key);
+               if(state->have_session_key)
+                       data_blob_free(&state->session_key);
 
-               session_key = data_blob(ntlmssp_state->session_key.data, 
-                               ntlmssp_state->session_key.length);
-               neg_flags = ntlmssp_state->neg_flags;
-               have_session_key = True;
+               state->session_key = data_blob(
+                               state->ntlmssp_state->session_key.data,
+                               state->ntlmssp_state->session_key.length);
+               state->neg_flags = state->ntlmssp_state->neg_flags;
+               state->have_session_key = true;
 
                DEBUG(10, ("NTLMSSP OK!\n"));
-               if (ntlmssp_state)
-                       ntlmssp_end(&ntlmssp_state);
+               state->cli_state = CLIENT_FINISHED;
+               if (state->ntlmssp_state)
+                       ntlmssp_end(&state->ntlmssp_state);
        } else {
                x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status));
                DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status)));
-               if (ntlmssp_state)
-                       ntlmssp_end(&ntlmssp_state);
+               state->cli_state = CLIENT_ERROR;
+               if (state->ntlmssp_state)
+                       ntlmssp_end(&state->ntlmssp_state);
        }
 
        data_blob_free(&request);
 }
 
-static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode, 
-                                      char *buf, int length) 
+static void manage_squid_basic_request(struct ntlm_auth_state *state,
+                                       char *buf, int length)
 {
        char *user, *pass;      
        user=buf;
@@ -979,7 +1031,7 @@ static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode,
        *pass='\0';
        pass++;
        
-       if (stdio_helper_mode == SQUID_2_5_BASIC) {
+       if (state->helper_mode == SQUID_2_5_BASIC) {
                rfc1738_unescape(user);
                rfc1738_unescape(pass);
        }
@@ -1039,7 +1091,7 @@ static void offer_gss_spnego_mechs(void) {
                return;
        }
 
-       reply_base64 = base64_encode_data_blob(token);
+       reply_base64 = base64_encode_data_blob(talloc_tos(), token);
        x_fprintf(x_stdout, "TT %s *\n", reply_base64);
 
        TALLOC_FREE(reply_base64);
@@ -1048,8 +1100,8 @@ static void offer_gss_spnego_mechs(void) {
        return;
 }
 
-static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, 
-                                     char *buf, int length) 
+static void manage_gss_spnego_request(struct ntlm_auth_state *state,
+                                       char *buf, int length)
 {
        static NTLMSSP_STATE *ntlmssp_state = NULL;
        SPNEGO_DATA request, response;
@@ -1276,7 +1328,7 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
                return;
        }
 
-       reply_base64 = base64_encode_data_blob(token);
+       reply_base64 = base64_encode_data_blob(talloc_tos(), token);
 
        x_fprintf(x_stdout, "%s %s %s\n",
                  reply_code, reply_base64, reply_argument);
@@ -1343,7 +1395,7 @@ static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego)
        write_spnego_data(&to_server, &spnego);
        data_blob_free(&spnego.negTokenInit.mechToken);
 
-       to_server_base64 = base64_encode_data_blob(to_server);
+       to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server);
        data_blob_free(&to_server);
        x_fprintf(x_stdout, "KK %s\n", to_server_base64);
        TALLOC_FREE(to_server_base64);
@@ -1401,7 +1453,7 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego)
        write_spnego_data(&to_server, &spnego);
        data_blob_free(&request);
 
-       to_server_base64 = base64_encode_data_blob(to_server);
+       to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server);
        data_blob_free(&to_server);
        x_fprintf(x_stdout, "KK %s\n", to_server_base64);
        TALLOC_FREE(to_server_base64);
@@ -1490,7 +1542,7 @@ static bool manage_client_krb5_init(SPNEGO_DATA spnego)
                return False;
        }
 
-       reply_base64 = base64_encode_data_blob(to_server);
+       reply_base64 = base64_encode_data_blob(talloc_tos(), to_server);
        x_fprintf(x_stdout, "KK %s *\n", reply_base64);
 
        TALLOC_FREE(reply_base64);
@@ -1522,8 +1574,8 @@ static void manage_client_krb5_targ(SPNEGO_DATA spnego)
 
 #endif
 
-static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper_mode, 
-                                            char *buf, int length) 
+static void manage_gss_spnego_client_request(struct ntlm_auth_state *state,
+                                               char *buf, int length)
 {
        DATA_BLOB request;
        SPNEGO_DATA spnego;
@@ -1660,8 +1712,8 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper
        return;
 }
 
-static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mode, 
-                                        char *buf, int length) 
+static void manage_ntlm_server_1_request(struct ntlm_auth_state *state,
+                                               char *buf, int length)
 {
        char *request, *parameter;      
        static DATA_BLOB challenge;
@@ -1853,7 +1905,8 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod
        }
 }
 
-static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_mode, char *buf, int length)
+static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state,
+                                                       char *buf, int length)
 {
        char *request, *parameter;      
        static DATA_BLOB new_nt_pswd;
@@ -2063,57 +2116,93 @@ static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_
        }
 }
 
-static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helper_function fn) 
+static void manage_squid_request(struct ntlm_auth_state *state,
+               stdio_helper_function fn)
 {
-       char buf[SQUID_BUFFER_SIZE+1];
-       int length;
+       char *buf;
+       char tmp[INITIAL_BUFFER_SIZE+1];
+       int length, buf_size = 0;
        char *c;
-       static bool err;
 
-       /* this is not a typo - x_fgets doesn't work too well under squid */
-       if (fgets(buf, sizeof(buf)-1, stdin) == NULL) {
-               if (ferror(stdin)) {
-                       DEBUG(1, ("fgets() failed! dying..... errno=%d (%s)\n", ferror(stdin),
-                                 strerror(ferror(stdin))));
-                       
-                       exit(1);    /* BIIG buffer */
-               }
-               exit(0);
-       }
-    
-       c=(char *)memchr(buf,'\n',sizeof(buf)-1);
-       if (c) {
-               *c = '\0';
-               length = c-buf;
-       } else {
-               err = 1;
-               return;
-       }
-       if (err) {
-               DEBUG(2, ("Oversized message\n"));
+       buf = talloc_strdup(state->mem_ctx, "");
+       if (!buf) {
+               DEBUG(0, ("Failed to allocate input buffer.\n"));
                x_fprintf(x_stderr, "ERR\n");
-               err = 0;
-               return;
+               exit(1);
        }
 
+       do {
+
+               /* this is not a typo - x_fgets doesn't work too well under
+                * squid */
+               if (fgets(tmp, sizeof(tmp)-1, stdin) == NULL) {
+                       if (ferror(stdin)) {
+                               DEBUG(1, ("fgets() failed! dying..... errno=%d "
+                                         "(%s)\n", ferror(stdin),
+                                         strerror(ferror(stdin))));
+
+                               exit(1);
+                       }
+                       exit(0);
+               }
+
+               buf = talloc_strdup_append_buffer(buf, tmp);
+               buf_size += INITIAL_BUFFER_SIZE;
+
+               if (buf_size > MAX_BUFFER_SIZE) {
+                       DEBUG(2, ("Oversized message\n"));
+                       x_fprintf(x_stderr, "ERR\n");
+                       talloc_free(buf);
+                       return;
+               }
+
+               c = strchr(buf, '\n');
+       } while (c == NULL);
+
+       *c = '\0';
+       length = c-buf;
+
        DEBUG(10, ("Got '%s' from squid (length: %d).\n",buf,length));
 
        if (buf[0] == '\0') {
                DEBUG(2, ("Invalid Request\n"));
                x_fprintf(x_stderr, "ERR\n");
+               talloc_free(buf);
                return;
        }
-       
-       fn(helper_mode, buf, length);
+
+       fn(state, buf, length);
+       talloc_free(buf);
 }
 
 
 static void squid_stream(enum stdio_helper_mode stdio_mode, stdio_helper_function fn) {
+       TALLOC_CTX *mem_ctx;
+       struct ntlm_auth_state *state;
+
        /* initialize FDescs */
        x_setbuf(x_stdout, NULL);
        x_setbuf(x_stderr, NULL);
+
+       mem_ctx = talloc_init("ntlm_auth");
+       if (!mem_ctx) {
+               DEBUG(0, ("squid_stream: Failed to create talloc context\n"));
+               x_fprintf(x_stderr, "ERR\n");
+               exit(1);
+       }
+
+       state = talloc_zero(mem_ctx, struct ntlm_auth_state);
+       if (!state) {
+               DEBUG(0, ("squid_stream: Failed to talloc ntlm_auth_state\n"));
+               x_fprintf(x_stderr, "ERR\n");
+               exit(1);
+       }
+
+       state->mem_ctx = mem_ctx;
+       state->helper_mode = stdio_mode;
+
        while(1) {
-               manage_squid_request(stdio_mode, fn);
+               manage_squid_request(state, fn);
        }
 }
 
index 07a6fbcf544cc64106eaf2d413946392f04bded9..c6233b0869485c66353335a68c934608759c6100 100644 (file)
@@ -164,7 +164,9 @@ void cgi_load_variables(void)
        open("/dev/null", O_RDWR);
 
        if ((s=query_string) || (s=getenv("QUERY_STRING"))) {
-               for (tok=strtok(s,"&;");tok;tok=strtok(NULL,"&;")) {
+               char *saveptr;
+               for (tok=strtok_r(s, "&;", &saveptr); tok;
+                    tok=strtok_r(NULL, "&;", &saveptr)) {
                        p = strchr_m(tok,'=');
                        if (!p) continue;
                        
index 908228717e686e901783d5090de55a0d3caebfb1..dbc664da8c76fee5e0b982d6eeb25f95a911bccd 100644 (file)
@@ -613,7 +613,13 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
                                                     DS_RETURN_DNS_NAME,
                                                     &domain_info);
                if (W_ERROR_IS_OK(werr)) {
-                       fstrcpy(tmp, domain_info->domain_controller_name);
+                       tmp = talloc_strdup(
+                               mem_ctx, domain_info->domain_controller_name);
+                       if (tmp == NULL) {
+                               DEBUG(0, ("talloc_strdup failed\n"));
+                               talloc_destroy(mem_ctx);
+                               return false;
+                       }
                        if (strlen(domain->alt_name) == 0) {
                                fstrcpy(domain->alt_name,
                                        domain_info->domain_name);
@@ -635,11 +641,10 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
        /* And restore our original timeout. */
        cli_set_timeout(netlogon_pipe->cli, orig_timeout);
 
-       talloc_destroy(mem_ctx);
-
        if (!W_ERROR_IS_OK(werr)) {
                DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
                           dos_errstr(werr)));
+               talloc_destroy(mem_ctx);
                return False;
        }
 
@@ -654,6 +659,8 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
 
        fstrcpy(dcname, p);
 
+       talloc_destroy(mem_ctx);
+
        DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
 
        if (!resolve_name(dcname, dc_ss, 0x20)) {
@@ -687,11 +694,15 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
 
        /* this is at least correct when domain is our domain,
         * which is the only case, when this is currently used: */
-       if ((machine_krb5_principal != NULL) &&
-           (asprintf(machine_krb5_principal, "%s$@%s", account_name,
-                     domain->alt_name) == -1))
+       if (machine_krb5_principal != NULL)
        {
-               return NT_STATUS_NO_MEMORY;
+               if (asprintf(machine_krb5_principal, "%s$@%s",
+                            account_name, domain->alt_name) == -1)
+               {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               strupper_m(*machine_krb5_principal);
        }
 
        return NT_STATUS_OK;
@@ -2291,7 +2302,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
        struct winbindd_cm_conn *conn;
        NTSTATUS result;
 
-       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+       uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
        uint8  mach_pwd[16];
        uint32  sec_chan_type;
        const char *account_name;
index 778886d8e28b87767f2d0eb63082563bc324f912..e21524689bbc5eae4702d66afbe668620b4a9518 100644 (file)
@@ -480,7 +480,6 @@ void winbind_child_died(pid_t pid)
        child->event.fd = 0;
        child->event.flags = 0;
        child->pid = 0;
-       SAFE_FREE(child->logfilename);
 
        schedule_async_request(child);
 }
index 0c75cb17a964fcda6599e69c67971f29b5d02908..98c9ae2ffe4d2fef0eb113d6f36967b8a0bedbe1 100644 (file)
@@ -31,8 +31,6 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
                                    struct winbindd_cli_state *state,
                                    NET_USER_INFO_3 *info3)
 {
-       fstring str_sid;
-
        state->response.data.auth.info3.logon_time =
                nt_time_to_unix(info3->logon_time);
        state->response.data.auth.info3.logoff_time =
@@ -51,8 +49,7 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
 
        state->response.data.auth.info3.user_rid = info3->user_rid;
        state->response.data.auth.info3.group_rid = info3->group_rid;
-       sid_to_fstring(str_sid, &(info3->dom_sid.sid));
-       fstrcpy(state->response.data.auth.info3.dom_sid, str_sid);
+       sid_to_fstring(state->response.data.auth.info3.dom_sid, &(info3->dom_sid.sid));
 
        state->response.data.auth.info3.num_groups = info3->num_groups;
        state->response.data.auth.info3.user_flgs = info3->user_flgs;
index dc48fdef8b1816ac6b44858a9ecc184b2f531c4e..038105333138e739c137b2c7f510f54c3777b594 100644 (file)
@@ -41,7 +41,7 @@ extern struct winbindd_methods passdb_methods;
    individual winbindd_domain structures cannot be made.  Keep a copy of
    the domain name instead. */
 
-static struct winbindd_domain *_domain_list;
+static struct winbindd_domain *_domain_list = NULL;
 
 /**
    When was the last scan of trusted domains done?